diff --git a/.gitignore b/.gitignore
index b4526ca7..2bb37b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -380,7 +380,7 @@
 /third_party/robolectric/lib
 /third_party/safe_browsing/testing
 /third_party/scons-2.0.1
-/third_party/sfntly/cpp
+/third_party/sfntly/src
 /third_party/skia
 /third_party/smhasher/src
 /third_party/snappy/src
diff --git a/BUILD.gn b/BUILD.gn
index 06f6d0f..e186437c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -160,6 +160,7 @@
       "//tools/gn",
       "//tools/gn:gn_unittests",
       "//tools/gn:generate_test_gn_data",
+      "//tools/perf/clear_system_cache",
       "//tools/telemetry:bitmaptools($host_toolchain)",
       "//ui/accessibility:accessibility_unittests",
       "//ui/app_list:app_list_unittests",
@@ -218,9 +219,6 @@
       "//base/android/linker:chromium_android_linker",
       "//build/android/gyp/test:hello_world",
       "//build/android/rezip",
-      "//chrome/android:chrome_public_apk",
-      "//chrome/android:chrome_public_test_apk",
-      "//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk",
       "//third_party/errorprone:chromium_errorprone",
       "//tools/android:android_tools",
       "//tools/imagediff($host_toolchain)",
@@ -306,6 +304,14 @@
       "//url:url_unittests",
     ]
 
+    if (!is_chromecast) {
+      deps += [
+        "//chrome/android:chrome_public_apk",
+        "//chrome/android:chrome_public_test_apk",
+        "//chrome/test/chromedriver/test/webview_shell:chromedriver_webview_shell_apk",
+      ]
+    }
+
     if (has_chrome_android_internal) {
       deps += [ "//clank" ]  # TODO(GYP) ??
     }
@@ -468,7 +474,6 @@
       "//sync/tools:sync_listen_notifications",
       "//testing/gmock:gmock_main",
       "//third_party/mojo/src/mojo/edk/test:mojo_public_system_perftests",
-      "//tools/perf/clear_system_cache",
       "//ui/keyboard:keyboard_unittests",
       "//ui/message_center:message_center_unittests",
       "//ui/snapshot:snapshot_unittests",
@@ -941,3 +946,47 @@
     ]
   }
 }
+
+group("chromium_builder_perf") {
+  testonly = true
+
+  # TODO(GYP): Make this target work on the mac.
+  if (!is_ios && !is_android && !is_chromecast && !is_mac) {
+    deps = [
+      "//cc:cc_perftests",
+      "//chrome",
+      "//chrome/test:load_library_perf_tests",
+      "//chrome/test:sync_performance_tests",
+      "//gpu:gpu_perftests",
+      "//media:media_perftests",
+      "//media/midi:midi_unittests",
+      "//tools/telemetry:bitmaptools",
+    ]
+
+    if (!is_chromeos) {
+      deps += [ "//chrome/test:performance_browser_tests" ]
+    }
+    if (is_linux && !is_chromeos) {
+      deps += [ "//chrome:linux_symbols" ]
+
+      if (!is_chromeos) {
+        deps += [ "//tools/perf/clear_system_cache" ]
+      }
+    }
+
+    if (is_win) {
+      deps += [
+        "//content/shell:crash_service",
+        # "//gpu:angle_perftests", TODO(GYP): crbug.com/537008
+      ]
+
+      if (target_cpu == "x86") {
+        deps += [
+          # "//content/shell:crash_service_win64", TODO(GYP): crbug.com/537009
+        ]
+      }
+    } else {
+      deps += [ "//breakpad:minidump_stackwalk" ]
+    }
+  }
+}
diff --git a/DEPS b/DEPS
index 3a2221a9..f70e2ac 100644
--- a/DEPS
+++ b/DEPS
@@ -32,13 +32,22 @@
   # If you do not know, use the full path while defining your new deps entry.
   'googlecode_url': 'http://%s.googlecode.com/svn',
   'chromium_git': 'https://chromium.googlesource.com',
-  'libvpx_revision': '70db2235b7e389f4d1b178320ebce76280c127af',
-  'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
-  'skia_revision': 'c9e190ddac3d193e89e580ea3819a55c28f15e61',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling libvpx
+  # and whatever else without interference from each other.
+  'libvpx_revision': 'b33794b9132c8c1722206d6676c37177ccbaef2e',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling sfntly
+  # and whatever else without interference from each other.
+  'sfntly_revision': '130f832eddf98467e6578b548cb74ce17d04a26d',
+  # Three lines of non-changing comments so that
+  # the commit queue can handle CLs rolling Skia
+  # and whatever else without interference from each other.
+  'skia_revision': '3a7701c0101386ba05acdde6f911be0c2696f317',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '40d687146a2c35b1328f21ea5f3b95b2be4dda52',
+  'v8_revision': '5d866a56e5778c1094d343c93dfbbe323772562d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -50,19 +59,19 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '8d89c1b15f80323b54b3305b2be7b26686fd5611',
+  'buildtools_revision': '0c88009d5c50b9f21b6f8849db08abfb9eb29f1e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '6c5afa68ed4e21f9d0bfd1ecc01e824d946c5485',
+  'pdfium_revision': '3e144b8c23d7c52ed36329e87f0cb01f38ec1ed7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
-  'openmax_dl_revision': '2eb98d819bed3082071a09268b886bc4496c6fb5',
+  'openmax_dl_revision': '37b900ccc45cfab71faf4fd332df15369766b94c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '4c60d356a926b68ac20e8090755799e1525874f0',
+  'boringssl_revision': '8c9b8783e26c3fbfc6d111017796256df6ea93dd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nss
   # and whatever else without interference from each other.
@@ -157,8 +166,8 @@
   'src/native_client':
    Var('chromium_git') + '/native_client/src/native_client.git' + '@' + Var('nacl_revision'),
 
-  'src/third_party/sfntly/cpp/src':
-    Var('chromium_git') + '/external/sfntly/cpp/src.git' + '@' +  Var('sfntly_revision'),
+  'src/third_party/sfntly/src':
+   Var('chromium_git') + '/external/github.com/googlei18n/sfntly.git' + '@' + Var('sfntly_revision'),
 
   'src/third_party/skia':
    Var('chromium_git') + '/skia.git' + '@' +  Var('skia_revision'),
@@ -185,13 +194,13 @@
    Var('chromium_git') + '/chromium/deps/libvpx.git' + '@' +  Var('libvpx_revision'),
 
   'src/third_party/libvpx_new/source/libvpx':
-   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '90a109f0eef8bfaaa4869cf7b2873dac5076b582',
+   Var('chromium_git') + '/webm/libvpx.git' + '@' +  '7d28d12ef34f6cbb6b1e18f3b23b71392fd3ddf5',
 
   'src/third_party/ffmpeg':
-   Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'dad5c1808dd2fafaa5ae43b8f7b1a2fe98bd06dd',
+   Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '45d76d0e7ad32cd3f17b52c7956abb2e33e01ad1',
 
   'src/third_party/libjingle/source/talk':
-    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'e1e22ac3d7bd583fd61781800409122a245a2aee', # commit position 10081
+    Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'c1f29d891d2d439060eff868e34935f69d454cca', # commit position 10116
 
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215
@@ -215,7 +224,7 @@
    Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'a6ae030b86e4ab27227ac43ed7d7d976214ffeed', # commit position 10081
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'd2b20e56b1e63d0d2fce3f9581753d91487744f6', # commit position 10117
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
@@ -224,7 +233,7 @@
     Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '62c49dc811f078e78ed76bfd7c6358c8b7513a14', # from version 1487
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'd039ad6e9b49ce61afcb22968eb0d3771f019abc', # from version 1495
 
   'src/third_party/smhasher/src':
     Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f',
@@ -388,7 +397,7 @@
 
     # For Linux and Chromium OS.
     'src/third_party/cros_system_api':
-     Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '0b175578c8150c7ee0e7e4fd6d4dc7480979e248',
+     Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '4a77577ef89e8a3f44d6604dc3a552e33bfa79e3',
 
     # Note that this is different from Android's freetype repo.
     'src/third_party/freetype2/src':
@@ -589,7 +598,7 @@
   },
   {
     # Update LASTCHANGE.blink.
-    'name': 'lastchange',
+    'name': 'lastchange_blink',
     'pattern': '.',
     'action': ['python', 'src/build/util/lastchange.py',
                '--git-hash-only',
@@ -735,7 +744,7 @@
     'action': ['python',
                'src/build/get_syzygy_binaries.py',
                '--output-dir=src/third_party/syzygy/binaries',
-               '--revision=8341560b55cebb58351b56bcb809bbbe22ca5398',
+               '--revision=a8456d9248a126881dcfb8707ca7dcdae56e1ac7',
                '--overwrite',
     ],
   },
@@ -811,3 +820,4 @@
   },
 ]
 
+
diff --git a/WATCHLISTS b/WATCHLISTS
index a001d47..504eef66 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1278,6 +1278,7 @@
     'clang_update': ['ukai+watch@chromium.org',
                      'dmikurube+clang@chromium.org',
                      'eugenis+clang@chromium.org',
+                     'yunlian@chromium.org',
                      'glider+clang@chromium.org'],
     'clipboard': ['dcheng@chromium.org'],
     'closure': ['dbeam+watch-closure@chromium.org',
@@ -1562,14 +1563,16 @@
                                  'jbroman@chromium.org',
                                  'dongseong.hwang@intel.com',
                                  'drott+blinkwatch@chromium.org',
-                                 'junov@chromium.org' ],
+                                 'junov@chromium.org',
+                                 'blink-reviews-platform-graphics@chromium.org' ],
     'blink_heap': [ 'ager@chromium.org',
                     'haraken@chromium.org',
                     'kouhei+heap@chromium.org',
                     'oilpan-reviews@chromium.org' ],
     'blink_html': [ 'dglazkov+blink@chromium.org',
                     'blink-reviews-html@chromium.org' ],
-    'blink_public_api': [ 'dglazkov+blink@chromium.org' ],
+    'blink_public_api': [ 'dglazkov+blink@chromium.org',
+                          'blink-reviews-api@chromium.org' ],
     'blink_indexed_db': ['dgrogan@chromium.org',
                          'jsbell+idb@chromium.org',
                          'cmumford@chromium.org'],
diff --git a/android_webview/android_webview_shell.gyp b/android_webview/android_webview_shell.gyp
index a5d898f..8704b92 100644
--- a/android_webview/android_webview_shell.gyp
+++ b/android_webview/android_webview_shell.gyp
@@ -8,6 +8,8 @@
       'type': 'none',
       'dependencies': [
         '../base/base.gyp:base_java_test_support',
+        '../testing/android/on_device_instrumentation.gyp:broker_java',
+        '../testing/android/on_device_instrumentation.gyp:require_driver_apk',
       ],
       'variables': {
         'apk_name': 'AndroidWebViewShell',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 759c844..ab14d49 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -25,10 +25,13 @@
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "components/cdm/browser/cdm_message_filter_android.h"
+#include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "content/public/browser/access_token_store.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -487,6 +490,22 @@
       content::WebContents::FromRenderViewHost(rvh), web_prefs);
 }
 
+ScopedVector<content::NavigationThrottle>
+AwContentBrowserClient::CreateThrottlesForNavigation(
+    content::NavigationHandle* navigation_handle) {
+  ScopedVector<content::NavigationThrottle> throttles;
+  if (navigation_handle->IsInMainFrame() ||
+      (!navigation_handle->GetURL().SchemeIs(url::kHttpScheme) &&
+       !navigation_handle->GetURL().SchemeIs(url::kHttpsScheme) &&
+       !navigation_handle->GetURL().SchemeIs(url::kAboutScheme))) {
+    throttles.push_back(
+        navigation_interception::InterceptNavigationDelegate::CreateThrottleFor(
+            navigation_handle)
+            .Pass());
+  }
+  return throttles.Pass();
+}
+
 #if defined(VIDEO_HOLE)
 content::ExternalVideoSurfaceContainer*
 AwContentBrowserClient::OverrideCreateExternalVideoSurfaceContainer(
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index d811cf2..a3a814e 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -142,6 +142,8 @@
       std::map<int, base::MemoryMappedFile::Region>* regions) override;
   void OverrideWebkitPrefs(content::RenderViewHost* rvh,
                            content::WebPreferences* web_prefs) override;
+  ScopedVector<content::NavigationThrottle> CreateThrottlesForNavigation(
+      content::NavigationHandle* navigation_handle) override;
 #if defined(VIDEO_HOLE)
   content::ExternalVideoSurfaceContainer*
   OverrideCreateExternalVideoSurfaceContainer(
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 07dae10..556feef 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -85,10 +85,12 @@
 
 BrowserViewRenderer::BrowserViewRenderer(
     BrowserViewRendererClient* client,
-    const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
+    const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
+    bool disable_page_visibility)
     : client_(client),
       shared_renderer_state_(ui_task_runner, this),
       ui_task_runner_(ui_task_runner),
+      disable_page_visibility_(disable_page_visibility),
       compositor_(NULL),
       is_paused_(false),
       view_visible_(false),
@@ -444,6 +446,13 @@
   return view_visible_ && (!attached_to_window_ || window_visible_);
 }
 
+bool BrowserViewRenderer::IsClientVisible() const {
+  if (disable_page_visibility_)
+    return !is_paused_;
+
+  return !is_paused_ && IsVisible();
+}
+
 gfx::Rect BrowserViewRenderer::GetScreenRect() const {
   return gfx::Rect(client_->GetLocationOnScreen(), size_);
 }
@@ -716,9 +725,13 @@
 }
 
 void BrowserViewRenderer::UpdateCompositorIsActive() {
-  if (compositor_)
-    compositor_->SetIsActive(!is_paused_ &&
-                             (!attached_to_window_ || window_visible_));
+  if (compositor_) {
+    if (disable_page_visibility_)
+      compositor_->SetIsActive(!is_paused_ &&
+                               (!attached_to_window_ || window_visible_));
+    else
+      compositor_->SetIsActive(IsClientVisible());
+  }
 }
 
 std::string BrowserViewRenderer::ToString() const {
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 97737aa..b4205c52 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -39,7 +39,8 @@
 
   BrowserViewRenderer(
       BrowserViewRendererClient* client,
-      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
+      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
+      bool disable_page_visibility);
 
   ~BrowserViewRenderer() override;
 
@@ -93,6 +94,7 @@
   gfx::Size size() const { return size_; }
   void ReleaseHardware();
 
+  bool IsClientVisible() const;
   void TrimMemory(const int level, const bool visible);
 
   // SynchronousCompositorClient overrides.
@@ -156,6 +158,7 @@
   BrowserViewRendererClient* client_;
   SharedRendererState shared_renderer_state_;
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+  bool disable_page_visibility_;
 
   content::SynchronousCompositor* compositor_;
 
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index 5979a1e..ff14f10 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -68,6 +68,7 @@
   // Reset draw constraints.
   shared_renderer_state_->PostExternalDrawConstraintsToChildCompositorOnRT(
       ParentCompositorDrawConstraints());
+  ReturnResourcesInChildFrame();
 }
 
 void HardwareRenderer::CommitFrame() {
@@ -77,6 +78,8 @@
       shared_renderer_state_->PassCompositorFrameOnRT();
   if (!child_frame.get())
     return;
+
+  ReturnResourcesInChildFrame();
   child_frame_ = child_frame.Pass();
   DCHECK(child_frame_->frame.get());
   DCHECK(!child_frame_->frame->gl_frame_data);
@@ -206,4 +209,16 @@
   gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);
 }
 
+void HardwareRenderer::ReturnResourcesInChildFrame() {
+  if (child_frame_.get() && child_frame_->frame.get()) {
+    cc::ReturnedResourceArray resources_to_return;
+    cc::TransferableResource::ReturnResources(
+        child_frame_->frame->delegated_frame_data->resource_list,
+        &resources_to_return);
+
+    ReturnResources(resources_to_return);
+  }
+  child_frame_.reset();
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h
index 16d01f66..fe7aaef 100644
--- a/android_webview/browser/hardware_renderer.h
+++ b/android_webview/browser/hardware_renderer.h
@@ -48,6 +48,8 @@
   // cc::SurfaceFactoryClient implementation.
   void ReturnResources(const cc::ReturnedResourceArray& resources) override;
 
+  void ReturnResourcesInChildFrame();
+
   SharedRendererState* shared_renderer_state_;
 
   typedef void* EGLContext;
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index 1d9e5854..ed7c52b 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -221,14 +221,6 @@
   throttles->push_back(new IoThreadClientThrottle(
       request_info->GetChildID(), request_info->GetRenderFrameID(), request));
 
-  if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME ||
-      (resource_type == content::RESOURCE_TYPE_SUB_FRAME &&
-       !request->url().SchemeIs(url::kHttpScheme) &&
-       !request->url().SchemeIs(url::kHttpsScheme) &&
-       !request->url().SchemeIs(url::kAboutScheme))) {
-    throttles->push_back(InterceptNavigationDelegate::CreateThrottleFor(
-        request));
-  }
   if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
     InterceptNavigationDelegate::UpdateUserGestureCarryoverInfo(request);
 }
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 26799b8..6b8e57e3 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -23,8 +23,8 @@
 
 void RenderingTest::SetUpTestHarness() {
   DCHECK(!browser_view_renderer_.get());
-  browser_view_renderer_.reset(
-      new BrowserViewRenderer(this, base::ThreadTaskRunnerHandle::Get()));
+  browser_view_renderer_.reset(new BrowserViewRenderer(
+      this, base::ThreadTaskRunnerHandle::Get(), false));
   InitializeCompositor();
   Attach();
 }
diff --git a/android_webview/common/aw_content_client.cc b/android_webview/common/aw_content_client.cc
index b4400ae..2e95f03 100644
--- a/android_webview/common/aw_content_client.cc
+++ b/android_webview/common/aw_content_client.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/user_agent.h"
+#include "gpu/config/gpu_info.h"
 #include "ipc/ipc_message.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -66,4 +67,11 @@
   return message->type() == IPC_REPLY_ID;
 }
 
+void AwContentClient::SetGpuInfo(const gpu::GPUInfo& gpu_info) {
+  gpu_fingerprint_ = gpu_info.gl_version + '|' + gpu_info.gl_vendor + '|' +
+                     gpu_info.gl_renderer;
+  std::replace_if(gpu_fingerprint_.begin(), gpu_fingerprint_.end(),
+                  [](char c) { return !::isprint(c); }, '_');
+}
+
 }  // namespace android_webview
diff --git a/android_webview/common/aw_content_client.h b/android_webview/common/aw_content_client.h
index 01f4ff8c..28eb2fc 100644
--- a/android_webview/common/aw_content_client.h
+++ b/android_webview/common/aw_content_client.h
@@ -9,6 +9,10 @@
 
 #include "base/compiler_specific.h"
 
+namespace gpu {
+struct GPUInfo;
+}
+
 namespace android_webview {
 
 std::string GetProduct();
@@ -26,6 +30,12 @@
       int resource_id,
       ui::ScaleFactor scale_factor) const override;
   bool CanSendWhileSwappedOut(const IPC::Message* message) override;
+
+  void SetGpuInfo(const gpu::GPUInfo& gpu_info) override;
+  const std::string& gpu_fingerprint() const { return gpu_fingerprint_; }
+
+ private:
+  std::string gpu_fingerprint_;
 };
 
 }  // namespace android_webview
diff --git a/android_webview/common/aw_switches.cc b/android_webview/common/aw_switches.cc
index 9cb954d..39a9556 100644
--- a/android_webview/common/aw_switches.cc
+++ b/android_webview/common/aw_switches.cc
@@ -6,7 +6,7 @@
 
 namespace switches {
 
-const char kEnablePageVisibility[] = "enable-page-visibility";
+const char kDisablePageVisibility[] = "disable-page-visibility";
 const char kUseIpcCommandBuffer[] = "use-ipc-command-buffer";
 const char kWebViewSandboxedRenderer[] = "webview-sandboxed-renderer";
 
diff --git a/android_webview/common/aw_switches.h b/android_webview/common/aw_switches.h
index 4873d6e..a760616b 100644
--- a/android_webview/common/aw_switches.h
+++ b/android_webview/common/aw_switches.h
@@ -7,7 +7,7 @@
 
 namespace switches {
 
-extern const char kEnablePageVisibility[];
+extern const char kDisablePageVisibility[];
 extern const char kUseIpcCommandBuffer[];
 extern const char kWebViewSandboxedRenderer[];
 
diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
index a95aaf9..ce94174 100644
--- a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
+++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
@@ -115,5 +115,10 @@
   g_enabled = true;
 }
 
+void AddGpuFingerprintToMicrodumpCrashHandler(
+    const std::string& gpu_fingerprint) {
+  breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint);
+}
+
 }  // namespace crash_reporter
 }  // namespace android_webview
diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.h b/android_webview/crash_reporter/aw_microdump_crash_reporter.h
index 5176b31..5fcda99a 100644
--- a/android_webview/crash_reporter/aw_microdump_crash_reporter.h
+++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.h
@@ -5,10 +5,14 @@
 #ifndef ANDROID_WEBVIEW_CRASH_REPORTER_AW_MICRODUMP_CRASH_REPORTER_H_
 #define ANDROID_WEBVIEW_CRASH_REPORTER_AW_MICRODUMP_CRASH_REPORTER_H_
 
+#include <string>
+
 namespace android_webview {
 namespace crash_reporter {
 
 void EnableMicrodumpCrashReporter();
+void AddGpuFingerprintToMicrodumpCrashHandler(
+    const std::string& gpu_fingerprint);
 
 }  // namespace crash_reporter
 }  // namespace android_webview
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 29c1e28c..5151678 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -42,7 +42,6 @@
 
 import org.chromium.android_webview.permission.AwGeolocationCallback;
 import org.chromium.android_webview.permission.AwPermissionRequest;
-import org.chromium.base.CommandLine;
 import org.chromium.base.LocaleUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.TraceEvent;
@@ -106,9 +105,6 @@
     private static final boolean FORCE_AUXILIARY_BITMAP_RENDERING =
             "goldfish".equals(Build.HARDWARE);
 
-    // Matches kEnablePageVisibility.
-    private static final String ENABLE_PAGE_VISIBILITY = "enable-page-visibility";
-
     /**
      * WebKit hit test related data structure. These are used to implement
      * getHitTestResult, requestFocusNodeHref, requestImageRef methods in WebView.
@@ -236,8 +232,6 @@
     private final AwSettings mSettings;
     private final ScrollAccessibilityHelper mScrollAccessibilityHelper;
 
-    // Visibility related state.
-    private final boolean mEnablePageVisibility;
     private boolean mIsPaused;
     private boolean mIsViewVisible;
     private boolean mIsWindowVisible;
@@ -721,7 +715,6 @@
         mScrollOffsetManager =
                 dependencyFactory.createScrollOffsetManager(new AwScrollOffsetManagerDelegate());
         mScrollAccessibilityHelper = new ScrollAccessibilityHelper(mContainerView);
-        mEnablePageVisibility = CommandLine.getInstance().hasSwitch(ENABLE_PAGE_VISIBILITY);
 
         setOverScrollMode(mContainerView.getOverScrollMode());
         setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
@@ -2287,10 +2280,7 @@
 
     private void updateContentViewCoreVisibility() {
         if (isDestroyed()) return;
-        boolean contentViewCoreVisible = !mIsPaused;
-        if (mEnablePageVisibility) {
-            contentViewCoreVisible = contentViewCoreVisible && mIsWindowVisible && mIsViewVisible;
-        }
+        boolean contentViewCoreVisible = nativeIsVisible(mNativeAwContents);
 
         if (contentViewCoreVisible && !mIsContentViewCoreVisible) {
             mContentViewCore.onShow();
@@ -3123,7 +3113,8 @@
     private native void nativeSetWindowVisibility(long nativeAwContents, boolean visible);
     private native void nativeSetIsPaused(long nativeAwContents, boolean paused);
     private native void nativeOnAttachedToWindow(long nativeAwContents, int w, int h);
-    private static native void nativeOnDetachedFromWindow(long nativeAwContents);
+    private native void nativeOnDetachedFromWindow(long nativeAwContents);
+    private native boolean nativeIsVisible(long nativeAwContents);
     private native void nativeSetDipScale(long nativeAwContents, float dipScale);
 
     // Returns null if save state fails.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
index 9ec1ab1..e82c771a 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
@@ -4,16 +4,21 @@
 
 package org.chromium.android_webview.test;
 
+import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.os.Build;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.View;
 
 import org.chromium.android_webview.AwContents;
+import org.chromium.android_webview.AwContents.VisualStateCallback;
 import org.chromium.android_webview.test.util.GraphicsTestUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * AwContents rendering / pixel tests.
@@ -23,14 +28,14 @@
 
     private TestAwContentsClient mContentsClient;
     private AwContents mAwContents;
+    private AwTestContainerView mContainerView;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mContentsClient = new TestAwContentsClient();
-        final AwTestContainerView testContainerView =
-                createAwTestContainerViewOnMainSync(mContentsClient);
-        mAwContents = testContainerView.getAwContents();
+        mContainerView = createAwTestContainerViewOnMainSync(mContentsClient);
+        mAwContents = mContainerView.getAwContents();
     }
 
     void setBackgroundColorOnUiThread(final int c) {
@@ -89,4 +94,48 @@
         // Invalidation only, so picture should be null.
         assertNull(mContentsClient.getPictureListenerHelper().getPicture());
     }
+
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testForceDrawWhenInvisible() throws Throwable {
+        loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
+                "data:text/html,<html><head><style>body {background-color:#227788}</style></head>"
+                        + "<body>Hello world!</body></html>");
+
+        Bitmap visibleBitmap = null;
+        Bitmap invisibleBitmap = null;
+        final CountDownLatch latch = new CountDownLatch(1);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final long requestId1 = 1;
+                mAwContents.insertVisualStateCallback(requestId1, new VisualStateCallback() {
+                    @Override
+                    public void onComplete(long id) {
+                        assertEquals(requestId1, id);
+                        latch.countDown();
+                    }
+                });
+            }
+        });
+        assertTrue(latch.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        final int width = mAwContents.getContentWidthCss();
+        final int height = mAwContents.getContentHeightCss();
+        visibleBitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, width, height);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mContainerView.setVisibility(View.INVISIBLE);
+            }
+        });
+
+        // VisualStateCallback#onComplete won't be called when WebView is
+        // invisible. So there is no reliable way to tell if View#setVisibility
+        // has taken effect. Just sleep the test thread for 500ms.
+        Thread.sleep(500);
+        invisibleBitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, width, height);
+        assertNotNull(invisibleBitmap);
+        assertTrue(invisibleBitmap.sameAs(visibleBitmap));
+    }
 }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java
index d41b7a38..d182da5 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java
@@ -29,6 +29,16 @@
         return doDrawAwContents(awContents, width, height, null, null);
     }
 
+    public static Bitmap drawAwContentsOnUiThread(
+            final AwContents awContents, final int width, final int height) {
+        return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Bitmap>() {
+            @Override
+            public Bitmap call() {
+                return drawAwContents(awContents, width, height);
+            }
+        });
+    }
+
     /**
      * Draws the supplied {@link AwContents} after applying a translate into the returned
      * {@link Bitmap}.
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index 0f4dfbb..8d2a91a 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -187,6 +187,12 @@
     int exit_code = browser_runner_->Initialize(main_function_params);
     DCHECK_LT(exit_code, 0);
 
+    // At this point the content client has received the GPU info required
+    // to create a GPU fingerpring, and we can pass it to the microdump
+    // crash handler on the same thread as the crash handler was initialized.
+    crash_reporter::AddGpuFingerprintToMicrodumpCrashHandler(
+        content_client_.gpu_fingerprint());
+
     g_allow_wait_in_ui_thread.Get().reset(
         new ScopedAllowWaitForLegacyWebViewApi);
 
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index ebe83fb..c67c557 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -16,6 +16,7 @@
 #include "android_webview/browser/scoped_app_gl_state_restore.h"
 #include "android_webview/browser/shared_renderer_state.h"
 #include "android_webview/common/aw_hit_test_data.h"
+#include "android_webview/common/aw_switches.h"
 #include "android_webview/common/devtools_instrumentation.h"
 #include "android_webview/native/aw_autofill_client.h"
 #include "android_webview/native/aw_browser_dependency_factory.h"
@@ -187,7 +188,9 @@
     : web_contents_(web_contents.Pass()),
       browser_view_renderer_(
           this,
-          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+          base::CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kDisablePageVisibility)),
       renderer_manager_key_(GLViewRendererManager::GetInstance()->NullKey()) {
   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
   icon_helper_.reset(new IconHelper(web_contents_.get()));
@@ -863,6 +866,10 @@
   browser_view_renderer_.OnDetachedFromWindow();
 }
 
+bool AwContents::IsVisible(JNIEnv* env, jobject obj) {
+  return browser_view_renderer_.IsClientVisible();
+}
+
 void AwContents::DetachFunctorFromView() {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 9e03a322..0b2fc1f6 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -115,6 +115,7 @@
   void SetIsPaused(JNIEnv* env, jobject obj, bool paused);
   void OnAttachedToWindow(JNIEnv* env, jobject obj, int w, int h);
   void OnDetachedFromWindow(JNIEnv* env, jobject obj);
+  bool IsVisible(JNIEnv* env, jobject obj);
   base::android::ScopedJavaLocalRef<jbyteArray> GetOpaqueState(
       JNIEnv* env, jobject obj);
   jboolean RestoreFromOpaqueState(JNIEnv* env, jobject obj, jbyteArray state);
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 3fcc253..98887e2 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -50,8 +50,9 @@
 namespace android_webview {
 
 AwContentRendererClient::AwContentRendererClient()
-    : enable_page_visibility_(base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnablePageVisibility)) {}
+    : disable_page_visibility_(
+          base::CommandLine::ForCurrentProcess()
+              ->HasSwitch(switches::kDisablePageVisibility)) {}
 
 AwContentRendererClient::~AwContentRendererClient() {
 }
@@ -174,12 +175,12 @@
 bool AwContentRendererClient::ShouldOverridePageVisibilityState(
     const content::RenderFrame* render_frame,
     blink::WebPageVisibilityState* override_state) {
-  if (enable_page_visibility_)
-    return false;
+  if (disable_page_visibility_) {
+    *override_state = blink::WebPageVisibilityStateVisible;
+    return true;
+  }
 
-  // webview is always visible due to rendering requirements.
-  *override_state = blink::WebPageVisibilityStateVisible;
-  return true;
+  return false;
 }
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index a6f1f02..f58da53 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -44,7 +44,7 @@
  private:
   scoped_ptr<AwRenderProcessObserver> aw_render_process_observer_;
   scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
-  const bool enable_page_visibility_;
+  const bool disable_page_visibility_;
 };
 
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_render_view_ext.cc b/android_webview/renderer/aw_render_view_ext.cc
index ee8f14e5..6a6164e 100644
--- a/android_webview/renderer/aw_render_view_ext.cc
+++ b/android_webview/renderer/aw_render_view_ext.cc
@@ -188,40 +188,43 @@
 }
 
 void AwRenderViewExt::DidCommitCompositorFrame() {
-  UpdatePageScaleFactor();
+  PostCheckContentsSizeAndScale();
 }
 
 void AwRenderViewExt::DidUpdateLayout() {
+  PostCheckContentsSizeAndScale();
+}
+
+void AwRenderViewExt::PostCheckContentsSizeAndScale() {
   if (check_contents_size_timer_.IsRunning())
     return;
 
   check_contents_size_timer_.Start(FROM_HERE,
                                    base::TimeDelta::FromMilliseconds(0), this,
-                                   &AwRenderViewExt::CheckContentsSize);
+                                   &AwRenderViewExt::CheckContentsSizeAndScale);
 }
 
-void AwRenderViewExt::UpdatePageScaleFactor() {
-  if (page_scale_factor_ != render_view()->GetWebView()->pageScaleFactor()) {
-    page_scale_factor_ = render_view()->GetWebView()->pageScaleFactor();
+void AwRenderViewExt::CheckContentsSizeAndScale() {
+  blink::WebView* webview = render_view()->GetWebView();
+  if (!webview)
+    return;
+
+  if (page_scale_factor_ != webview->pageScaleFactor()) {
+    page_scale_factor_ = webview->pageScaleFactor();
     Send(new AwViewHostMsg_PageScaleFactorChanged(routing_id(),
                                                   page_scale_factor_));
   }
-}
-
-void AwRenderViewExt::CheckContentsSize() {
-  if (!render_view()->GetWebView())
-    return;
 
   gfx::Size contents_size;
 
-  blink::WebFrame* main_frame = render_view()->GetWebView()->mainFrame();
+  blink::WebFrame* main_frame = webview->mainFrame();
   if (main_frame)
     contents_size = main_frame->contentsSize();
 
   // Fall back to contentsPreferredMinimumSize if the mainFrame is reporting a
   // 0x0 size (this happens during initial load).
   if (contents_size.IsEmpty()) {
-    contents_size = render_view()->GetWebView()->contentsPreferredMinimumSize();
+    contents_size = webview->contentsPreferredMinimumSize();
   }
 
   if (contents_size == last_sent_contents_size_)
diff --git a/android_webview/renderer/aw_render_view_ext.h b/android_webview/renderer/aw_render_view_ext.h
index ee046848..1a032b306 100644
--- a/android_webview/renderer/aw_render_view_ext.h
+++ b/android_webview/renderer/aw_render_view_ext.h
@@ -56,9 +56,9 @@
 
   void OnSmoothScroll(int target_x, int target_y, long duration_ms);
 
-  void UpdatePageScaleFactor();
+  void CheckContentsSizeAndScale();
 
-  void CheckContentsSize();
+  void PostCheckContentsSizeAndScale();
 
   bool capture_picture_enabled_;
 
diff --git a/android_webview/tools/WebViewShell/AndroidManifest.xml b/android_webview/tools/WebViewShell/AndroidManifest.xml
index a7a79e5e..6223d823 100644
--- a/android_webview/tools/WebViewShell/AndroidManifest.xml
+++ b/android_webview/tools/WebViewShell/AndroidManifest.xml
@@ -84,6 +84,8 @@
             android:label="@string/title_activity_layout_test"
             android:exported="true">
         </activity>
+        <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker"
+            android:exported="true"/>
 
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java
index f94a9b9..4d84446 100644
--- a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java
+++ b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTest.java
@@ -6,6 +6,7 @@
 
 import android.os.Environment;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
 
 import junit.framework.ComparisonFailure;
 
@@ -67,17 +68,20 @@
         return (WebViewLayoutTestRunner) super.getInstrumentation();
     }
 
+    @MediumTest
     public void testSimple() throws Exception {
         runWebViewLayoutTest("experimental/basic-logging.html",
                              "experimental/basic-logging-expected.txt");
     }
 
     // This is a non-failing test because it tends to require frequent rebaselines.
+    @MediumTest
     public void testGlobalInterfaceNoFail() throws Exception {
         runBlinkLayoutTest("webexposed/global-interface-listing.html",
                            "webexposed/global-interface-listing-expected.txt", true);
     }
 
+    @MediumTest
     public void testNoUnexpectedInterfaces() throws Exception {
         ensureJsTestCopied();
         loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
@@ -101,6 +105,7 @@
         assertEquals("Unexpected new webview interfaces found", "", newInterfaces.toString());
     }
 
+    @MediumTest
     public void testWebViewExcludedInterfaces() throws Exception {
         ensureJsTestCopied();
         loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
@@ -130,6 +135,7 @@
         assertEquals("Unexpected webview interfaces found", "", unexpected.toString());
     }
 
+    @MediumTest
     public void testWebViewIncludedStableInterfaces() throws Exception {
         ensureJsTestCopied();
         loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
@@ -164,16 +170,19 @@
 
     // Blink platform API tests
 
+    @MediumTest
     public void testGeolocationCallbacks() throws Exception {
         runWebViewLayoutTest("blink-apis/geolocation/geolocation-permission-callbacks.html",
                 "blink-apis/geolocation/geolocation-permission-callbacks-expected.txt");
     }
 
+    @MediumTest
     public void testMediaStreamApiDenyPermission() throws Exception {
         runWebViewLayoutTest("blink-apis/webrtc/mediastream-permission-denied-callbacks.html",
                 "blink-apis/webrtc/mediastream-permission-denied-callbacks-expected.txt");
     }
 
+    @MediumTest
     public void testMediaStreamApi() throws Exception {
         mTestActivity.setGrantPermission(true);
         runWebViewLayoutTest("blink-apis/webrtc/mediastream-callbacks.html",
diff --git a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java
index 4356e3bf..147c3e5 100644
--- a/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java
+++ b/android_webview/tools/WebViewShell/src/org/chromium/webview_shell/WebViewLayoutTestRunner.java
@@ -5,8 +5,11 @@
 package org.chromium.webview_shell;
 
 import android.os.Bundle;
+import android.test.AndroidTestRunner;
 import android.test.InstrumentationTestRunner;
 
+import org.chromium.test.reporter.TestStatusListener;
+
 /**
  * Customized test runner for running instrumentation tests in WebViewBrowserTests.
  */
@@ -25,4 +28,11 @@
     public boolean isRebaseline() {
         return mModeArgument != null ? mModeArgument.equals(MODE_REBASELINE) : false;
     }
+
+    @Override
+    protected AndroidTestRunner getAndroidTestRunner() {
+        AndroidTestRunner runner = super.getAndroidTestRunner();
+        runner.addTestListener(new TestStatusListener(getContext()));
+        return runner;
+    }
 }
\ No newline at end of file
diff --git a/android_webview/tools/WebViewShell/test/webexposed/global-interface-listing-expected.txt b/android_webview/tools/WebViewShell/test/webexposed/global-interface-listing-expected.txt
index 505e9b2..ca39b693 100644
--- a/android_webview/tools/WebViewShell/test/webexposed/global-interface-listing-expected.txt
+++ b/android_webview/tools/WebViewShell/test/webexposed/global-interface-listing-expected.txt
@@ -4361,11 +4361,7 @@
     getter currentTranslate
     getter currentView
     getter height
-    getter pixelUnitToMillimeterX
-    getter pixelUnitToMillimeterY
     getter preserveAspectRatio
-    getter screenPixelToMillimeterX
-    getter screenPixelToMillimeterY
     getter useCurrentView
     getter viewBox
     getter viewport
diff --git a/apps/saved_files_service.cc b/apps/saved_files_service.cc
index 49e0b56f..43a0062 100644
--- a/apps/saved_files_service.cc
+++ b/apps/saved_files_service.cc
@@ -262,7 +262,7 @@
 void SavedFilesService::ClearQueueIfNoRetainPermission(
     const Extension* extension) {
   if (extensions::util::IsEphemeralApp(extension->id(), profile_) ||
-      !extension->permissions_data()->active_permissions()->HasAPIPermission(
+      !extension->permissions_data()->active_permissions().HasAPIPermission(
           APIPermission::kFileSystemRetainEntries)) {
     ClearQueue(extension);
   }
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc
index 262d826f..ff66e04 100644
--- a/ash/autoclick/autoclick_unittest.cc
+++ b/ash/autoclick/autoclick_unittest.cc
@@ -269,13 +269,7 @@
   EXPECT_EQ(0u, events.size());
 }
 
-// Fails on official cros trunk build. See crbug.com/489896.
-#if defined(OFFICIAL_BUILD)
-#define MAYBE_SynthesizedMouseMovesIgnored DISABLED_SynthesizedMouseMovesIgnored
-#else
-#define MAYBE_SynthesizedMouseMovesIgnored SynthesizedMouseMovesIgnored
-#endif
-TEST_F(AutoclickTest, MAYBE_SynthesizedMouseMovesIgnored) {
+TEST_F(AutoclickTest, SynthesizedMouseMovesIgnored) {
   GetAutoclickController()->SetEnabled(true);
   std::vector<ui::MouseEvent> events;
   GetEventGenerator().MoveMouseTo(100, 100);
diff --git a/ash/focus_cycler.cc b/ash/focus_cycler.cc
index 402fdc8..097654b1 100644
--- a/ash/focus_cycler.cc
+++ b/ash/focus_cycler.cc
@@ -35,6 +35,12 @@
   widgets_.push_back(widget);
 }
 
+void FocusCycler::RemoveWidget(views::Widget* widget) {
+  auto iter = std::find(widgets_.begin(), widgets_.end(), widget);
+  if (iter != widgets_.end())
+    widgets_.erase(iter);
+}
+
 void FocusCycler::RotateFocus(Direction direction) {
   aura::Window* window = ash::wm::GetActiveWindow();
   if (window) {
diff --git a/ash/focus_cycler.h b/ash/focus_cycler.h
index 769c2ea..014b08a 100644
--- a/ash/focus_cycler.h
+++ b/ash/focus_cycler.h
@@ -37,6 +37,9 @@
   // AccessiblePaneView as the content view.
   void AddWidget(views::Widget* widget);
 
+  // Remove a widget from the focus cycle.
+  void RemoveWidget(views::Widget* widget);
+
   // Move focus to the next widget.
   void RotateFocus(Direction direction);
 
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc
index e8a8ca8..8e263a77 100644
--- a/ash/focus_cycler_unittest.cc
+++ b/ash/focus_cycler_unittest.cc
@@ -399,5 +399,32 @@
   EXPECT_EQ(focus_manager->GetFocusedView(), view1);
 }
 
+// Test that when the shelf widget & status area widget are removed, they should
+// also be removed from focus cycler.
+TEST_F(FocusCyclerTest, RemoveWidgetOnDisplayRemoved) {
+  // Two displays are added, so two shelf widgets and two status area widgets
+  // are added to focus cycler.
+  UpdateDisplay("800x800, 500x500");
+  // Remove one display. Its shelf widget and status area widget should also be
+  // removed from focus cycler.
+  UpdateDisplay("800x800");
+
+  // Create a single test window.
+  scoped_ptr<Window> window(CreateTestWindowInShellWithId(0));
+  wm::ActivateWindow(window.get());
+  EXPECT_TRUE(wm::IsActiveWindow(window.get()));
+
+  // Cycle focus to the status area.
+  Shell::GetInstance()->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
+  EXPECT_FALSE(wm::IsActiveWindow(window.get()));
+
+  // Cycle focus to the shelf.
+  Shell::GetInstance()->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
+
+  // Cycle focus should go back to the browser.
+  Shell::GetInstance()->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
+  EXPECT_TRUE(wm::IsActiveWindow(window.get()));
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 95bc689..d93153a 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -653,6 +653,8 @@
 }
 
 ShelfWidget::~ShelfWidget() {
+  Shell::GetInstance()->focus_cycler()->RemoveWidget(this);
+  SetFocusCycler(nullptr);
   RemoveObserver(this);
 }
 
@@ -804,8 +806,10 @@
 }
 
 void ShelfWidget::ShutdownStatusAreaWidget() {
-  if (status_area_widget_)
+  if (status_area_widget_) {
+    Shell::GetInstance()->focus_cycler()->RemoveWidget(status_area_widget_);
     status_area_widget_->Shutdown();
+  }
   status_area_widget_ = NULL;
 }
 
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc
index a964fcd..e0b9fe2 100644
--- a/ash/shell/app_list.cc
+++ b/ash/shell/app_list.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_path.h"
 #include "base/i18n/case_conversion.h"
 #include "base/i18n/string_search.h"
+#include "base/memory/scoped_vector.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -29,7 +30,8 @@
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image_skia.h"
-#include "ui/views/examples/examples_window_with_content.h"
+#include "ui/views/examples/example_base.h"
+#include "ui/views/examples/examples_window.h"
 
 namespace ash {
 namespace shell {
@@ -121,10 +123,9 @@
         break;
       }
       case EXAMPLES_WINDOW: {
-        views::examples::ShowExamplesWindowWithContent(
-            views::examples::DO_NOTHING_ON_CLOSE,
-            Shell::GetInstance()->delegate()->GetActiveBrowserContext(),
-            NULL);
+        views::examples::ShowExamplesWindow(
+            views::examples::QUIT_ON_CLOSE, NULL,
+            scoped_ptr<ScopedVector<views::examples::ExampleBase>>());
         break;
       }
       default:
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index 735cd0d..359693c 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -185,6 +185,10 @@
   return false;
 }
 
+bool ShellDelegateImpl::CanShowWindowForUser(aura::Window* window) const {
+  return true;
+}
+
 bool ShellDelegateImpl::IsForceMaximizeOnFirstRun() const {
   return false;
 }
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index 6c054c37..2167b0f8 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -39,6 +39,7 @@
   bool IsMultiProfilesEnabled() const override;
   bool IsRunningInForcedAppMode() const override;
   bool IsMultiAccountEnabled() const override;
+  bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
   void PreInit() override;
   void PreShutdown() override;
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index 5e1c3a2..5794294 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -87,6 +87,10 @@
   // Returns true if multi account is enabled.
   virtual bool IsMultiAccountEnabled() const = 0;
 
+  // Returns true if |window| can be shown for the delegate's concept of current
+  // user.
+  virtual bool CanShowWindowForUser(aura::Window* window) const = 0;
+
   // Returns true if the first window shown on first run should be
   // unconditionally maximized, overriding the heuristic that normally chooses
   // the window size.
diff --git a/ash/system/tray/default_system_tray_delegate.cc b/ash/system/tray/default_system_tray_delegate.cc
index 49386b4..ea163393 100644
--- a/ash/system/tray/default_system_tray_delegate.cc
+++ b/ash/system/tray/default_system_tray_delegate.cc
@@ -30,7 +30,7 @@
   return user::LOGGED_IN_USER;
 }
 
-const std::string DefaultSystemTrayDelegate::GetSupervisedUserManager() const {
+std::string DefaultSystemTrayDelegate::GetSupervisedUserManager() const {
   if (!IsUserSupervised())
     return std::string();
   return "manager@chrome.com";
diff --git a/ash/system/tray/default_system_tray_delegate.h b/ash/system/tray/default_system_tray_delegate.h
index ed26303..47c6da4 100644
--- a/ash/system/tray/default_system_tray_delegate.h
+++ b/ash/system/tray/default_system_tray_delegate.h
@@ -20,7 +20,7 @@
   // SystemTrayDelegate
   bool GetTrayVisibilityOnStartup() override;
   user::LoginStatus GetUserLoginStatus() const override;
-  const std::string GetSupervisedUserManager() const override;
+  std::string GetSupervisedUserManager() const override;
   bool IsUserSupervised() const override;
   void GetSystemUpdateInfo(UpdateInfo* info) const override;
   bool ShouldShowSettings() override;
diff --git a/ash/system/tray/system_tray_delegate.cc b/ash/system/tray/system_tray_delegate.cc
index 19a7c7e8..314817e 100644
--- a/ash/system/tray/system_tray_delegate.cc
+++ b/ash/system/tray/system_tray_delegate.cc
@@ -71,19 +71,19 @@
   return std::string();
 }
 
-const base::string16 SystemTrayDelegate::GetEnterpriseMessage() const {
+base::string16 SystemTrayDelegate::GetEnterpriseMessage() const {
   return base::string16();
 }
 
-const std::string SystemTrayDelegate::GetSupervisedUserManager() const {
+std::string SystemTrayDelegate::GetSupervisedUserManager() const {
   return std::string();
 }
 
-const base::string16 SystemTrayDelegate::GetSupervisedUserManagerName() const {
+base::string16 SystemTrayDelegate::GetSupervisedUserManagerName() const {
   return base::string16();
 }
 
-const base::string16 SystemTrayDelegate::GetSupervisedUserMessage() const {
+base::string16 SystemTrayDelegate::GetSupervisedUserMessage() const {
   return base::string16();
 }
 
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h
index c16cdb7..9859a48 100644
--- a/ash/system/tray/system_tray_delegate.h
+++ b/ash/system/tray/system_tray_delegate.h
@@ -144,17 +144,17 @@
   virtual std::string GetEnterpriseDomain() const;
 
   // Returns notification for enterprise enrolled devices.
-  virtual const base::string16 GetEnterpriseMessage() const;
+  virtual base::string16 GetEnterpriseMessage() const;
 
   // Returns the display email of the user that manages the current supervised
   // user.
-  virtual const std::string GetSupervisedUserManager() const;
+  virtual std::string GetSupervisedUserManager() const;
 
   // Returns the name of the user that manages the current supervised user.
-  virtual const base::string16 GetSupervisedUserManagerName() const;
+  virtual base::string16 GetSupervisedUserManagerName() const;
 
   // Returns the notification for supervised users.
-  virtual const base::string16 GetSupervisedUserMessage() const;
+  virtual base::string16 GetSupervisedUserMessage() const;
 
   // Returns true if the current user is supervised: has legacy supervised
   // account or kid account.
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index d884547..1c07267b 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -31,6 +31,7 @@
 #if defined(OS_CHROMEOS)
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #endif
 
 #if defined(OS_WIN)
@@ -86,8 +87,13 @@
   // Create DBusThreadManager for testing.
   if (!chromeos::DBusThreadManager::IsInitialized()) {
     chromeos::DBusThreadManager::Initialize();
+    bluez::BluezDBusManager::Initialize(
+        chromeos::DBusThreadManager::Get()->GetSystemBus(),
+        chromeos::DBusThreadManager::Get()->IsUsingStub(
+            chromeos::DBusClientBundle::BLUETOOTH));
     dbus_thread_manager_initialized_ = true;
   }
+
   // Create CrasAudioHandler for testing since g_browser_process is not
   // created in AshTestBase tests.
   chromeos::CrasAudioHandler::InitializeForTesting();
@@ -125,6 +131,7 @@
 #if defined(OS_CHROMEOS)
   chromeos::CrasAudioHandler::Shutdown();
   if (dbus_thread_manager_initialized_) {
+    bluez::BluezDBusManager::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
     dbus_thread_manager_initialized_ = false;
   }
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index dbc04f8..b19d240 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -110,6 +110,10 @@
   return false;
 }
 
+bool TestShellDelegate::CanShowWindowForUser(aura::Window* window) const {
+  return true;
+}
+
 bool TestShellDelegate::IsForceMaximizeOnFirstRun() const {
   return force_maximize_on_first_run_;
 }
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index 91d000e..f0771d5 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -36,6 +36,7 @@
   bool IsMultiProfilesEnabled() const override;
   bool IsRunningInForcedAppMode() const override;
   bool IsMultiAccountEnabled() const override;
+  bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
   void PreInit() override;
   void PreShutdown() override;
diff --git a/ash/wm/ash_focus_rules.cc b/ash/wm/ash_focus_rules.cc
index 58a71eb..7a54e7d 100644
--- a/ash/wm/ash_focus_rules.cc
+++ b/ash/wm/ash_focus_rules.cc
@@ -4,7 +4,6 @@
 
 #include "ash/wm/ash_focus_rules.h"
 
-#include "ash/session/session_state_delegate.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/shell_window_ids.h"
@@ -86,22 +85,8 @@
     aura::Window* window) const {
   // If the |window| doesn't belong to the current active user and also doesn't
   // show for the current active user, then it should not be activated.
-  SessionStateDelegate* delegate =
-      Shell::GetInstance()->session_state_delegate();
-  if (delegate->NumberOfLoggedInUsers() > 1) {
-    content::BrowserContext* active_browser_context =
-        Shell::GetInstance()->delegate()->GetActiveBrowserContext();
-    content::BrowserContext* owner_browser_context =
-        delegate->GetBrowserContextForWindow(window);
-    content::BrowserContext* shown_browser_context =
-        delegate->GetUserPresentingBrowserContextForWindow(window);
-
-    if (owner_browser_context && active_browser_context &&
-        owner_browser_context != active_browser_context &&
-        shown_browser_context != active_browser_context) {
-      return false;
-    }
-  }
+  if (!Shell::GetInstance()->delegate()->CanShowWindowForUser(window))
+    return false;
 
   if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window))
     return true;
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index a119acb..cff0e37 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -352,24 +352,6 @@
 
     /**
      * @see android.view.Window#setStatusBarColor(int color).
-     * TODO(ianwen): remove this method after downstream rolling.
-     */
-    public static void setStatusBarColor(Activity activity, int statusBarColor) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            // If both system bars are black, we can remove these from our layout,
-            // removing or shrinking the SurfaceFlinger overlay required for our views.
-            Window window = activity.getWindow();
-            if (statusBarColor == Color.BLACK && window.getNavigationBarColor() == Color.BLACK) {
-                window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-            } else {
-                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-            }
-            window.setStatusBarColor(statusBarColor);
-        }
-    }
-
-    /**
-     * @see android.view.Window#setStatusBarColor(int color).
      */
     public static void setStatusBarColor(Window window, int statusBarColor) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -454,4 +436,16 @@
             return res.getColorStateList(id);
         }
     }
+
+    /**
+     * @see android.widget.TextView#setTextAppearance(int id).
+     */
+    @SuppressWarnings("deprecation")
+    public static void setTextAppearance(TextView view, int id) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            view.setTextAppearance(id);
+        } else {
+            view.setTextAppearance(view.getContext(), id);
+        }
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index cf70b71..ef2887ac 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -210,4 +210,14 @@
     public static void setThreadPriorityAudio(int tid) {
         Process.setThreadPriority(tid, Process.THREAD_PRIORITY_AUDIO);
     }
+
+    /**
+     * Checks whether Thread priority is THREAD_PRIORITY_AUDIO or not.
+     * @param tid Thread id.
+     * @return true for THREAD_PRIORITY_AUDIO and false otherwise.
+     */
+    @CalledByNative
+    private static boolean isThreadPriorityAudio(int tid) {
+        return Process.getThreadPriority(tid) == Process.THREAD_PRIORITY_AUDIO;
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java b/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java
index d8b37cd9a..89be90bd 100644
--- a/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java
+++ b/base/android/java/src/org/chromium/base/WindowCallbackWrapper.java
@@ -5,6 +5,8 @@
 package org.chromium.base;
 
 import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.os.Build;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
 import android.view.KeyEvent;
@@ -134,11 +136,13 @@
     }
 
     @Override
+    @TargetApi(Build.VERSION_CODES.M)
     public boolean onSearchRequested(SearchEvent searchEvent) {
         return mCallback.onSearchRequested(searchEvent);
     }
 
     @Override
+    @TargetApi(Build.VERSION_CODES.M)
     public ActionMode onWindowStartingActionMode(Callback callback, int type) {
         return mCallback.onWindowStartingActionMode(callback, type);
     }
diff --git a/base/base_switches.cc b/base/base_switches.cc
index 7f3be7f..76827b8 100644
--- a/base/base_switches.cc
+++ b/base/base_switches.cc
@@ -23,6 +23,16 @@
 // Force disabling of low-end device mode when set.
 const char kDisableLowEndDeviceMode[]       = "disable-low-end-device-mode";
 
+// This option can be used to force field trials when testing changes locally.
+// The argument is a list of name and value pairs, separated by slashes. If a
+// trial name is prefixed with an asterisk, that trial will start activated.
+// For example, the following argument defines two trials, with the second one
+// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/" This option can
+// also be used by the browser process to send the list of trials to a
+// non-browser process, using the same format. See
+// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
+const char kForceFieldTrials[]              = "force-fieldtrials";
+
 // Suppresses all error dialogs when present.
 const char kNoErrorDialogs[]                = "noerrdialogs";
 
diff --git a/base/base_switches.h b/base/base_switches.h
index bbd590b..95f6bff 100644
--- a/base/base_switches.h
+++ b/base/base_switches.h
@@ -13,6 +13,7 @@
 
 extern const char kDisableBreakpad[];
 extern const char kEnableCrashReporter[];
+extern const char kForceFieldTrials[];
 extern const char kFullMemoryCrashReport[];
 extern const char kEnableLowEndDeviceMode[];
 extern const char kDisableLowEndDeviceMode[];
diff --git a/base/feature_list.cc b/base/feature_list.cc
index 16eba67..2acd2900 100644
--- a/base/feature_list.cc
+++ b/base/feature_list.cc
@@ -4,9 +4,11 @@
 
 #include "base/feature_list.h"
 
+#include <utility>
 #include <vector>
 
 #include "base/logging.h"
+#include "base/metrics/field_trial.h"
 #include "base/strings/string_split.h"
 
 namespace base {
@@ -37,13 +39,55 @@
   // Process disabled features first, so that disabled ones take precedence over
   // enabled ones (since RegisterOverride() uses insert()).
   for (const auto& feature_name : SplitFeatureListString(disable_features)) {
-    RegisterOverride(feature_name, OVERRIDE_DISABLE_FEATURE);
+    RegisterOverride(feature_name, OVERRIDE_DISABLE_FEATURE, nullptr);
   }
   for (const auto& feature_name : SplitFeatureListString(enable_features)) {
-    RegisterOverride(feature_name, OVERRIDE_ENABLE_FEATURE);
+    RegisterOverride(feature_name, OVERRIDE_ENABLE_FEATURE, nullptr);
   }
 }
 
+bool FeatureList::IsFeatureOverriddenFromCommandLine(
+    const std::string& feature_name,
+    OverrideState state) const {
+  auto it = overrides_.find(feature_name);
+  return it != overrides_.end() && it->second.overridden_state == state &&
+         !it->second.overridden_by_field_trial;
+}
+
+void FeatureList::RegisterFieldTrialOverride(const std::string& feature_name,
+                                             OverrideState override_state,
+                                             FieldTrial* field_trial) {
+  DCHECK(field_trial);
+  DCHECK(!ContainsKey(overrides_, feature_name) ||
+         !overrides_.find(feature_name)->second.field_trial)
+      << "Feature " << feature_name
+      << " has conflicting field trial overrides: "
+      << overrides_.find(feature_name)->second.field_trial->trial_name()
+      << " / " << field_trial->trial_name();
+
+  RegisterOverride(feature_name, override_state, field_trial);
+}
+
+void FeatureList::AssociateReportingFieldTrial(
+    const std::string& feature_name,
+    OverrideState for_overridden_state,
+    FieldTrial* field_trial) {
+  DCHECK(
+      IsFeatureOverriddenFromCommandLine(feature_name, for_overridden_state));
+
+  // Only one associated field trial is supported per feature. This is generally
+  // enforced server-side.
+  OverrideEntry* entry = &overrides_.find(feature_name)->second;
+  if (entry->field_trial) {
+    NOTREACHED() << "Feature " << feature_name
+                 << " already has trial: " << entry->field_trial->trial_name()
+                 << ", associating trial: " << field_trial->trial_name();
+    return;
+  }
+
+  entry->field_trial = field_trial;
+}
+
 // static
 bool FeatureList::IsEnabled(const Feature& feature) {
   return GetInstance()->IsFeatureEnabled(feature);
@@ -81,6 +125,11 @@
   auto it = overrides_.find(feature.name);
   if (it != overrides_.end()) {
     const OverrideEntry& entry = it->second;
+
+    // Activate the corresponding field trial, if necessary.
+    if (entry.field_trial)
+      entry.field_trial->group();
+
     // TODO(asvitkine) Expand this section as more support is added.
     return entry.overridden_state == OVERRIDE_ENABLE_FEATURE;
   }
@@ -89,9 +138,14 @@
 }
 
 void FeatureList::RegisterOverride(const std::string& feature_name,
-                                   OverrideState overridden_state) {
+                                   OverrideState overridden_state,
+                                   FieldTrial* field_trial) {
   DCHECK(!initialized_);
-  overrides_.insert(make_pair(feature_name, OverrideEntry(overridden_state)));
+  // Note: The semantics of insert() is that it does not overwrite the entry if
+  // one already exists for the key. Thus, only the first override for a given
+  // feature name takes effect.
+  overrides_.insert(std::make_pair(
+      feature_name, OverrideEntry(overridden_state, field_trial)));
 }
 
 bool FeatureList::CheckFeatureIdentity(const Feature& feature) {
@@ -107,7 +161,10 @@
   return it->second == &feature;
 }
 
-FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state)
-    : overridden_state(overridden_state) {}
+FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state,
+                                          FieldTrial* field_trial)
+    : overridden_state(overridden_state),
+      field_trial(field_trial),
+      overridden_by_field_trial(field_trial != nullptr) {}
 
 }  // namespace base
diff --git a/base/feature_list.h b/base/feature_list.h
index 6e4ad58..0f91a3e 100644
--- a/base/feature_list.h
+++ b/base/feature_list.h
@@ -16,6 +16,8 @@
 
 namespace base {
 
+class FieldTrial;
+
 // Specifies whether a given feature is enabled or disabled by default.
 enum FeatureState {
   FEATURE_DISABLED_BY_DEFAULT,
@@ -83,6 +85,37 @@
   void InitializeFromCommandLine(const std::string& enable_features,
                                  const std::string& disable_features);
 
+  // Specifies whether a feature override enables or disables the feature.
+  enum OverrideState {
+    OVERRIDE_DISABLE_FEATURE,
+    OVERRIDE_ENABLE_FEATURE,
+  };
+
+  // Returns true if the state of |feature_name| has been overridden via
+  // |InitializeFromCommandLine()|.
+  bool IsFeatureOverriddenFromCommandLine(const std::string& feature_name,
+                                          OverrideState state) const;
+
+  // Associates a field trial for reporting purposes corresponding to the
+  // command-line setting the feature state to |for_overridden_state|. The trial
+  // will be activated when the state of the feature is first queried. This
+  // should be called during registration, after InitializeFromCommandLine() has
+  // been called but before the instance is registered via SetInstance().
+  void AssociateReportingFieldTrial(const std::string& feature_name,
+                                    OverrideState for_overridden_state,
+                                    FieldTrial* field_trial);
+
+  // Registers a field trial to override the enabled state of the specified
+  // feature to |override_state|. Command-line overrides still take precedence
+  // over field trials, so this will have no effect if the feature is being
+  // overridden from the command-line. The associated field trial will be
+  // activated when the feature state for this feature is queried. This should
+  // be called during registration, after InitializeFromCommandLine() has been
+  // called but before the instance is registered via SetInstance().
+  void RegisterFieldTrialOverride(const std::string& feature_name,
+                                  OverrideState override_state,
+                                  FieldTrial* field_trial);
+
   // Returns whether the given |feature| is enabled. Must only be called after
   // the singleton instance has been registered via SetInstance(). Additionally,
   // a feature with a given name must only have a single corresponding Feature
@@ -103,10 +136,27 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(FeatureListTest, CheckFeatureIdentity);
 
-  // Specifies whether a feature override enables or disables the feature.
-  enum OverrideState {
-    OVERRIDE_DISABLE_FEATURE,
-    OVERRIDE_ENABLE_FEATURE,
+  struct OverrideEntry {
+    // The overridden enable (on/off) state of the feature.
+    const OverrideState overridden_state;
+
+    // An optional associated field trial, which will be activated when the
+    // state of the feature is queried for the first time. Weak pointer to the
+    // FieldTrial object that is owned by the FieldTrialList singleton.
+    base::FieldTrial* field_trial;
+
+    // Specifies whether the feature's state is overridden by |field_trial|.
+    // If it's not, and |field_trial| is not null, it means it is simply an
+    // associated field trial for reporting purposes (and |overridden_state|
+    // came from the command-line).
+    const bool overridden_by_field_trial;
+
+    // TODO(asvitkine): Expand this as more support is added.
+
+    // Constructs an OverrideEntry for the given |overridden_state|. If
+    // |field_trial| is not null, it implies that |overridden_state| comes from
+    // the trial, so |overridden_by_field_trial| will be set to true.
+    OverrideEntry(OverrideState overridden_state, FieldTrial* field_trial);
   };
 
   // Finalizes the initialization state of the FeatureList, so that no further
@@ -121,9 +171,14 @@
 
   // Registers an override for feature |feature_name|. The override specifies
   // whether the feature should be on or off (via |overridden_state|), which
-  // will take precedence over the feature's default state.
+  // will take precedence over the feature's default state. If |field_trial| is
+  // not null, registers the specified field trial object to be associated with
+  // the feature, which will activate the field trial when the feature state is
+  // queried. If an override is already registered for the given feature, it
+  // will not be changed.
   void RegisterOverride(const std::string& feature_name,
-                        OverrideState overridden_state);
+                        OverrideState overridden_state,
+                        FieldTrial* field_trial);
 
   // Verifies that there's only a single definition of a Feature struct for a
   // given feature name. Keeps track of the first seen Feature struct for each
@@ -132,14 +187,6 @@
   // DCHECKs and tests.
   bool CheckFeatureIdentity(const Feature& feature);
 
-  struct OverrideEntry {
-    // The overridden enable (on/off) state of the feature.
-    const OverrideState overridden_state;
-
-    // TODO(asvitkine): Expand this as more support is added.
-
-    explicit OverrideEntry(OverrideState overridden_state);
-  };
   // Map from feature name to an OverrideEntry struct for the feature, if it
   // exists.
   std::map<std::string, OverrideEntry> overrides_;
diff --git a/base/feature_list_unittest.cc b/base/feature_list_unittest.cc
index c9423ce7..9d8538e9 100644
--- a/base/feature_list_unittest.cc
+++ b/base/feature_list_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "base/feature_list.h"
 
+#include "base/format_macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/stringprintf.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -70,6 +73,9 @@
 
   for (size_t i = 0; i < arraysize(test_cases); ++i) {
     const auto& test_case = test_cases[i];
+    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
+                                    test_case.enable_features,
+                                    test_case.disable_features));
 
     ClearFeatureListInstance();
     scoped_ptr<FeatureList> feature_list(new FeatureList);
@@ -105,4 +111,200 @@
   EXPECT_FALSE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault2));
 }
 
+TEST_F(FeatureListTest, FieldTrialOverrides) {
+  struct {
+    FeatureList::OverrideState trial1_state;
+    FeatureList::OverrideState trial2_state;
+  } test_cases[] = {
+      {FeatureList::OVERRIDE_DISABLE_FEATURE,
+       FeatureList::OVERRIDE_DISABLE_FEATURE},
+      {FeatureList::OVERRIDE_DISABLE_FEATURE,
+       FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {FeatureList::OVERRIDE_ENABLE_FEATURE,
+       FeatureList::OVERRIDE_DISABLE_FEATURE},
+      {FeatureList::OVERRIDE_ENABLE_FEATURE,
+       FeatureList::OVERRIDE_ENABLE_FEATURE},
+  };
+
+  FieldTrial::ActiveGroup active_group;
+  for (size_t i = 0; i < arraysize(test_cases); ++i) {
+    const auto& test_case = test_cases[i];
+    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
+
+    ClearFeatureListInstance();
+
+    FieldTrialList field_trial_list(nullptr);
+    scoped_ptr<FeatureList> feature_list(new FeatureList);
+
+    FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
+    FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
+    feature_list->RegisterFieldTrialOverride(kFeatureOnByDefaultName,
+                                             test_case.trial1_state, trial1);
+    feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
+                                             test_case.trial2_state, trial2);
+    RegisterFeatureListInstance(feature_list.Pass());
+
+    // Initially, neither trial should be active.
+    EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
+    EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
+
+    const bool expected_enabled_1 =
+        (test_case.trial1_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
+    EXPECT_EQ(expected_enabled_1, FeatureList::IsEnabled(kFeatureOnByDefault));
+    // The above should have activated |trial1|.
+    EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
+    EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
+
+    const bool expected_enabled_2 =
+        (test_case.trial2_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
+    EXPECT_EQ(expected_enabled_2, FeatureList::IsEnabled(kFeatureOffByDefault));
+    // The above should have activated |trial2|.
+    EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
+    EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
+  }
+}
+
+TEST_F(FeatureListTest, CommandLineTakesPrecedenceOverFieldTrial) {
+  ClearFeatureListInstance();
+
+  FieldTrialList field_trial_list(nullptr);
+  scoped_ptr<FeatureList> feature_list(new FeatureList);
+
+  // The feature is explicitly enabled on the command-line.
+  feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
+
+  // But the FieldTrial would set the feature to disabled.
+  FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
+  feature_list->RegisterFieldTrialOverride(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
+  RegisterFeatureListInstance(feature_list.Pass());
+
+  EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
+  // Command-line should take precedence.
+  EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
+  // Since the feature is on due to the command-line, and not as a result of the
+  // field trial, the field trial should not be activated (since the Associate*
+  // API wasn't used.)
+  EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
+}
+
+TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
+  ClearFeatureListInstance();
+
+  FieldTrialList field_trial_list(nullptr);
+  scoped_ptr<FeatureList> feature_list(new FeatureList);
+
+  // No features are overridden from the command line yet
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
+
+  // Now, enable |kFeatureOffByDefaultName| via the command-line.
+  feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
+
+  // It should now be overridden for the enabled group.
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
+  EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
+
+  // Register a field trial to associate with the feature and ensure that the
+  // results are still the same.
+  feature_list->AssociateReportingFieldTrial(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
+      FieldTrialList::CreateFieldTrial("Trial1", "A"));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
+  EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
+
+  // Now, register a field trial to override |kFeatureOnByDefaultName| state
+  // and check that the function still returns false for that feature.
+  feature_list->RegisterFieldTrialOverride(
+      kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
+      FieldTrialList::CreateFieldTrial("Trial2", "A"));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
+  EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
+      kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
+  RegisterFeatureListInstance(feature_list.Pass());
+
+  // Check the expected feature states for good measure.
+  EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
+  EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
+}
+
+TEST_F(FeatureListTest, AssociateReportingFieldTrial) {
+  struct {
+    const char* enable_features;
+    const char* disable_features;
+    bool expected_enable_trial_created;
+    bool expected_disable_trial_created;
+  } test_cases[] = {
+      // If no enable/disable flags are specified, no trials should be created.
+      {"", "", false, false},
+      // Enabling the feature should result in the enable trial created.
+      {kFeatureOffByDefaultName, "", true, false},
+      // Disabling the feature should result in the disable trial created.
+      {"", kFeatureOffByDefaultName, false, true},
+  };
+
+  const char kTrialName[] = "ForcingTrial";
+  const char kForcedOnGroupName[] = "ForcedOn";
+  const char kForcedOffGroupName[] = "ForcedOff";
+
+  for (size_t i = 0; i < arraysize(test_cases); ++i) {
+    const auto& test_case = test_cases[i];
+    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
+                                    test_case.enable_features,
+                                    test_case.disable_features));
+
+    ClearFeatureListInstance();
+
+    FieldTrialList field_trial_list(nullptr);
+    scoped_ptr<FeatureList> feature_list(new FeatureList);
+    feature_list->InitializeFromCommandLine(test_case.enable_features,
+                                            test_case.disable_features);
+
+    FieldTrial* enable_trial = nullptr;
+    if (feature_list->IsFeatureOverriddenFromCommandLine(
+            kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE)) {
+      enable_trial = base::FieldTrialList::CreateFieldTrial(kTrialName,
+                                                            kForcedOnGroupName);
+      feature_list->AssociateReportingFieldTrial(
+          kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
+          enable_trial);
+    }
+    FieldTrial* disable_trial = nullptr;
+    if (feature_list->IsFeatureOverriddenFromCommandLine(
+            kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE)) {
+      disable_trial = base::FieldTrialList::CreateFieldTrial(
+          kTrialName, kForcedOffGroupName);
+      feature_list->AssociateReportingFieldTrial(
+          kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
+          disable_trial);
+    }
+    EXPECT_EQ(test_case.expected_enable_trial_created, enable_trial != nullptr);
+    EXPECT_EQ(test_case.expected_disable_trial_created,
+              disable_trial != nullptr);
+    RegisterFeatureListInstance(feature_list.Pass());
+
+    EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
+    if (disable_trial) {
+      EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
+      EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
+      EXPECT_EQ(kForcedOffGroupName, disable_trial->group_name());
+    } else if (enable_trial) {
+      EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
+      EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
+      EXPECT_EQ(kForcedOnGroupName, enable_trial->group_name());
+    }
+  }
+}
+
 }  // namespace base
diff --git a/base/files/file.h b/base/files/file.h
index cba43536..976188b 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -21,7 +21,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_tracing.h"
 #include "base/files/scoped_file.h"
-#include "base/gtest_prod_util.h"
 #include "base/move.h"
 #include "base/time/time.h"
 
@@ -29,8 +28,6 @@
 #include "base/win/scoped_handle.h"
 #endif
 
-FORWARD_DECLARE_TEST(FileTest, MemoryCorruption);
-
 namespace base {
 
 #if defined(OS_WIN)
@@ -306,55 +303,8 @@
   static std::string ErrorToString(Error error);
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(::FileTest, MemoryCorruption);
-
   friend class FileTracing::ScopedTrace;
 
-#if defined(OS_POSIX)
-  // Encloses a single ScopedFD, saving a cheap tamper resistent memory checksum
-  // alongside it. This checksum is validated at every access, allowing early
-  // detection of memory corruption.
-
-  // TODO(gavinp): This is in place temporarily to help us debug
-  // https://crbug.com/424562 , which can't be reproduced in valgrind. Remove
-  // this code after we have fixed this issue.
-  class MemoryCheckingScopedFD {
-   public:
-    MemoryCheckingScopedFD();
-    MemoryCheckingScopedFD(int fd);
-    ~MemoryCheckingScopedFD();
-
-    bool is_valid() const { Check(); return file_.is_valid(); }
-    int get() const { Check(); return file_.get(); }
-
-    void reset() { Check(); file_.reset(); UpdateChecksum(); }
-    void reset(int fd) { Check(); file_.reset(fd); UpdateChecksum(); }
-    int release() {
-      Check();
-      int fd = file_.release();
-      UpdateChecksum();
-      return fd;
-    }
-
-   private:
-    FRIEND_TEST_ALL_PREFIXES(::FileTest, MemoryCorruption);
-
-    // Computes the checksum for the current value of |file_|. Returns via an
-    // out parameter to guard against implicit conversions of unsigned integral
-    // types.
-    void ComputeMemoryChecksum(unsigned int* out_checksum) const;
-
-    // Confirms that the current |file_| and |file_memory_checksum_| agree,
-    // failing a CHECK if they do not.
-    void Check() const;
-
-    void UpdateChecksum();
-
-    ScopedFD file_;
-    unsigned int file_memory_checksum_;
-  };
-#endif
-
   // Creates or opens the given file. Only called if |path| has no
   // traversal ('..') components.
   void DoInitialize(const FilePath& path, uint32 flags);
@@ -368,7 +318,7 @@
 #if defined(OS_WIN)
   win::ScopedHandle file_;
 #elif defined(OS_POSIX)
-  MemoryCheckingScopedFD file_;
+  ScopedFD file_;
 #endif
 
   // A path to use for tracing purposes. Set if file tracing is enabled during
@@ -386,3 +336,4 @@
 }  // namespace base
 
 #endif  // BASE_FILES_FILE_H_
+
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index 081698f..3f37cec 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -106,7 +106,7 @@
   if (!UpdateWatch())
     return false;
 
-  watcher_.StartWatching(handle_, this);
+  watcher_.StartWatchingOnce(handle_, this);
 
   return true;
 }
@@ -198,7 +198,7 @@
 
   // The watch may have been cancelled by the callback.
   if (handle_ != INVALID_HANDLE_VALUE)
-    watcher_.StartWatching(handle_, this);
+    watcher_.StartWatchingOnce(handle_, this);
 }
 
 // static
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc
index 7fb617c..a5aee01 100644
--- a/base/files/file_posix.cc
+++ b/base/files/file_posix.cc
@@ -420,49 +420,6 @@
   }
 }
 
-File::MemoryCheckingScopedFD::MemoryCheckingScopedFD() {
-  UpdateChecksum();
-}
-
-File::MemoryCheckingScopedFD::MemoryCheckingScopedFD(int fd) : file_(fd) {
-  UpdateChecksum();
-}
-
-File::MemoryCheckingScopedFD::~MemoryCheckingScopedFD() {}
-
-// static
-void File::MemoryCheckingScopedFD::ComputeMemoryChecksum(
-    unsigned int* out_checksum) const {
-  // Use a single iteration of a linear congruentional generator (lcg) to
-  // provide a cheap checksum unlikely to be accidentally matched by a random
-  // memory corruption.
-
-  // By choosing constants that satisfy the Hull-Duebell Theorem on lcg cycle
-  // length, we insure that each distinct fd value maps to a distinct checksum,
-  // which maximises the utility of our checksum.
-
-  // This code uses "unsigned int" throughout for its defined modular semantics,
-  // which implicitly gives us a divisor that is a power of two.
-
-  const unsigned int kMultiplier = 13035 * 4 + 1;
-  COMPILE_ASSERT(((kMultiplier - 1) & 3) == 0, pred_must_be_multiple_of_four);
-  const unsigned int kIncrement = 1595649551;
-  COMPILE_ASSERT(kIncrement & 1, must_be_coprime_to_powers_of_two);
-
-  *out_checksum =
-      static_cast<unsigned int>(file_.get()) * kMultiplier + kIncrement;
-}
-
-void File::MemoryCheckingScopedFD::Check() const {
-  unsigned int computed_checksum;
-  ComputeMemoryChecksum(&computed_checksum);
-  CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory";
-}
-
-void File::MemoryCheckingScopedFD::UpdateChecksum() {
-  ComputeMemoryChecksum(&file_memory_checksum_);
-}
-
 // NaCl doesn't implement system calls to open files directly.
 #if !defined(OS_NACL)
 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc
index fd79a37c..67dbbfd1 100644
--- a/base/files/file_unittest.cc
+++ b/base/files/file_unittest.cc
@@ -5,7 +5,6 @@
 #include "base/files/file.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -510,71 +509,3 @@
   EXPECT_EQ(0, info.size);
 }
 #endif  // defined(OS_WIN)
-
-#if defined(OS_POSIX) && defined(GTEST_HAS_DEATH_TEST)
-TEST(FileTest, MemoryCorruption) {
-  {
-    // Test that changing the checksum value is detected.
-    base::File file;
-    EXPECT_NE(file.file_.file_memory_checksum_,
-              static_cast<unsigned int>(file.GetPlatformFile()));
-    file.file_.file_memory_checksum_ = file.GetPlatformFile();
-    EXPECT_DEATH(file.IsValid(), "");
-
-    file.file_.UpdateChecksum();  // Do not crash on File::~File().
-  }
-
-  {
-    // Test that changing the file descriptor value is detected.
-    base::File file;
-    file.file_.file_.reset(17);
-    EXPECT_DEATH(file.IsValid(), "");
-
-    // Do not crash on File::~File().
-    ignore_result(file.file_.file_.release());
-    file.file_.UpdateChecksum();
-  }
-
-  {
-    // Test that GetPlatformFile() checks for corruption.
-    base::File file;
-    file.file_.file_memory_checksum_ = file.GetPlatformFile();
-    EXPECT_DEATH(file.GetPlatformFile(), "");
-
-    file.file_.UpdateChecksum();  // Do not crash on File::~File().
-  }
-
-  {
-    // Test that the base::File destructor checks for corruption.
-    scoped_ptr<base::File> file(new File());
-    file->file_.file_memory_checksum_ = file->GetPlatformFile();
-    EXPECT_DEATH(file.reset(), "");
-
-    // Do not crash on this thread's destructor call.
-    file->file_.UpdateChecksum();
-  }
-
-  {
-    // Test that the base::File constructor checks for corruption.
-    base::File file;
-    file.file_.file_memory_checksum_ = file.GetPlatformFile();
-    EXPECT_DEATH(File f(file.Pass()), "");
-
-    file.file_.UpdateChecksum();  // Do not crash on File::~File().
-  }
-
-  {
-    // Test that doing IO checks for corruption.
-    base::File file;
-    file.file_.file_.reset(17);  // A fake open FD value.
-
-    EXPECT_DEATH(file.Seek(File::FROM_BEGIN, 0), "");
-    EXPECT_DEATH(file.Read(0, NULL, 0), "");
-    EXPECT_DEATH(file.ReadAtCurrentPos(NULL, 0), "");
-    EXPECT_DEATH(file.Write(0, NULL, 0), "");
-
-    ignore_result(file.file_.file_.release());
-    file.file_.UpdateChecksum();
-  }
-}
-#endif  // defined(OS_POSIX)
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index 10e308aa..14e43201 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -10,7 +10,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/process/memory.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "base/win/wrapped_window_proc.h"
@@ -132,11 +131,6 @@
 // static
 LRESULT CALLBACK MessagePumpForUI::WndProcThunk(
     HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile1(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 MessagePumpForUI::WndProcThunk1"));
-
   switch (message) {
     case kMsgHaveWork:
       reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage();
@@ -145,12 +139,6 @@
       reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage();
       break;
   }
-
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile2(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 MessagePumpForUI::WndProcThunk2"));
-
   return DefWindowProc(hwnd, message, wparam, lparam);
 }
 
@@ -345,11 +333,6 @@
 }
 
 bool MessagePumpForUI::ProcessNextWindowsMessage() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile1(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 MessagePumpForUI::ProcessNextWindowsMessage1"));
-
   // If there are sent messages in the queue then PeekMessage internally
   // dispatches the message and returns false. We return true in this
   // case to ensure that the message loop peeks again instead of calling
@@ -359,11 +342,6 @@
   if (HIWORD(queue_status) & QS_SENDMESSAGE)
     sent_messages_in_queue = true;
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile2(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 MessagePumpForUI::ProcessNextWindowsMessage2"));
-
   MSG msg;
   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE)
     return ProcessMessageHelper(msg);
@@ -390,14 +368,8 @@
     return true;
 
   uint32_t action = MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT;
-  if (state_->dispatcher) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile4(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 MessagePumpForUI::ProcessMessageHelper4"));
-
+  if (state_->dispatcher)
     action = state_->dispatcher->Dispatch(msg);
-  }
   if (action & MessagePumpDispatcher::POST_DISPATCH_QUIT_LOOP)
     state_->should_quit = true;
   if (action & MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT) {
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 3f874d8..2ad7517 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -139,6 +139,11 @@
   return group_name_;
 }
 
+const std::string& FieldTrial::GetGroupNameWithoutActivation() {
+  FinalizeGroupChoice();
+  return group_name_;
+}
+
 void FieldTrial::SetForced() {
   // We might have been forced before (e.g., by CreateFieldTrial) and it's
   // first come first served, e.g., command line switch has precedence.
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index 4b35c19..899d89a5 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -149,6 +149,11 @@
   // is used as the group name. This causes a winner to be chosen if none was.
   const std::string& group_name();
 
+  // Finalizes the group choice and returns the chosen group, but does not mark
+  // the trial as active - so its state will not be reported until group_name()
+  // or similar is called.
+  const std::string& GetGroupNameWithoutActivation();
+
   // Set the field trial as forced, meaning that it was setup earlier than
   // the hard coded registration of the field trial to override it.
   // This allows the code that was hard coded to register the field trial to
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
index ed84d86..6cecc00 100644
--- a/base/metrics/field_trial_unittest.cc
+++ b/base/metrics/field_trial_unittest.cc
@@ -72,6 +72,8 @@
  private:
   MessageLoop message_loop_;
   FieldTrialList trial_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(FieldTrialTest);
 };
 
 // Test registration, and also check that destructors are called for trials
@@ -376,6 +378,28 @@
   EXPECT_EQ(active_group.group_name, active_groups[0].group_name);
 }
 
+TEST_F(FieldTrialTest, GetGroupNameWithoutActivation) {
+  const char kTrialName[] = "TestTrial";
+  const char kSecondaryGroupName[] = "SecondaryGroup";
+
+  int default_group = -1;
+  scoped_refptr<FieldTrial> trial =
+      CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
+  trial->AppendGroup(kSecondaryGroupName, 50);
+
+  // The trial should start inactive.
+  EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
+
+  // Calling |GetGroupNameWithoutActivation()| should not activate the trial.
+  std::string group_name = trial->GetGroupNameWithoutActivation();
+  EXPECT_FALSE(group_name.empty());
+  EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
+
+  // Calling |group_name()| should activate it and return the same group name.
+  EXPECT_EQ(group_name, trial->group_name());
+  EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
+}
+
 TEST_F(FieldTrialTest, Save) {
   std::string save_string;
 
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h
index 8fc88b4..cd89b2d 100644
--- a/base/numerics/safe_math.h
+++ b/base/numerics/safe_math.h
@@ -196,6 +196,16 @@
   static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; }
 
  private:
+  template <typename NumericType>
+  struct UnderlyingType {
+    using type = NumericType;
+  };
+
+  template <typename NumericType>
+  struct UnderlyingType<CheckedNumeric<NumericType>> {
+    using type = NumericType;
+  };
+
   CheckedNumericState<T> state_;
 };
 
@@ -232,7 +242,8 @@
   template <typename T>                                                       \
   template <typename Src>                                                     \
   CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) {       \
-    *this = CheckedNumeric<T>::cast(*this) OP CheckedNumeric<Src>::cast(rhs); \
+    *this = CheckedNumeric<T>::cast(*this)                                    \
+        OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs);     \
     return *this;                                                             \
   }                                                                           \
   /* Binary arithmetic operator for CheckedNumeric of different type. */      \
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index 67af9285..81873ea 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -740,3 +740,27 @@
   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
       std::numeric_limits<int64_t>::min()));
 }
+
+TEST(SafeNumerics, CompoundNumericOperations) {
+  CheckedNumeric<int> a = 1;
+  CheckedNumeric<int> b = 2;
+  CheckedNumeric<int> c = 3;
+  CheckedNumeric<int> d = 4;
+  a += b;
+  EXPECT_EQ(3, a.ValueOrDie());
+  a -= c;
+  EXPECT_EQ(0, a.ValueOrDie());
+  d /= b;
+  EXPECT_EQ(2, d.ValueOrDie());
+  d *= d;
+  EXPECT_EQ(4, d.ValueOrDie());
+
+  CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
+  EXPECT_TRUE(too_large.IsValid());
+  too_large += d;
+  EXPECT_FALSE(too_large.IsValid());
+  too_large -= d;
+  EXPECT_FALSE(too_large.IsValid());
+  too_large /= d;
+  EXPECT_FALSE(too_large.IsValid());
+}
diff --git a/base/pickle.cc b/base/pickle.cc
index 7c8ffed..489c7f8 100644
--- a/base/pickle.cc
+++ b/base/pickle.cc
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 
 #include <algorithm>  // for max()
+#include <limits>
 
 #include "base/bits.h"
 #include "base/macros.h"
@@ -338,17 +339,41 @@
 const char* Pickle::FindNext(size_t header_size,
                              const char* start,
                              const char* end) {
+  size_t pickle_size = 0;
+  if (!PeekNext(header_size, start, end, &pickle_size))
+    return NULL;
+
+  if (pickle_size > static_cast<size_t>(end - start))
+    return NULL;
+
+  return start + pickle_size;
+}
+
+// static
+bool Pickle::PeekNext(size_t header_size,
+                      const char* start,
+                      const char* end,
+                      size_t* pickle_size) {
   DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32)));
+  DCHECK_GE(header_size, sizeof(Header));
   DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
 
   size_t length = static_cast<size_t>(end - start);
   if (length < sizeof(Header))
-    return NULL;
+    return false;
 
   const Header* hdr = reinterpret_cast<const Header*>(start);
-  if (length < header_size || length - header_size < hdr->payload_size)
-    return NULL;
-  return start + header_size + hdr->payload_size;
+  if (length < header_size)
+    return false;
+
+  if (hdr->payload_size > std::numeric_limits<size_t>::max() - header_size) {
+    // If payload_size causes an overflow, we return maximum possible
+    // pickle size to indicate that.
+    *pickle_size = std::numeric_limits<size_t>::max();
+  } else {
+    *pickle_size = header_size + hdr->payload_size;
+  }
+  return true;
 }
 
 template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
diff --git a/base/pickle.h b/base/pickle.h
index b6ec116..22b8055 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -271,6 +271,18 @@
                               const char* range_start,
                               const char* range_end);
 
+  // Parse pickle header and return total size of the pickle. Data range
+  // doesn't need to contain entire pickle.
+  // Returns true if pickle header was found and parsed. Callers must check
+  // returned |pickle_size| for sanity (against maximum message size, etc).
+  // NOTE: when function successfully parses a header, but encounters an
+  // overflow during pickle size calculation, it sets |pickle_size| to the
+  // maximum size_t value and returns true.
+  static bool PeekNext(size_t header_size,
+                       const char* range_start,
+                       const char* range_end,
+                       size_t* pickle_size);
+
   // The allocation granularity of the payload.
   static const int kPayloadUnit;
 
@@ -298,6 +310,8 @@
 
   FRIEND_TEST_ALL_PREFIXES(PickleTest, DeepCopyResize);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, Resize);
+  FRIEND_TEST_ALL_PREFIXES(PickleTest, PeekNext);
+  FRIEND_TEST_ALL_PREFIXES(PickleTest, PeekNextOverflow);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNext);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextWithIncompleteHeader);
   FRIEND_TEST_ALL_PREFIXES(PickleTest, FindNextOverflow);
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc
index 6f9fcc7..f58e7ece 100644
--- a/base/pickle_unittest.cc
+++ b/base/pickle_unittest.cc
@@ -233,6 +233,88 @@
   EXPECT_FALSE(iter.ReadString16(&outstr));
 }
 
+TEST(PickleTest, PeekNext) {
+  struct CustomHeader : base::Pickle::Header {
+    int cookies[10];
+  };
+
+  Pickle pickle(sizeof(CustomHeader));
+
+  EXPECT_TRUE(pickle.WriteString("Goooooooooooogle"));
+
+  const char* pickle_data = static_cast<const char*>(pickle.data());
+
+  size_t pickle_size;
+
+  // Data range doesn't contain header
+  EXPECT_FALSE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + sizeof(CustomHeader) - 1,
+      &pickle_size));
+
+  // Data range contains header
+  EXPECT_TRUE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + sizeof(CustomHeader),
+      &pickle_size));
+  EXPECT_EQ(pickle_size, pickle.size());
+
+  // Data range contains header and some other data
+  EXPECT_TRUE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + sizeof(CustomHeader) + 1,
+      &pickle_size));
+  EXPECT_EQ(pickle_size, pickle.size());
+
+  // Data range contains full pickle
+  EXPECT_TRUE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + pickle.size(),
+      &pickle_size));
+  EXPECT_EQ(pickle_size, pickle.size());
+}
+
+TEST(PickleTest, PeekNextOverflow) {
+  struct CustomHeader : base::Pickle::Header {
+    int cookies[10];
+  };
+
+  CustomHeader header;
+
+  // Check if we can wrap around at all
+  if (sizeof(size_t) > sizeof(header.payload_size))
+    return;
+
+  const char* pickle_data = reinterpret_cast<const char*>(&header);
+
+  size_t pickle_size;
+
+  // Wrapping around is detected and reported as maximum size_t value
+  header.payload_size = static_cast<uint32_t>(
+      1 - static_cast<int32_t>(sizeof(CustomHeader)));
+  EXPECT_TRUE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + sizeof(CustomHeader),
+      &pickle_size));
+  EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
+
+  // Ridiculous pickle sizes are fine (callers are supposed to
+  // verify them)
+  header.payload_size =
+      std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
+  EXPECT_TRUE(Pickle::PeekNext(
+      sizeof(CustomHeader),
+      pickle_data,
+      pickle_data + sizeof(CustomHeader),
+      &pickle_size));
+  EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
+}
+
 TEST(PickleTest, FindNext) {
   Pickle pickle;
   EXPECT_TRUE(pickle.WriteInt(1));
diff --git a/base/power_monitor/power_monitor_device_source_win.cc b/base/power_monitor/power_monitor_device_source_win.cc
index 69bc6aa..b8b16e1d 100644
--- a/base/power_monitor/power_monitor_device_source_win.cc
+++ b/base/power_monitor/power_monitor_device_source_win.cc
@@ -5,7 +5,6 @@
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_device_source.h"
 #include "base/power_monitor/power_monitor_source.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/win/wrapped_window_proc.h"
 
 namespace base {
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 0da3a26..7cbf948 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -57,7 +57,7 @@
 };
 
 TimerExpiredTask::TimerExpiredTask(Process process) : process_(process.Pass()) {
-  watcher_.StartWatching(process_.Handle(), this);
+  watcher_.StartWatchingOnce(process_.Handle(), this);
 }
 
 TimerExpiredTask::~TimerExpiredTask() {
diff --git a/base/synchronization/waitable_event_watcher_win.cc b/base/synchronization/waitable_event_watcher_win.cc
index 46d47ac5..6533539d 100644
--- a/base/synchronization/waitable_event_watcher_win.cc
+++ b/base/synchronization/waitable_event_watcher_win.cc
@@ -22,7 +22,7 @@
     const EventCallback& callback) {
   callback_ = callback;
   event_ = event;
-  return watcher_.StartWatching(event->handle(), this);
+  return watcher_.StartWatchingOnce(event->handle(), this);
 }
 
 void WaitableEventWatcher::StopWatching() {
diff --git a/base/test/test_file_util_win.cc b/base/test/test_file_util_win.cc
index 241e69d..d2d6ac3 100644
--- a/base/test/test_file_util_win.cc
+++ b/base/test/test_file_util_win.cc
@@ -19,8 +19,6 @@
 
 namespace base {
 
-static const ptrdiff_t kOneMB = 1024 * 1024;
-
 namespace {
 
 struct PermissionInfo {
@@ -132,85 +130,21 @@
 }
 
 bool EvictFileFromSystemCache(const FilePath& file) {
-  // Request exclusive access to the file and overwrite it with no buffering.
   base::win::ScopedHandle file_handle(
       CreateFile(file.value().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
                  OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL));
   if (!file_handle.IsValid())
     return false;
 
-  // Get some attributes to restore later.
+  // Re-write the file time information to trigger cache eviction for the file.
+  // This function previously overwrote the entire file without buffering, but
+  // local experimentation validates this simplified and *much* faster approach:
+  // [1] Sysinternals RamMap no longer lists these files as cached afterwards.
+  // [2] Telemetry performance test startup.cold.blank_page reports sane values.
   BY_HANDLE_FILE_INFORMATION bhi = {0};
   CHECK(::GetFileInformationByHandle(file_handle.Get(), &bhi));
-
-  // Execute in chunks. It could be optimized. We want to do few of these since
-  // these operations will be slow without the cache.
-
-  // Allocate a buffer for the reads and the writes.
-  char* buffer = reinterpret_cast<char*>(VirtualAlloc(NULL,
-                                                      kOneMB,
-                                                      MEM_COMMIT | MEM_RESERVE,
-                                                      PAGE_READWRITE));
-
-  // If the file size isn't a multiple of kOneMB, we'll need special
-  // processing.
-  bool file_is_aligned = true;
-  int total_bytes = 0;
-  DWORD bytes_read, bytes_written;
-  for (;;) {
-    bytes_read = 0;
-    ::ReadFile(file_handle.Get(), buffer, kOneMB, &bytes_read, NULL);
-    if (bytes_read == 0)
-      break;
-
-    if (bytes_read < kOneMB) {
-      // Zero out the remaining part of the buffer.
-      // WriteFile will fail if we provide a buffer size that isn't a
-      // sector multiple, so we'll have to write the entire buffer with
-      // padded zeros and then use SetEndOfFile to truncate the file.
-      ZeroMemory(buffer + bytes_read, kOneMB - bytes_read);
-      file_is_aligned = false;
-    }
-
-    // Move back to the position we just read from.
-    // Note that SetFilePointer will also fail if total_bytes isn't sector
-    // aligned, but that shouldn't happen here.
-    DCHECK_EQ(total_bytes % kOneMB, 0);
-    SetFilePointer(file_handle.Get(), total_bytes, NULL, FILE_BEGIN);
-    if (!::WriteFile(file_handle.Get(), buffer, kOneMB, &bytes_written, NULL) ||
-        bytes_written != kOneMB) {
-      BOOL freed = VirtualFree(buffer, 0, MEM_RELEASE);
-      DCHECK(freed);
-      NOTREACHED();
-      return false;
-    }
-
-    total_bytes += bytes_read;
-
-    // If this is false, then we just processed the last portion of the file.
-    if (!file_is_aligned)
-      break;
-  }
-
-  BOOL freed = VirtualFree(buffer, 0, MEM_RELEASE);
-  DCHECK(freed);
-
-  if (!file_is_aligned) {
-    // The size of the file isn't a multiple of 1 MB, so we'll have
-    // to open the file again, this time without the FILE_FLAG_NO_BUFFERING
-    // flag and use SetEndOfFile to mark EOF.
-    file_handle.Set(NULL);
-    file_handle.Set(CreateFile(file.value().c_str(), GENERIC_WRITE, 0, NULL,
-                               OPEN_EXISTING, 0, NULL));
-    CHECK_NE(SetFilePointer(file_handle.Get(), total_bytes, NULL, FILE_BEGIN),
-             INVALID_SET_FILE_POINTER);
-    CHECK(::SetEndOfFile(file_handle.Get()));
-  }
-
-  // Restore the file attributes.
   CHECK(::SetFileTime(file_handle.Get(), &bhi.ftCreationTime,
                       &bhi.ftLastAccessTime, &bhi.ftLastWriteTime));
-
   return true;
 }
 
diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
index 176a6bd..b6bea49 100644
--- a/base/threading/platform_thread_android.cc
+++ b/base/threading/platform_thread_android.cc
@@ -49,8 +49,14 @@
 }
 
 bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) {
-  // See http://crbug.com/505474.
-  NOTIMPLEMENTED();
+  DCHECK(priority);
+  *priority = ThreadPriority::NORMAL;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  if (Java_ThreadUtils_isThreadPriorityAudio(
+      env, PlatformThread::CurrentId())) {
+    *priority = ThreadPriority::REALTIME_AUDIO;
+    return true;
+  }
   return false;
 }
 
diff --git a/base/win/message_window.cc b/base/win/message_window.cc
index 58010e4..57fe64c 100644
--- a/base/win/message_window.cc
+++ b/base/win/message_window.cc
@@ -7,7 +7,6 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/process/memory.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/win/wrapped_window_proc.h"
 
 const wchar_t kMessageWindowClassName[] = L"Chrome_MessageWindow";
diff --git a/base/win/object_watcher.cc b/base/win/object_watcher.cc
index 5ebe185..93efd06 100644
--- a/base/win/object_watcher.cc
+++ b/base/win/object_watcher.cc
@@ -16,6 +16,7 @@
     : object_(NULL),
       wait_object_(NULL),
       origin_loop_(NULL),
+      run_once_(true),
       weak_factory_(this) {
 }
 
@@ -23,36 +24,13 @@
   StopWatching();
 }
 
-bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {
-  CHECK(delegate);
-  if (wait_object_) {
-    NOTREACHED() << "Already watching an object";
-    return false;
-  }
+bool ObjectWatcher::StartWatchingOnce(HANDLE object, Delegate* delegate) {
+  return StartWatchingInternal(object, delegate, true);
+}
 
-  // Since our job is to just notice when an object is signaled and report the
-  // result back to this thread, we can just run on a Windows wait thread.
-  DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE;
-
-  // DoneWaiting can be synchronously called from RegisterWaitForSingleObject,
-  // so set up all state now.
-  callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),
-                         delegate);
-  object_ = object;
-  origin_loop_ = MessageLoop::current();
-
-  if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,
-                                   this, INFINITE, wait_flags)) {
-    DPLOG(FATAL) << "RegisterWaitForSingleObject failed";
-    object_ = NULL;
-    wait_object_ = NULL;
-    return false;
-  }
-
-  // We need to know if the current message loop is going away so we can
-  // prevent the wait thread from trying to access a dead message loop.
-  MessageLoop::current()->AddDestructionObserver(this);
-  return true;
+bool ObjectWatcher::StartWatchingMultipleTimes(HANDLE object,
+                                               Delegate* delegate) {
+  return StartWatchingInternal(object, delegate, false);
 }
 
 bool ObjectWatcher::StopWatching() {
@@ -93,7 +71,44 @@
   // that is always a pointer to a valid ObjectWater.
   ObjectWatcher* that = static_cast<ObjectWatcher*>(param);
   that->origin_loop_->task_runner()->PostTask(FROM_HERE, that->callback_);
-  that->callback_.Reset();
+  if (that->run_once_)
+    that->callback_.Reset();
+}
+
+bool ObjectWatcher::StartWatchingInternal(HANDLE object, Delegate* delegate,
+                                          bool execute_only_once) {
+  CHECK(delegate);
+  if (wait_object_) {
+    NOTREACHED() << "Already watching an object";
+    return false;
+  }
+  run_once_ = execute_only_once;
+
+  // Since our job is to just notice when an object is signaled and report the
+  // result back to this thread, we can just run on a Windows wait thread.
+  DWORD wait_flags = WT_EXECUTEINWAITTHREAD;
+  if (run_once_)
+    wait_flags |= WT_EXECUTEONLYONCE;
+
+  // DoneWaiting can be synchronously called from RegisterWaitForSingleObject,
+  // so set up all state now.
+  callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),
+                         delegate);
+  object_ = object;
+  origin_loop_ = MessageLoop::current();
+
+  if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,
+                                   this, INFINITE, wait_flags)) {
+    DPLOG(FATAL) << "RegisterWaitForSingleObject failed";
+    object_ = NULL;
+    wait_object_ = NULL;
+    return false;
+  }
+
+  // We need to know if the current message loop is going away so we can
+  // prevent the wait thread from trying to access a dead message loop.
+  MessageLoop::current()->AddDestructionObserver(this);
+  return true;
 }
 
 void ObjectWatcher::Signal(Delegate* delegate) {
@@ -101,7 +116,8 @@
   // StartWatching(). As a result, we save any state we need and clear previous
   // watcher state before signaling the delegate.
   HANDLE object = object_;
-  StopWatching();
+  if (run_once_)
+    StopWatching();
   delegate->OnObjectSignaled(object);
 }
 
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h
index d68d935..f4d6085 100644
--- a/base/win/object_watcher.h
+++ b/base/win/object_watcher.h
@@ -26,16 +26,16 @@
 //
 // Typical usage:
 //
-//   class MyClass : public base::ObjectWatcher::Delegate {
+//   class MyClass : public base::win::ObjectWatcher::Delegate {
 //    public:
 //     void DoStuffWhenSignaled(HANDLE object) {
-//       watcher_.StartWatching(object, this);
+//       watcher_.StartWatchingOnce(object, this);
 //     }
-//     virtual void OnObjectSignaled(HANDLE object) {
+//     void OnObjectSignaled(HANDLE object) override {
 //       // OK, time to do stuff!
 //     }
 //    private:
-//     base::ObjectWatcher watcher_;
+//     base::win::ObjectWatcher watcher_;
 //   };
 //
 // In the above example, MyClass wants to "do stuff" when object becomes
@@ -59,19 +59,23 @@
   ~ObjectWatcher() override;
 
   // When the object is signaled, the given delegate is notified on the thread
-  // where StartWatching is called.  The ObjectWatcher is not responsible for
+  // where StartWatchingOnce is called. The ObjectWatcher is not responsible for
   // deleting the delegate.
-  //
   // Returns true if the watch was started.  Otherwise, false is returned.
-  //
-  bool StartWatching(HANDLE object, Delegate* delegate);
+  bool StartWatchingOnce(HANDLE object, Delegate* delegate);
+
+  // Notifies the delegate, on the thread where this method is called, each time
+  // the object is set. By definition, the handle must be an auto-reset object.
+  // The caller must ensure that it (or any Windows system code) doesn't reset
+  // the event or else the delegate won't be called.
+  // Returns true if the watch was started.  Otherwise, false is returned.
+  bool StartWatchingMultipleTimes(HANDLE object, Delegate* delegate);
 
   // Stops watching.  Does nothing if the watch has already completed.  If the
   // watch is still active, then it is canceled, and the associated delegate is
   // not notified.
   //
   // Returns true if the watch was canceled.  Otherwise, false is returned.
-  //
   bool StopWatching();
 
   // Returns true if currently watching an object.
@@ -84,6 +88,10 @@
   // Called on a background thread when done waiting.
   static void CALLBACK DoneWaiting(void* param, BOOLEAN timed_out);
 
+  // Helper used by StartWatchingOnce and StartWatchingMultipleTimes.
+  bool StartWatchingInternal(HANDLE object, Delegate* delegate,
+                             bool execute_only_once);
+
   void Signal(Delegate* delegate);
 
   // MessageLoop::DestructionObserver implementation:
@@ -94,7 +102,7 @@
   HANDLE object_;             // The object being watched
   HANDLE wait_object_;        // Returned by RegisterWaitForSingleObject
   MessageLoop* origin_loop_;  // Used to get back to the origin thread
-
+  bool run_once_;
   WeakPtrFactory<ObjectWatcher> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ObjectWatcher);
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index b30ca41a..511ec49d 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -42,7 +42,7 @@
   HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
 
   QuitDelegate delegate;
-  bool ok = watcher.StartWatching(event, &delegate);
+  bool ok = watcher.StartWatchingOnce(event, &delegate);
   EXPECT_TRUE(ok);
   EXPECT_TRUE(watcher.IsWatching());
   EXPECT_EQ(event, watcher.GetWatchedObject());
@@ -64,7 +64,7 @@
   HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
 
   QuitDelegate delegate;
-  bool ok = watcher.StartWatching(event, &delegate);
+  bool ok = watcher.StartWatchingOnce(event, &delegate);
   EXPECT_TRUE(ok);
 
   watcher.StopWatching();
@@ -83,7 +83,7 @@
   // A manual-reset event that is not yet signaled.
   HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
 
-  bool ok = watcher.StartWatching(event, &delegate);
+  bool ok = watcher.StartWatchingOnce(event, &delegate);
   EXPECT_TRUE(ok);
 
   SetEvent(event);
@@ -110,7 +110,7 @@
   HANDLE event = CreateEvent(NULL, TRUE, TRUE, NULL);
 
   QuitDelegate delegate;
-  bool ok = watcher.StartWatching(event, &delegate);
+  bool ok = watcher.StartWatchingOnce(event, &delegate);
   EXPECT_TRUE(ok);
 
   MessageLoop::current()->Run();
@@ -130,12 +130,53 @@
       MessageLoop message_loop(message_loop_type);
 
       QuitDelegate delegate;
-      watcher.StartWatching(event, &delegate);
+      watcher.StartWatchingOnce(event, &delegate);
     }
   }
   CloseHandle(event);
 }
 
+class QuitAfterMultipleDelegate : public ObjectWatcher::Delegate {
+ public:
+  QuitAfterMultipleDelegate(HANDLE event, int iterations)
+      : event_(event), iterations_(iterations) {}
+  void OnObjectSignaled(HANDLE object) override {
+    if (--iterations_) {
+      SetEvent(event_);
+    } else {
+      MessageLoop::current()->QuitWhenIdle();
+    }
+  }
+
+ private:
+  HANDLE event_;
+  int iterations_;
+};
+
+void RunTest_ExecuteMultipleTimes(MessageLoop::Type message_loop_type) {
+  MessageLoop message_loop(message_loop_type);
+
+  ObjectWatcher watcher;
+  EXPECT_FALSE(watcher.IsWatching());
+
+  // An auto-reset event that is not yet signaled.
+  HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+  QuitAfterMultipleDelegate delegate(event, 2);
+  bool ok = watcher.StartWatchingMultipleTimes(event, &delegate);
+  EXPECT_TRUE(ok);
+  EXPECT_TRUE(watcher.IsWatching());
+  EXPECT_EQ(event, watcher.GetWatchedObject());
+
+  SetEvent(event);
+
+  MessageLoop::current()->Run();
+
+  EXPECT_TRUE(watcher.IsWatching());
+  EXPECT_TRUE(watcher.StopWatching());
+  CloseHandle(event);
+}
+
 }  // namespace
 
 //-----------------------------------------------------------------------------
@@ -170,5 +211,11 @@
   RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
 }
 
+TEST(ObjectWatcherTest, ExecuteMultipleTimes) {
+  RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_DEFAULT);
+  RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_IO);
+  RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_UI);
+}
+
 }  // namespace win
 }  // namespace base
diff --git a/base/win/registry.cc b/base/win/registry.cc
index 47afcbf..28e0461 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -82,7 +82,7 @@
   }
 
   callback_ = callback;
-  return object_watcher_.StartWatching(watch_event_.Get(), this);
+  return object_watcher_.StartWatchingOnce(watch_event_.Get(), this);
 }
 
 // RegKey ----------------------------------------------------------------------
diff --git a/breakpad/breakpad.gyp b/breakpad/breakpad.gyp
index d422f07..52bf0db 100644
--- a/breakpad/breakpad.gyp
+++ b/breakpad/breakpad.gyp
@@ -983,6 +983,27 @@
           ],
         }
       ],
+      'conditions': [
+        ['test_isolation_mode != "noop"',
+          {
+            'targets': [
+              {
+                'target_name': 'breakpad_unittests_apk_run',
+                'type': 'none',
+                'dependencies': [
+                  'breakpad_unittests',
+                ],
+                'includes': [
+                  '../build/isolate.gypi',
+                ],
+                'sources': [
+                  'breakpad_unittests_apk.isolate',
+                ],
+              },
+            ]
+          }
+        ],
+      ],
     }],
   ],
 }
diff --git a/breakpad/breakpad_unittests_apk.isolate b/breakpad/breakpad_unittests_apk.isolate
new file mode 100644
index 0000000..0f5aa51
--- /dev/null
+++ b/breakpad/breakpad_unittests_apk.isolate
@@ -0,0 +1,19 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'includes': [
+    '../build/android/android.isolate',
+    'breakpad_unittests.isolate',
+  ],
+  'variables': {
+    'command': [
+      '<(PRODUCT_DIR)/bin/run_breakpad_unittests',
+    ],
+    'files': [
+      '<(PRODUCT_DIR)/bin/run_breakpad_unittests',
+      '<(PRODUCT_DIR)/breakpad_unittests',
+      'breakpad_unittests.isolate',
+    ]
+  },
+}
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn
index ef953a6..e45cf2da 100644
--- a/build/android/BUILD.gn
+++ b/build/android/BUILD.gn
@@ -32,12 +32,27 @@
   output_jar = "$root_out_dir/lib.java/android.interface.jar"
 }
 
+# Copy to the lib.unstripped directory so that gdb can easily find it.
+copy("cpplib_unstripped") {
+  _soname = "libc++_shared.so"
+  sources = [
+    "${android_libcpp_root}/libs/${android_app_abi}/${_soname}",
+  ]
+  outputs = [
+    "${root_out_dir}/lib.unstripped/${_soname}",
+  ]
+}
+
 action("cpplib_stripped") {
   _strip_bin = "${android_tool_prefix}strip"
   _soname = "libc++_shared.so"
-  _input_so = "${android_libcpp_root}/libs/${android_app_abi}/${_soname}"
+  _input_so = "${root_out_dir}/lib.unstripped/${_soname}"
   _output_so = "${root_shlib_dir}/${_soname}"
 
+  deps = [
+    ":cpplib_unstripped",
+  ]
+
   script = "//build/gn_run_binary.py"
   inputs = [
     _strip_bin,
diff --git a/build/android/adb_gdb b/build/android/adb_gdb
index 65ec7b20..2d670dd 100755
--- a/build/android/adb_gdb
+++ b/build/android/adb_gdb
@@ -707,12 +707,14 @@
 #
 detect_symbol_dir () {
   local SUBDIRS SUBDIR LIST DIR DIR_LIBS TSTAMP
-  # Note: Ninja places debug libraries under out/$BUILDTYPE/lib/, while
-  # Make places then under out/$BUILDTYPE/lib.target.
+  # Make places them under out/$BUILDTYPE/lib.target.
+  # GYP places debug libraries under out/$BUILDTYPE/lib
+  # GN places them under out/$BUILDTYPE/lib.unstripped
   if [ "$1" ]; then
-    SUBDIRS="$1/lib $1/lib.target"
+    SUBDIRS="$1/lib $1/lib.target $1/lib.unstripped"
   else
     SUBDIRS="Release/lib Debug/lib Release/lib.target Debug/lib.target"
+    SUBDIRS+=" Release/lib.unstripped Debug/lib.unstripped"
   fi
   LIST=$TMPDIR/scan-subdirs-$$.txt
   printf "" > "$LIST"
diff --git a/build/android/android.isolate b/build/android/android.isolate
index 8d6291b..b2a04bd 100644
--- a/build/android/android.isolate
+++ b/build/android/android.isolate
@@ -9,6 +9,7 @@
       '../../third_party/android_tools/sdk/platform-tools/',
       '../../third_party/appurify-python/',
       '../../third_party/requests/',
+      '../../tools/swarming_client/',
       '<(PRODUCT_DIR)/md5sum_bin_host',
       '<(PRODUCT_DIR)/md5sum_dist/',
       'devil/',
diff --git a/build/android/devil/android/device_utils.py b/build/android/devil/android/device_utils.py
index e01f462..432677f 100644
--- a/build/android/devil/android/device_utils.py
+++ b/build/android/devil/android/device_utils.py
@@ -752,7 +752,7 @@
     def handle_large_output(cmd, large_output_mode):
       if large_output_mode:
         with device_temp_file.DeviceTempFile(self.adb) as large_output_file:
-          cmd = '%s > %s' % (cmd, large_output_file.name)
+          cmd = '( %s )>%s' % (cmd, large_output_file.name)
           logging.debug('Large output mode enabled. Will write output to '
                         'device and read results from file.')
           handle_large_command(cmd)
diff --git a/build/android/devil/android/device_utils_test.py b/build/android/devil/android/device_utils_test.py
index d6d64319..5eb0525e 100755
--- a/build/android/devil/android/device_utils_test.py
+++ b/build/android/devil/android/device_utils_test.py
@@ -857,7 +857,7 @@
   def testRunShellCommand_largeOutput_enabled(self):
     cmd = 'echo $VALUE'
     temp_file = MockTempFile('/sdcard/temp-123')
-    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    cmd_redirect = '( %s )>%s' % (cmd, temp_file.name)
     with self.assertCalls(
         (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
             temp_file),
@@ -878,7 +878,7 @@
   def testRunShellCommand_largeOutput_disabledTrigger(self):
     cmd = 'echo $VALUE'
     temp_file = MockTempFile('/sdcard/temp-123')
-    cmd_redirect = '%s > %s' % (cmd, temp_file.name)
+    cmd_redirect = '( %s )>%s' % (cmd, temp_file.name)
     with self.assertCalls(
         (self.call.adb.Shell(cmd), self.ShellError('', None)),
         (mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
diff --git a/build/android/devil/android/sdk/adb_wrapper.py b/build/android/devil/android/sdk/adb_wrapper.py
index bf68b569..77fbdc1 100644
--- a/build/android/devil/android/sdk/adb_wrapper.py
+++ b/build/android/devil/android/sdk/adb_wrapper.py
@@ -267,7 +267,7 @@
     if expect_status is None:
       args = ['shell', command]
     else:
-      args = ['shell', '(%s);echo %%$?' % command.rstrip()]
+      args = ['shell', '( %s );echo %%$?' % command.rstrip()]
     output = self._RunDeviceAdbCmd(args, timeout, retries, check_error=False)
     if expect_status is not None:
       output_end = output.rfind('%')
diff --git a/build/android/gyp/aidl.py b/build/android/gyp/aidl.py
index d5aa5467..85ceeae3e 100755
--- a/build/android/gyp/aidl.py
+++ b/build/android/gyp/aidl.py
@@ -9,7 +9,9 @@
 
 import optparse
 import os
+import re
 import sys
+import zipfile
 
 from util import build_utils
 
@@ -42,7 +44,13 @@
       ]
       build_utils.CheckOutput(aidl_cmd)
 
-    build_utils.ZipDir(options.srcjar, temp_dir)
+    with zipfile.ZipFile(options.srcjar, 'w') as srcjar:
+      for path in build_utils.FindInDirectory(temp_dir, '*.java'):
+        with open(path) as fileobj:
+          data = fileobj.read()
+        pkg_name = re.search(r'^\s*package\s+(.*?)\s*;', data, re.M).group(1)
+        arcname = '%s/%s' % (pkg_name.replace('.', '/'), os.path.basename(path))
+        srcjar.writestr(arcname, data)
 
   if options.depfile:
     build_utils.WriteDepfile(
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index 728c49d5..eb17acc4 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -322,6 +322,9 @@
       # javac pulling a default encoding from the user's environment.
       '-encoding', 'UTF-8',
       '-classpath', ':'.join(compile_classpath),
+      # Prevent compiler from compiling .java files not listed as inputs.
+      # See: http://blog.ltgt.net/most-build-tools-misuse-javac/
+      '-sourcepath', ''
   ))
 
   if options.bootclasspath:
@@ -332,8 +335,7 @@
         ])
 
   if options.chromium_code:
-    # TODO(aurimas): re-enable '-Xlint:deprecation' checks once they are fixed.
-    javac_cmd.extend(['-Xlint:unchecked'])
+    javac_cmd.extend(['-Xlint:unchecked', '-Xlint:deprecation'])
   else:
     # XDignore.symbol.file makes javac compile against rt.jar instead of
     # ct.sym. This means that using a java internal package/class will not
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index c83c129..441a7987 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -407,7 +407,7 @@
           gen_dir,
           options.extra_res_packages,
           options.extra_r_text_files,
-          options.shared_resources,
+          options.shared_resources or options.app_as_shared_lib,
           options.include_all_resources)
 
     # This is the list of directories with resources to put in the final .zip
diff --git a/build/android/gyp/util/md5_check.py b/build/android/gyp/util/md5_check.py
index 699d3bf..3020944 100644
--- a/build/android/gyp/util/md5_check.py
+++ b/build/android/gyp/util/md5_check.py
@@ -14,6 +14,9 @@
 # When set and a difference is detected, a diff of what changed is printed.
 _PRINT_MD5_DIFFS = int(os.environ.get('PRINT_MD5_DIFFS', 0))
 
+# An escape hatch that causes all targets to be rebuilt.
+_FORCE_REBUILD = int(os.environ.get('FORCE_REBUILD', 0))
+
 
 def CallAndRecordIfStale(
     function, record_path=None, input_paths=None, input_strings=None,
@@ -60,6 +63,7 @@
       new_metadata.AddFile(path, _Md5ForPath(path))
 
   old_metadata = None
+  force = force or _FORCE_REBUILD
   missing_outputs = [x for x in output_paths if force or not os.path.exists(x)]
   # When outputs are missing, don't bother gathering change information.
   if not missing_outputs and os.path.exists(record_path):
@@ -79,11 +83,6 @@
     print changes.DescribeDifference()
     print '=' * 80
 
-  # Delete the old metdata beforehand since failures leave it in an
-  # inderterminate state.
-  if old_metadata:
-    os.unlink(record_path)
-
   args = (changes,) if pass_changes else ()
   function(*args)
 
diff --git a/build/android/locale_pak_resources.gypi b/build/android/locale_pak_resources.gypi
index 6f8e56f8..020b831 100644
--- a/build/android/locale_pak_resources.gypi
+++ b/build/android/locale_pak_resources.gypi
@@ -12,6 +12,8 @@
 # Variables:
 #   locale_pak_files - List of .pak files to process.
 #     Names must be of the form "en.pak" or "en-US.pak".
+#   resource_zip_path - the path of generated zip file, optional, normally, you
+#     don't need to set this variable.
 #
 # Example
 #  {
@@ -25,12 +27,12 @@
 #
 {
   'variables': {
-    'resources_zip_path': '<(PRODUCT_DIR)/res.java/<(_target_name).zip',
+    'resources_zip_path%': '<(PRODUCT_DIR)/res.java/<(_target_name).zip',
   },
   'all_dependent_settings': {
     'variables': {
-      'additional_input_paths': ['<(resources_zip_path)'],
-      'dependencies_res_zip_paths': ['<(resources_zip_path)'],
+      'additional_locale_input_paths': ['<(resources_zip_path)'],
+      'dependencies_locale_zip_paths': ['<(resources_zip_path)'],
     },
   },
   'actions': [{
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index faf980f..745248b 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -24,6 +24,7 @@
 from devil.android import battery_utils
 from devil.android import device_blacklist
 from devil.android import device_errors
+from devil.android import device_temp_file
 from devil.android import device_utils
 from devil.android.sdk import version_codes
 from devil.utils import run_tests_helper
@@ -99,6 +100,7 @@
       device.adb.WaitForDevice()
 
   try:
+    CheckExternalStorage(device)
     if should_run_phase(_PHASES.WIPE):
       if options.chrome_specific_wipe:
         run_phase(WipeChromeData)
@@ -126,6 +128,23 @@
                       str(device))
     blacklist.Extend([str(device)])
 
+def CheckExternalStorage(device):
+  """Checks that storage is writable and if not makes it writable.
+
+  Arguments:
+    device: The device to check.
+  """
+  try:
+    with device_temp_file.DeviceTempFile(
+        device.adb, suffix='.sh', dir=device.GetExternalStoragePath()):
+      pass
+  except device_errors.CommandFailedError:
+    logging.info('External storage not writable. Remounting / as RW')
+    device.RunShellCommand(['mount', '-o', 'remount,rw', '/'],
+                           check_return=True, as_root=True)
+    with device_temp_file.DeviceTempFile(
+        device.adb, suffix='.sh', dir=device.GetExternalStoragePath()):
+      pass
 
 def WipeChromeData(device, options):
   """Wipes chrome specific data from device
@@ -392,7 +411,6 @@
   subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
                                  'build/android/host_heartbeat.py')])
 
-
 def KillHostHeartbeat():
   ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   stdout, _ = ps.communicate()
@@ -402,7 +420,6 @@
     pid = re.findall(r'(\S+)', match)[1]
     subprocess.call(['kill', str(pid)])
 
-
 def main():
   # Recommended options on perf bots:
   # --disable-network
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index 4523b74a..fd1f90e22 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -77,6 +77,9 @@
         'NativeTestActivity')
 _EXTRA_RUN_IN_SUB_THREAD = (
     'org.chromium.native_test.NativeTestActivity.RunInSubThread')
+EXTRA_SHARD_NANO_TIMEOUT = (
+    'org.chromium.native_test.NativeTestInstrumentationTestRunner.'
+        'ShardNanoTimeout')
 _EXTRA_SHARD_SIZE_LIMIT = (
     'org.chromium.native_test.NativeTestInstrumentationTestRunner.'
         'ShardSizeLimit')
@@ -156,6 +159,7 @@
         self._extras[_EXTRA_RUN_IN_SUB_THREAD] = 1
       if self._suite in BROWSER_TEST_SUITES:
         self._extras[_EXTRA_SHARD_SIZE_LIMIT] = 1
+        self._extras[EXTRA_SHARD_NANO_TIMEOUT] = int(60e9)
 
     if not os.path.exists(self._exe_path):
       self._exe_path = None
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 3c0c107..6595004 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -137,6 +137,7 @@
   def __init__(self, args, isolate_delegate, error_func):
     super(InstrumentationTestInstance, self).__init__()
 
+    self._additional_apks = []
     self._apk_under_test = None
     self._apk_under_test_permissions = None
     self._package_info = None
@@ -216,6 +217,11 @@
     if not self._package_info:
       logging.warning('Unable to find package info for %s', self._test_package)
 
+    for apk in args.additional_apks:
+      if not os.path.exists(apk):
+        error_func('Unable to find additional APK: %s' % apk)
+    self._additional_apks = args.additional_apks
+
   def _initializeDataDependencyAttributes(self, args, isolate_delegate):
     self._data_deps = []
     if args.isolate_file_path:
@@ -286,6 +292,10 @@
       self._driver_apk = None
 
   @property
+  def additional_apks(self):
+    return self._additional_apks
+
+  @property
   def apk_under_test(self):
     return self._apk_under_test
 
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py
index e3176e6..b6bcdae2 100644
--- a/build/android/pylib/local/device/local_device_gtest_run.py
+++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -21,9 +21,6 @@
     'org.chromium.native_test.NativeTestActivity.CommandLineFile')
 _EXTRA_COMMAND_LINE_FLAGS = (
     'org.chromium.native_test.NativeTestActivity.CommandLineFlags')
-_EXTRA_SHARD_NANO_TIMEOUT = (
-    'org.chromium.native_test.NativeTestInstrumentationTestRunner'
-        '.ShardNanoTimeout')
 _EXTRA_TEST_LIST = (
     'org.chromium.native_test.NativeTestInstrumentationTestRunner'
         '.TestList')
@@ -72,12 +69,13 @@
   def Run(self, test, device, flags=None, **kwargs):
     extras = dict(self._extras)
 
-    if 'timeout' in kwargs:
+    if ('timeout' in kwargs
+        and gtest_test_instance.EXTRA_SHARD_NANO_TIMEOUT not in extras):
       # Make sure the instrumentation doesn't kill the test before the
       # scripts do. The provided timeout value is in seconds, but the
       # instrumentation deals with nanoseconds because that's how Android
       # handles time.
-      extras[_EXTRA_SHARD_NANO_TIMEOUT] = int(
+      extras[gtest_test_instance.EXTRA_SHARD_NANO_TIMEOUT] = int(
           kwargs['timeout'] * _SECONDS_TO_NANOS)
 
     with device_temp_file.DeviceTempFile(device.adb) as command_line_file:
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index f36c745..daf2a7d7 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -68,6 +68,8 @@
                   permissions=self._test_instance.apk_under_test_permissions)
       dev.Install(self._test_instance.test_apk,
                   permissions=self._test_instance.test_permissions)
+      for apk in self._test_instance.additional_apks:
+        dev.Install(apk)
 
       external_storage = dev.GetExternalStoragePath()
       host_device_tuples = [
diff --git a/build/android/pylib/perf/test_options.py b/build/android/pylib/perf/test_options.py
index eff928e1..2764e42 100644
--- a/build/android/pylib/perf/test_options.py
+++ b/build/android/pylib/perf/test_options.py
@@ -17,6 +17,7 @@
     'single_step',
     'collect_chartjson_data',
     'output_chartjson_data',
+    'get_output_dir_archive',
     'max_battery_temp',
     'min_battery_level',
 ])
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index 80a89a38..32c4f81 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -47,6 +47,7 @@
 """
 
 import collections
+import io
 import json
 import logging
 import os
@@ -56,6 +57,7 @@
 import tempfile
 import threading
 import time
+import zipfile
 
 from devil.android import battery_utils
 from devil.android import device_errors
@@ -89,6 +91,7 @@
       data['start_time'] = persisted_result['start_time']
       data['end_time'] = persisted_result['end_time']
       data['total_time'] = persisted_result['total_time']
+      data['has_archive'] = persisted_result['archive_bytes'] is not None
     step_values.append(data)
 
   with file(json_output, 'w') as o:
@@ -96,12 +99,13 @@
   return 0
 
 
-def PrintTestOutput(test_name, json_file_name=None):
+def PrintTestOutput(test_name, json_file_name=None, archive_file_name=None):
   """Helper method to print the output of previously executed test_name.
 
   Args:
     test_name: name of the test that has been previously executed.
     json_file_name: name of the file to output chartjson data to.
+    archive_file_name: name of the file to write the compressed ZIP archive.
 
   Returns:
     exit code generated by the test step.
@@ -125,6 +129,13 @@
     with file(json_file_name, 'w') as f:
       f.write(persisted_result['chartjson'])
 
+  if archive_file_name:
+    if persisted_result['archive_bytes'] is not None:
+      with file(archive_file_name, 'wb') as f:
+        f.write(persisted_result['archive_bytes'])
+    else:
+      logging.error('The output dir was not archived.')
+
   return persisted_result['exit_code']
 
 
@@ -242,6 +253,25 @@
                     ' the test.')
       return ''
 
+  def _ArchiveOutputDir(self):
+    """Archive all files in the output dir, and return as compressed bytes."""
+    with io.BytesIO() as archive:
+      with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as contents:
+        num_files = 0
+        for absdir, _, files in os.walk(self._output_dir):
+          reldir = os.path.relpath(absdir, self._output_dir)
+          for filename in files:
+            src_path = os.path.join(absdir, filename)
+            # We use normpath to turn './file.txt' into just 'file.txt'.
+            dst_path = os.path.normpath(os.path.join(reldir, filename))
+            contents.write(src_path, dst_path)
+            num_files += 1
+      if num_files:
+        logging.info('%d files in the output dir were archived.', num_files)
+      else:
+        logging.warning('No files in the output dir. Archive is empty.')
+      return archive.getvalue()
+
   def _LaunchPerfTest(self, test_name):
     """Runs a perf test.
 
@@ -261,11 +291,11 @@
     except Exception as e: # pylint: disable=broad-except
       logging.error('Exception when tearing down device %s', e)
 
-    cmd = ('%s --device %s' %
-           (self._tests['steps'][test_name]['cmd'],
-            self.device_serial))
+    test_config = self._tests['steps'][test_name]
+    cmd = ('%s --device %s' % (test_config['cmd'], self.device_serial))
 
-    if self._options.collect_chartjson_data:
+    if (self._options.collect_chartjson_data
+        or test_config.get('archive_output_dir')):
       self._output_dir = tempfile.mkdtemp()
       cmd = cmd + ' --output-dir=%s' % self._output_dir
 
@@ -285,7 +315,7 @@
     logging.info('%s : %s', test_name, cmd)
     start_time = time.time()
 
-    timeout = self._tests['steps'][test_name].get('timeout', 3600)
+    timeout = test_config.get('timeout', 3600)
     if self._options.no_timeout:
       timeout = None
     logging.info('Timeout for %s test: %s', test_name, timeout)
@@ -294,6 +324,7 @@
       full_cmd = 'echo %s' % cmd
 
     logfile = sys.stdout
+    archive_bytes = None
     if self._options.single_step:
       # Just print a heart-beat so that the outer buildbot scripts won't timeout
       # without response.
@@ -305,6 +336,8 @@
       exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
           full_cmd, timeout, cwd=cwd, shell=True, logfile=logfile)
       json_output = self._ReadChartjsonOutput()
+      if test_config.get('archive_output_dir'):
+        archive_bytes = self._ArchiveOutputDir()
     except cmd_helper.TimeoutError as e:
       exit_code = -1
       output = e.output
@@ -344,6 +377,7 @@
         'name': test_name,
         'output': [output],
         'chartjson': json_output,
+        'archive_bytes': archive_bytes,
         'exit_code': exit_code,
         'actual_exit_code': actual_exit_code,
         'result_type': result_type,
diff --git a/build/android/pylib/remote/device/remote_device_gtest_run.py b/build/android/pylib/remote/device/remote_device_gtest_run.py
index e22c6d5..02d3154a 100644
--- a/build/android/pylib/remote/device/remote_device_gtest_run.py
+++ b/build/android/pylib/remote/device/remote_device_gtest_run.py
@@ -10,14 +10,12 @@
 
 from pylib import constants
 from pylib.base import base_test_result
+from pylib.gtest import gtest_test_instance
 from pylib.remote.device import remote_device_test_run
 
 
 _EXTRA_COMMAND_LINE_FILE = (
     'org.chromium.native_test.NativeTestActivity.CommandLineFile')
-_EXTRA_SHARD_NANO_TIMEOUT = (
-    'org.chromium.native_test.NativeTestInstrumentationTestRunner'
-        '.ShardNanoTimeout')
 
 
 class RemoteDeviceGtestTestRun(remote_device_test_run.RemoteDeviceTestRun):
@@ -51,9 +49,9 @@
 
     # pylint: disable=protected-access
     with tempfile.NamedTemporaryFile(suffix='.flags.txt') as flag_file:
-      env_vars = {
-        _EXTRA_SHARD_NANO_TIMEOUT: int(900e9),
-      }
+      env_vars = dict(self._test_instance.extras)
+      if gtest_test_instance.EXTRA_SHARD_NANO_TIMEOUT not in env_vars:
+        env_vars[gtest_test_instance.EXTRA_SHARD_NANO_TIMEOUT] = int(900e9)
       filter_string = self._test_instance._GenerateDisabledFilterString(None)
       if filter_string:
         flag_file.write('_ --gtest_filter=%s' % filter_string)
diff --git a/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py b/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py
index 1057970..8858b06 100644
--- a/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py
@@ -51,7 +51,8 @@
           self._test_instance.driver_apk,
           self._test_instance.driver_name,
           environment_variables=env_vars,
-          extra_apks=[self._test_instance.test_apk])
+          extra_apks=([self._test_instance.test_apk] +
+                      self._test_instance.additional_apks))
 
   #override
   def _ParseTestResults(self):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index e756006c..16a2260 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -332,6 +332,10 @@
                      help=('The name of the apk containing the tests '
                            '(without the .apk extension; '
                            'e.g. "ContentShellTest").'))
+  group.add_argument('--additional-apk', action='append',
+                     dest='additional_apks', default=[],
+                     help='Additional apk that must be installed on '
+                          'the device when the tests are run')
   group.add_argument('--coverage-dir',
                      help=('Directory in which to place all generated '
                            'EMMA coverage files.'))
@@ -593,6 +597,10 @@
       default='',
       help='Write out chartjson into the given file.')
   group.add_argument(
+      '--get-output-dir-archive', metavar='FILENAME',
+      help='Write the chached output directory archived by a step into the'
+      ' given ZIP file.')
+  group.add_argument(
       '--flaky-steps',
       help=('A JSON file containing steps that are flaky '
             'and will have its exit code ignored.'))
@@ -638,7 +646,8 @@
       args.steps, args.flaky_steps, args.output_json_list,
       args.print_step, args.no_timeout, args.test_filter,
       args.dry_run, args.single_step, args.collect_chartjson_data,
-      args.output_chartjson_data, args.max_battery_temp, args.min_battery_level)
+      args.output_chartjson_data, args.get_output_dir_archive,
+      args.max_battery_temp, args.min_battery_level)
 
 
 def AddPythonTestOptions(parser):
@@ -808,7 +817,8 @@
   # Just print the results from a single previously executed step.
   if perf_options.print_step:
     return perf_test_runner.PrintTestOutput(
-        perf_options.print_step, perf_options.output_chartjson_data)
+        perf_options.print_step, perf_options.output_chartjson_data,
+        perf_options.get_output_dir_archive)
 
   runner_factory, tests, devices = perf_setup.Setup(
       perf_options, active_devices)
@@ -959,9 +969,9 @@
                        else itertools.count())
         for _ in repetitions:
           iteration_results = test_run.RunTests()
-          results.append(iteration_results)
 
           if iteration_results is not None:
+            results.append(iteration_results)
             report_results.LogFull(
                 results=iteration_results,
                 test_type=test.TestType(),
diff --git a/build/common.gypi b/build/common.gypi
index ebf5e4e..cce7b3c 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -1874,7 +1874,6 @@
             'arm_arch%': '',
             'arm_tune%': 'cortex-a9',
             'arm_thumb%': 1,
-            'video_hole%': 1,
           }],
         ],
       }],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index f7c52f8a..39f79e6 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -168,6 +168,9 @@
   if (is_msan) {
     defines += [ "MEMORY_SANITIZER" ]
   }
+  if (is_ubsan) {
+    defines += [ "UNDEFINED_SANITIZER" ]
+  }
   if (enable_webrtc) {
     defines += [ "ENABLE_WEBRTC=1" ]
   }
@@ -449,9 +452,7 @@
     # then delete the precompile.c.obj file, then build again.
     cflags_c = [ "/wd4206" ]
   } else if (is_mac && !is_official_build && !use_goma) {
-    # TODO(andybons): enable this when GCC PCH support in the binary has been
-    # rolled.
-    #precompiled_header = "build/precompile.h"
-    #precompiled_source = "//build/precompile.h"
+    precompiled_header = "build/precompile.h"
+    precompiled_source = "//build/precompile.h"
   }
 }
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 234332b..2ff1f8c4 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -356,6 +356,7 @@
   "//build/config/compiler:default_symbols",
   "//build/config/compiler:no_rtti",
   "//build/config/compiler:runtime_library",
+  "//build/config/sanitizers:default_sanitizer_flags",
 ]
 if (is_win) {
   _native_compiler_configs += [
@@ -387,6 +388,11 @@
   _native_compiler_configs += [ "//build/config/android:sdk" ]
 }
 
+if (is_android) {
+  _native_compiler_configs +=
+      [ "//build/config/android:default_cygprofile_instrumentation" ]
+}
+
 if (is_clang && !is_nacl) {
   _native_compiler_configs += [
     "//build/config/clang:find_bad_constructs",
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn
index 0514b43..0503bef 100644
--- a/build/config/android/BUILD.gn
+++ b/build/config/android/BUILD.gn
@@ -115,6 +115,10 @@
       abi_target,
     ]
   }
+
+  # Assign any flags set for the C compiler to asmflags so that they are sent
+  # to the assembler.
+  asmflags = cflags
 }
 
 # This is included by reference in the //build/config/compiler:runtime_library
@@ -194,6 +198,7 @@
 config("sdk") {
   if (sysroot != "") {
     cflags = [ "--sysroot=" + sysroot ]
+    asmflags = [ "--sysroot=" + sysroot ]
     ldflags = [ "--sysroot=" + sysroot ]
 
     # Need to get some linker flags out of the sysroot.
@@ -209,6 +214,7 @@
 
 config("executable_config") {
   cflags = [ "-fPIE" ]
+  asmflags = [ "-fPIE" ]
   ldflags = [ "-pie" ]
 }
 
@@ -216,3 +222,37 @@
   ldflags = [ "-Wl,--version-script=" +
               rebase_path("//build/android/android_no_jni_exports.lst") ]
 }
+
+# Instrumentation -------------------------------------------------------------
+#
+# The BUILDCONFIG file sets the "default_cygprofile_instrumentation" config on
+# targets by default. You can override whether the cygprofile instrumentation is
+# used on a per-target basis:
+#
+# configs -= [ "//build/config/android:default_cygprofile_instrumentation" ]
+# configs += [ "//build/config/android:no_cygprofile_instrumentation" ]
+
+config("default_cygprofile_instrumentation") {
+  if (use_order_profiling) {
+    configs = [ ":cygprofile_instrumentation" ]
+  } else {
+    configs = [ ":no_cygprofile_instrumentation" ]
+  }
+}
+
+config("cygprofile_instrumentation") {
+  cflags = [
+    "-finstrument-functions",
+
+    # Allow mmx intrinsics to inline, so that the compiler can expand the intrinsics.
+    "-finstrument-functions-exclude-file-list=mmintrin.h",
+
+    # Avoid errors with current NDK:
+    # "third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/include/arm_neon.h:3426:3: error: argument must be a constant"
+    "-finstrument-functions-exclude-file-list=arm_neon.h,SaturatedArithmeticARM.h",
+  ]
+  defines = [ "CYGPROFILE_INSTRUMENTATION=1" ]
+}
+
+config("no_cygprofile_instrumentation") {
+}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index 1b77769..7abf51a 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -75,6 +75,10 @@
 
     # Speed up dexing using dx --incremental.
     incremental_dx = true
+
+    # Adds intrumentation to each function. Writes a file with the order that
+    # functions are called at startup.
+    use_order_profiling = false
   }
 
   # Host stuff -----------------------------------------------------------------
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 00ce47b4..0a8f64df 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -489,7 +489,9 @@
                            ])
     script = "//build/android/gyp/apkbuilder.py"
     depfile = "$target_gen_dir/$target_name.d"
-    data_deps = [ "//tools/android/md5sum" ]  # Used when deploying APKs
+    data_deps = [
+      "//tools/android/md5sum",
+    ]  # Used when deploying APKs
 
     inputs = [
       invoker.resource_packaged_apk_path,
@@ -1183,6 +1185,8 @@
   _requires_android =
       defined(invoker.requires_android) && invoker.requires_android
   assert(_requires_android || true)  # Mark as used.
+  _run_findbugs = defined(invoker.run_findbugs) && invoker.run_findbugs
+  assert(_run_findbugs || true)  # Mark as used.
 
   if (_supports_android) {
     _dex_path = _base_path + ".dex.jar"
@@ -1322,10 +1326,7 @@
         }
       }
 
-      if (defined(invoker.run_findbugs)) {
-        run_findbugs = invoker.run_findbugs
-      }
-      if (run_findbugs) {
+      if (_run_findbugs) {
         _final_datadeps += [ ":${_template_name}__findbugs" ]
         findbugs("${_template_name}__findbugs") {
           build_config = _build_config
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 74dec11..ef8fbd4 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -93,6 +93,7 @@
 # where stuff should go. Put warning related stuff in the "warnings" config.
 
 config("compiler") {
+  asmflags = []
   cflags = []
   cflags_c = []
   cflags_cc = []
@@ -140,110 +141,13 @@
     }
 
     # Linker warnings.
-    if (!(is_chromeos && current_cpu == "arm") && !is_mac && !is_ios) {
+    if (!(is_chromeos && current_cpu == "arm") &&
+        !(is_android && use_order_profiling) && !is_mac && !is_ios) {
       # TODO(jochen): Enable this on chromeos on arm. http://crbug.com/356580
+      # TODO(azarchs): Fix link errors when linking with order_profiling=1
+      # crbug.com/485542
       ldflags += [ "-Wl,--fatal-warnings" ]
     }
-
-    # Common options for AddressSanitizer, LeakSanitizer, ThreadSanitizer,
-    # MemorySanitizer and non-official CFI builds.
-    if (using_sanitizer || (is_cfi && !is_official_build)) {
-      cflags += [
-        "-fno-omit-frame-pointer",
-        "-gline-tables-only",
-      ]
-    }
-    if (is_asan) {
-      asan_blacklist_path =
-          rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir)
-      cflags += [
-        "-fsanitize=address",
-        "-fsanitize-blacklist=$asan_blacklist_path",
-      ]
-      if (is_mac) {
-        cflags += [ "-mllvm -asan-globals=0" ]  # http://crbug.com/352073
-        # TODO(GYP): deal with mac_bundles.
-      }
-    }
-    if (is_lsan) {
-      cflags += [ "-fsanitize=leak" ]
-    }
-    if (is_tsan) {
-      tsan_blacklist_path =
-          rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir)
-      cflags += [
-        "-fsanitize=thread",
-        "-fsanitize-blacklist=$tsan_blacklist_path",
-      ]
-    }
-    if (is_msan) {
-      msan_blacklist_path =
-          rebase_path("//tools/msan/blacklist.txt", root_build_dir)
-      cflags += [
-        "-fsanitize=memory",
-        "-fsanitize-memory-track-origins=$msan_track_origins",
-        "-fsanitize-blacklist=$msan_blacklist_path",
-      ]
-    }
-    if (is_cfi && !is_nacl) {
-      cfi_blacklist_path =
-          rebase_path("//tools/cfi/blacklist.txt", root_build_dir)
-      cflags += [
-        "-flto",
-        "-fsanitize=cfi-vcall",
-        "-fsanitize=cfi-derived-cast",
-        "-fsanitize=cfi-unrelated-cast",
-        "-fsanitize-blacklist=$cfi_blacklist_path",
-      ]
-      ldflags += [
-        "-flto",
-        "-fsanitize=cfi-vcall",
-        "-fsanitize=cfi-derived-cast",
-        "-fsanitize=cfi-unrelated-cast",
-      ]
-
-      # Apply a lower LTO optimization level in non-official builds.
-      if (!is_official_build) {
-        if (is_linux) {
-          ldflags += [ "-Wl,-plugin-opt,O1" ]
-        } else if (is_mac) {
-          ldflags += [ "-Wl,-mllvm,-O1" ]
-        }
-      }
-
-      # Work-around for http://openradar.appspot.com/20356002
-      if (is_mac) {
-        ldflags += [ "-Wl,-all_load" ]
-      }
-
-      # Without this flag, LTO produces a .text section that is larger
-      # than the maximum call displacement, preventing the linker from
-      # relocating calls (http://llvm.org/PR22999).
-      if (current_cpu == "arm") {
-        ldflags += [ "-Wl,-plugin-opt,-function-sections" ]
-      }
-
-      if (use_cfi_diag) {
-        cflags += [
-          "-fno-sanitize-trap=cfi",
-          "-fsanitize-recover=cfi",
-        ]
-        ldflags += [
-          "-fno-sanitize-trap=cfi",
-          "-fsanitize-recover=cfi",
-        ]
-      } else {
-        defines += [ "CFI_ENFORCEMENT" ]
-      }
-    }
-
-    if (use_custom_libcxx) {
-      cflags_cc += [ "-nostdinc++" ]
-      include_dirs = [
-        "//buildtools/third_party/libc++/trunk/include",
-        "//buildtools/third_party/libc++abi/trunk/include",
-      ]
-    }
   }
 
   if (is_clang && is_debug) {
@@ -511,7 +415,7 @@
       #"-Wl,--thread-count=4",
     ]
 
-    if (!is_asan && !is_msan && !is_lsan && !is_tsan) {
+    if (!using_sanitizer) {
       # TODO(brettw) common.gypi has this only for target toolset.
       ldflags += [ "-Wl,--icf=all" ]
     }
@@ -553,11 +457,20 @@
   # Pass the same C/C++ flags to the objective C/C++ compiler.
   cflags_objc += cflags_c
   cflags_objcc += cflags_cc
+
+  # Assign any flags set for the C compiler to asmflags so that they are sent
+  # to the assembler. The Windows assembler takes different types of flags
+  # so only do so for posix platforms.
+  if (is_posix) {
+    asmflags += cflags
+    asmflags += cflags_c
+  }
 }
 
 config("compiler_arm_fpu") {
   if (current_cpu == "arm" && !is_ios && !is_nacl) {
     cflags = [ "-mfpu=$arm_fpu" ]
+    asmflags = cflags
   }
 }
 
@@ -906,6 +819,7 @@
       "-Wno-deprecated",
     ]
   }
+
   cflags += default_warning_flags
   cflags_cc += default_warning_flags_cc
 }
@@ -1183,6 +1097,7 @@
     if (use_debug_fission) {
       cflags += [ "-gsplit-dwarf" ]
     }
+    asmflags = cflags
     ldflags = []
   }
 }
@@ -1205,6 +1120,7 @@
     if (use_debug_fission) {
       cflags += [ "-gsplit-dwarf" ]
     }
+    asmflags = cflags
     ldflags = []
   }
 }
@@ -1213,6 +1129,7 @@
 config("no_symbols") {
   if (!is_win) {
     cflags = [ "-g0" ]
+    asmflags = cflags
   }
 }
 
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index d5db930d..5adc470 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 
 declare_args() {
@@ -18,10 +19,11 @@
 assert(symbol_level >= -1 && symbol_level <= 2, "Invalid symbol_level")
 if (symbol_level == -1) {
   # Linux is slowed by having symbols as part of the target binary, whereas
-  # Mac and Windows have them separate, so in Release Linux, default them off.
-  if (is_debug || !is_linux) {
+  # Mac and Windows have them separate, so in Release Linux, default them off,
+  # but keep them on for Official builds.
+  if (!is_linux || (is_debug || is_official_build)) {
     symbol_level = 2
-  } else if (is_asan || is_lsan || is_tsan || is_msan) {
+  } else if (using_sanitizer) {
     # Sanitizers require symbols for filename suppressions to work.
     symbol_level = 1
   } else {
diff --git a/build/config/features.gni b/build/config/features.gni
index 969a464..9a29d5e1 100644
--- a/build/config/features.gni
+++ b/build/config/features.gni
@@ -89,7 +89,7 @@
   enable_remoting = !is_ios && !is_android && !is_chromecast
 
   # Enable hole punching for the protected video.
-  enable_video_hole = is_android || is_chromecast
+  enable_video_hole = is_android
 
   # Enables browser side Content Decryption Modules. Required for embedders
   # (e.g. Android and ChromeCast) that use a browser side CDM.
diff --git a/build/config/mac/BUILD.gn b/build/config/mac/BUILD.gn
index 61c85bc..7653b966 100644
--- a/build/config/mac/BUILD.gn
+++ b/build/config/mac/BUILD.gn
@@ -12,6 +12,7 @@
     "-mmacosx-version-min=$mac_deployment_target",
   ]
 
+  asmflags = common_flags
   cflags = common_flags
   ldflags = common_flags
 }
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
index 20008d4..8767aa4 100644
--- a/build/config/mac/mac_sdk.gni
+++ b/build/config/mac/mac_sdk.gni
@@ -34,11 +34,5 @@
     exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines")
 mac_sdk_version = find_sdk_lines[1]
 if (mac_sdk_path == "") {
-  # TODO(brettw) http://crbug.com/335325  when everybody moves to XCode 5 we
-  # can remove the --print_sdk_path argument to find_sdk and instead just use
-  # the following two lines to get the path. Although it looks longer here, it
-  # saves forking a process in find_sdk.py so will be faster.
-  #mac_sdk_root = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX"
-  #mac_sdk_path = mac_sdk_root + mac_sdk_version + ".sdk"
   mac_sdk_path = find_sdk_lines[0]
 }
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index 319c272..c06e4e77 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -8,7 +8,7 @@
 # shared_libraries. Unconditionally depend upon this target as it is empty if
 # |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false.
 group("deps") {
-  if (is_asan || is_lsan || is_tsan || is_msan) {
+  if (is_asan || is_lsan || is_tsan || is_msan || is_ubsan) {
     public_configs = [ ":sanitizer_options_link_helper" ]
     deps = [
       ":options_sources",
@@ -37,6 +37,9 @@
   if (is_msan) {
     ldflags += [ "-fsanitize=memory" ]
   }
+  if (is_ubsan) {
+    ldflags += [ "-fsanitize=undefined" ]
+  }
 }
 
 source_set("options_sources") {
@@ -48,6 +51,11 @@
     "//build/sanitizers/sanitizer_options.cc",
   ]
 
+  # Don't compile this target with any sanitizer code. It can be called from
+  # the sanitizer runtimes, so instrumenting these functions could cause
+  # recursive calls into the runtime if there is an error.
+  configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
+
   if (is_asan) {
     sources += [ "//build/sanitizers/asan_suppressions.cc" ]
   }
@@ -60,3 +68,149 @@
     sources += [ "//build/sanitizers/tsan_suppressions.cc" ]
   }
 }
+
+# This config is applied by default to all targets. It sets the compiler flags
+# for sanitizer usage, or, if no sanitizer is set, does nothing.
+#
+# This needs to be in a separate config so that targets can opt out of
+# sanitizers if they desire.
+config("default_sanitizer_flags") {
+  cflags = []
+  cflags_cc = []
+  ldflags = []
+  defines = []
+
+  # Only works on Posix-like platforms.
+  if (is_posix) {
+    # Common options for AddressSanitizer, LeakSanitizer, ThreadSanitizer,
+    # MemorySanitizer and non-official CFI builds.
+    if (using_sanitizer || (is_cfi && !is_official_build)) {
+      cflags += [
+        "-fno-omit-frame-pointer",
+        "-gline-tables-only",
+      ]
+    }
+    if (is_asan) {
+      asan_blacklist_path =
+          rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir)
+      cflags += [
+        "-fsanitize=address",
+        "-fsanitize-blacklist=$asan_blacklist_path",
+      ]
+      if (is_mac) {
+        cflags += [ "-mllvm -asan-globals=0" ]  # http://crbug.com/352073
+        # TODO(GYP): deal with mac_bundles.
+      }
+    }
+    if (is_lsan) {
+      cflags += [ "-fsanitize=leak" ]
+    }
+    if (is_tsan) {
+      tsan_blacklist_path =
+          rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir)
+      cflags += [
+        "-fsanitize=thread",
+        "-fsanitize-blacklist=$tsan_blacklist_path",
+      ]
+    }
+    if (is_msan) {
+      msan_blacklist_path =
+          rebase_path("//tools/msan/blacklist.txt", root_build_dir)
+      cflags += [
+        "-fsanitize=memory",
+        "-fsanitize-memory-track-origins=$msan_track_origins",
+        "-fsanitize-blacklist=$msan_blacklist_path",
+      ]
+    }
+    if (is_ubsan) {
+      ubsan_blacklist_path =
+          rebase_path("//tools/ubsan/blacklist.txt", root_build_dir)
+      cflags += [
+        # Yasm dies with an "Illegal instruction" error when bounds checking is
+        # enabled. See http://crbug.com/489901
+        # "-fsanitize=bounds",
+        "-fsanitize=float-divide-by-zero",
+        "-fsanitize=integer-divide-by-zero",
+        "-fsanitize=null",
+        "-fsanitize=object-size",
+        "-fsanitize=return",
+        "-fsanitize=returns-nonnull-attribute",
+        "-fsanitize=shift-exponent",
+        "-fsanitize=signed-integer-overflow",
+        "-fsanitize=unreachable",
+        "-fsanitize=vla-bound",
+        "-fsanitize-blacklist=$ubsan_blacklist_path",
+
+        # Employ the experimental PBQP register allocator to avoid slow
+        # compilation on files with too many basic blocks.
+        # See http://crbug.com/426271.
+        "-mllvm",
+        "-regalloc=pbqp",
+
+        # Speculatively use coalescing to slightly improve the code generated
+        # by PBQP regallocator. May increase compile time.
+        "-mllvm",
+        "-pbqp-coalescing",
+      ]
+    }
+    if (is_cfi && !is_nacl) {
+      cfi_blacklist_path =
+          rebase_path("//tools/cfi/blacklist.txt", root_build_dir)
+      cflags += [
+        "-flto",
+        "-fsanitize=cfi-vcall",
+        "-fsanitize=cfi-derived-cast",
+        "-fsanitize=cfi-unrelated-cast",
+        "-fsanitize-blacklist=$cfi_blacklist_path",
+      ]
+      ldflags += [
+        "-flto",
+        "-fsanitize=cfi-vcall",
+        "-fsanitize=cfi-derived-cast",
+        "-fsanitize=cfi-unrelated-cast",
+      ]
+
+      # Apply a lower LTO optimization level in non-official builds.
+      if (!is_official_build) {
+        if (is_linux) {
+          ldflags += [ "-Wl,-plugin-opt,O1" ]
+        } else if (is_mac) {
+          ldflags += [ "-Wl,-mllvm,-O1" ]
+        }
+      }
+
+      # Work-around for http://openradar.appspot.com/20356002
+      if (is_mac) {
+        ldflags += [ "-Wl,-all_load" ]
+      }
+
+      # Without this flag, LTO produces a .text section that is larger
+      # than the maximum call displacement, preventing the linker from
+      # relocating calls (http://llvm.org/PR22999).
+      if (current_cpu == "arm") {
+        ldflags += [ "-Wl,-plugin-opt,-function-sections" ]
+      }
+
+      if (use_cfi_diag) {
+        cflags += [
+          "-fno-sanitize-trap=cfi",
+          "-fsanitize-recover=cfi",
+        ]
+        ldflags += [
+          "-fno-sanitize-trap=cfi",
+          "-fsanitize-recover=cfi",
+        ]
+      } else {
+        defines += [ "CFI_ENFORCEMENT" ]
+      }
+    }
+
+    if (use_custom_libcxx) {
+      cflags_cc += [ "-nostdinc++" ]
+      include_dirs = [
+        "//buildtools/third_party/libc++/trunk/include",
+        "//buildtools/third_party/libc++abi/trunk/include",
+      ]
+    }
+  }
+}
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index 1aa212d..84348da 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -15,10 +15,14 @@
   # Compile for Thread Sanitizer to find threading bugs.
   is_tsan = false
 
+  # Compile for Undefined Behaviour Sanitizer to find various types of
+  # undefined behaviour.
+  is_ubsan = false
+
   # Use libc++ (buildtools/third_party/libc++ and
   # buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
   # This is intended to be used for instrumented builds.
-  use_custom_libcxx = (is_asan && is_linux) || is_tsan || is_msan
+  use_custom_libcxx = (is_asan && is_linux) || is_tsan || is_msan || is_ubsan
 
   # Track where uninitialized memory originates from. From fastest to slowest:
   # 0 - no tracking, 1 - track only the initial allocation site, 2 - track the
@@ -45,7 +49,7 @@
 }
 
 # TODO(GYP) bug 527515: is_ubsan, is_ubsan_vptr
-using_sanitizer = is_asan || is_lsan || is_tsan || is_msan
+using_sanitizer = is_asan || is_lsan || is_tsan || is_msan || is_ubsan
 
 assert(!using_sanitizer || is_clang,
        "Sanitizers (is_*san) require setting is_clang = true in 'gn args'")
@@ -63,5 +67,5 @@
 # unsupported or unadvisable configurations.
 #
 # For one-off testing, just comment this assertion out.
-assert(!is_debug || !(is_msan || is_lsan || is_tsan),
+assert(!is_debug || !(is_msan || is_lsan || is_tsan || is_ubsan),
        "Sanitizers should generally be used in release (set is_debug=false).")
diff --git a/build/config/ui.gni b/build/config/ui.gni
index eb502b4..f7070bbf 100644
--- a/build/config/ui.gni
+++ b/build/config/ui.gni
@@ -24,7 +24,7 @@
   # Indicates if Ozone is enabled. Ozone is a low-level library layer for Linux
   # that does not require X11. Enabling this feature disables use of glib, x11,
   # Pango, and Cairo. Default to false on non-Chromecast builds.
-  use_ozone = is_chromecast
+  use_ozone = is_chromecast && !is_android
 
   # Indicates if Aura is enabled. Aura is a low-level windowing library, sort
   # of a replacement for GDI or GTK.
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index a93ed30d..d1f670e9 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -12,6 +12,14 @@
 # is applied to all targets. It is here to separate out the logic that is
 # Windows-only.
 config("compiler") {
+  asmflags = [
+    # When /SAFESEH is specified, the linker will only produce an image if it
+    # can also produce a table of the image's safe exception handlers. This
+    # table specifies for the operating system which exception handlers are
+    # valid for the image.
+    "/SAFESEH",
+  ]
+
   cflags = [
     "/Gy",  # Enable function-level linking.
     "/GS",  # Enable buffer security checking.
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi
index 370b256..ad910b0 100644
--- a/build/gn_migration.gypi
+++ b/build/gn_migration.gypi
@@ -289,9 +289,6 @@
             '../base/base.gyp:chromium_android_linker',
             '../breakpad/breakpad.gyp:dump_syms',
             '../build/android/rezip.gyp:rezip_apk_jar',
-            '../chrome/chrome.gyp:chrome_public_apk',
-            '../chrome/chrome.gyp:chrome_public_test_apk',
-            '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
             #"//clank" TODO(GYP) - conditional somehow?
             '../tools/imagediff/image_diff.gyp:image_diff#host',
             '../tools/telemetry/telemetry.gyp:bitmaptools#host',
@@ -354,6 +351,13 @@
             '../url/url.gyp:url_unittests',
           ],
         }],
+        ['OS=="android" and chromecast==0', {
+          'dependencies': [
+            '../chrome/chrome.gyp:chrome_public_apk',
+            '../chrome/chrome.gyp:chrome_public_test_apk',
+            '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+          ],
+        }],
         ['OS=="android" or OS=="linux"', {
           'dependencies': [
             '../net/net.gyp:disk_cache_memory_test',
diff --git a/build/java.gypi b/build/java.gypi
index c97b07e..0fdf19b 100644
--- a/build/java.gypi
+++ b/build/java.gypi
@@ -63,6 +63,7 @@
     'jar_excluded_classes': [ '*/R.class', '*/R##*.class' ],
     'instr_stamp': '<(intermediate_dir)/instr.stamp',
     'additional_input_paths': [],
+    'additional_locale_input_paths': [],
     'dex_path': '<(PRODUCT_DIR)/lib.java/<(_target_name).dex.jar',
     'main_dex_list_path': '<(intermediate_dir)/main_dex_list.txt',
     'generated_src_dirs': ['>@(generated_R_dirs)'],
@@ -135,6 +136,7 @@
         'generated_src_dirs': ['<(R_dir)'],
         'additional_input_paths': ['<(resource_zip_path)', ],
 
+        'dependencies_locale_zip_paths': [],
         'dependencies_res_zip_paths': [],
         'resource_zip_path': '<(PRODUCT_DIR)/res.java/<(_target_name).zip',
       },
@@ -166,6 +168,10 @@
             # the list of inputs changes.
             'inputs_list_file': '>|(java_resources.<(_target_name).gypcmd >@(resource_input_paths))',
             'process_resources_options': [],
+            'local_dependencies_res_zip_paths': [
+              '>@(dependencies_res_zip_paths)',
+              '>@(dependencies_locale_zip_paths)'
+            ],
             'conditions': [
               ['res_v14_skip == 1', {
                 'process_resources_options': ['--v14-skip']
@@ -177,7 +183,7 @@
             '<(DEPTH)/build/android/gyp/process_resources.py',
             '<(DEPTH)/build/android/gyp/generate_v14_compatible_resources.py',
             '>@(resource_input_paths)',
-            '>@(dependencies_res_zip_paths)',
+            '>@(local_dependencies_res_zip_paths)',
             '>(inputs_list_file)',
           ],
           'outputs': [
@@ -193,7 +199,7 @@
             '--android-manifest', '<(android_manifest)',
             '--custom-package', '<(R_package)',
 
-            '--dependencies-res-zips', '>(dependencies_res_zip_paths)',
+            '--dependencies-res-zips', '>(local_dependencies_res_zip_paths)',
             '--resource-dirs', '<(res_input_dirs)',
 
             '--R-dir', '<(R_dir)',
@@ -278,6 +284,10 @@
       'action_name': 'javac_<(_target_name)',
       'message': 'Compiling <(_target_name) java sources',
       'variables': {
+        'local_additional_input_paths': [
+          '>@(additional_input_paths)',
+          '>@(additional_locale_input_paths)',
+        ],
         'extra_args': [],
         'extra_inputs': [],
         'java_sources': ['>!@(find >(java_in_dir)>(java_in_dir_suffix) >(additional_src_dirs) -name "*.java")'],
@@ -295,7 +305,7 @@
         '<(DEPTH)/build/android/gyp/javac.py',
         '>@(java_sources)',
         '>@(input_jars_paths)',
-        '>@(additional_input_paths)',
+        '>@(local_additional_input_paths)',
         '<@(extra_inputs)',
       ],
       'outputs': [
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index 992f0cb..dfc103a5 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -39,6 +39,8 @@
 #    that are generated at build time. This should be set automatically by a
 #    target's dependencies. The .java files in these directories are not
 #    included in the 'inputs' list (unlike additional_src_dirs).
+#  library_jars_paths - The path to library jars to be included in the classpath.
+#    These will not be included into the final apk.
 #  input_jars_paths - The path to jars to be included in the classpath. This
 #    should be filled automatically by depending on the appropriate targets.
 #  is_test_apk - Set to 1 if building a test apk.  This prevents resources from
@@ -68,14 +70,18 @@
 #  java_in_dir_suffix - To override the /src suffix on java_in_dir.
 #  app_manifest_version_name - set the apps 'human readable' version number.
 #  app_manifest_version_code - set the apps version number.
+#  dependencies_locale_zip_alternative_paths - a list of paths that used to
+#    replace dependencies_locale_zip_paths of all_dependent_settings.
 {
   'variables': {
     'tested_apk_obfuscated_jar_path%': '/',
     'tested_apk_dex_path%': '/',
     'tested_apk_is_multidex%': 0,
     'additional_input_paths': [],
+    'additional_locale_input_paths': [],
     'create_density_splits%': 0,
     'language_splits': [],
+    'library_jars_paths': [],
     'input_jars_paths': [],
     'library_dexed_jars_paths': [],
     'main_dex_list_path': '<(intermediate_dir)/main_dex_list.txt',
@@ -93,6 +99,8 @@
     'R_package%':'',
     'include_all_resources%': 0,
     'additional_R_text_files': [],
+    'dependencies_locale_zip_alternative_paths%': [],
+    'dependencies_locale_zip_paths': [],
     'dependencies_res_zip_paths': [],
     'additional_res_packages': [],
     'additional_bundled_libs%': [],
@@ -781,12 +789,27 @@
       'action_name': 'process_resources',
       'message': 'processing resources for <(_target_name)',
       'variables': {
+        'local_additional_input_paths': [
+          '>@(additional_input_paths)',
+        ],
+        'local_dependencies_res_zip_paths': [
+          '>@(dependencies_res_zip_paths)'
+        ],
         # Write the inputs list to a file, so that its mtime is updated when
         # the list of inputs changes.
-        'inputs_list_file': '>|(apk_codegen.<(_target_name).gypcmd >@(additional_input_paths) >@(resource_input_paths))',
+        'inputs_list_file': '>|(apk_codegen.<(_target_name).gypcmd >@(local_additional_input_paths) >@(resource_input_paths))',
+
         'process_resources_options': [],
         'conditions': [
+          ['dependencies_locale_zip_alternative_paths == []', {
+            'local_dependencies_res_zip_paths': ['>@(dependencies_locale_zip_paths)'],
+            'local_additional_input_paths': ['>@(additional_locale_input_paths)']
+          }, {
+            'local_dependencies_res_zip_paths': ['<@(dependencies_locale_zip_alternative_paths)'],
+            'local_additional_input_paths': ['>@(dependencies_locale_zip_alternative_paths)'],
+          }],
           ['is_test_apk == 1', {
+            'dependencies_locale_zip_paths=': [],
             'dependencies_res_zip_paths=': [],
             'additional_res_packages=': [],
           }],
@@ -811,9 +834,9 @@
         '<(DEPTH)/build/android/gyp/util/build_utils.py',
         '<(DEPTH)/build/android/gyp/process_resources.py',
         '<(android_manifest_path)',
-        '>@(additional_input_paths)',
+        '>@(local_additional_input_paths)',
         '>@(resource_input_paths)',
-        '>@(dependencies_res_zip_paths)',
+        '>@(local_dependencies_res_zip_paths)',
         '>(inputs_list_file)',
       ],
       'outputs': [
@@ -827,7 +850,7 @@
         '--aapt-path', '<(android_aapt_path)',
 
         '--android-manifest', '<(android_manifest_path)',
-        '--dependencies-res-zips', '>(dependencies_res_zip_paths)',
+        '--dependencies-res-zips', '>(local_dependencies_res_zip_paths)',
 
         '--extra-res-packages', '>(additional_res_packages)',
         '--extra-r-text-files', '>(additional_R_text_files)',
@@ -894,7 +917,7 @@
       'action': [
         'python', '<(DEPTH)/build/android/gyp/javac.py',
         '--bootclasspath=<(android_sdk_jar)',
-        '--classpath=>(input_jars_paths) <(android_sdk_jar)',
+        '--classpath=>(input_jars_paths) <(android_sdk_jar) >(library_jars_paths)',
         '--src-gendirs=>(gen_src_dirs)',
         '--javac-includes=<(javac_includes)',
         '--chromium-code=<(chromium_code)',
@@ -1096,14 +1119,20 @@
     },
     {
       'variables': {
+        'local_dependencies_res_zip_paths': ['>@(dependencies_res_zip_paths)'],
         'extra_inputs': ['<(codegen_stamp)'],
         'resource_zips': [
           '<(resource_zip_path)',
         ],
         'conditions': [
+          ['dependencies_locale_zip_alternative_paths == []', {
+            'local_dependencies_res_zip_paths': ['>@(dependencies_locale_zip_paths)'],
+          }, {
+            'local_dependencies_res_zip_paths': ['<@(dependencies_locale_zip_alternative_paths)'],
+          }],
           ['is_test_apk == 0', {
             'resource_zips': [
-              '>@(dependencies_res_zip_paths)',
+              '>@(local_dependencies_res_zip_paths)',
             ],
           }],
         ],
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 74dbf073..042a836 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -194,7 +194,7 @@
     tool("asm") {
       # For GCC we can just use the C compiler to compile assembly.
       depfile = "{{output}}.d"
-      command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+      command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "ASM {{output}}"
       outputs = [
@@ -353,6 +353,7 @@
         is_msan = false
         is_syzyasan = false
         is_tsan = false
+        is_ubsan = false
       }
     }
 
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index dd3ff610..b0c233a 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -50,10 +50,7 @@
 
     tool("cc") {
       depfile = "{{output}}.d"
-
-      # TODO(andybons): enable this when GCC PCH support in the binary has been
-      # rolled.
-      #precompiled_header_type = "gcc"
+      precompiled_header_type = "gcc"
       command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "CC {{output}}"
@@ -64,10 +61,7 @@
 
     tool("cxx") {
       depfile = "{{output}}.d"
-
-      # TODO(andybons): enable this when GCC PCH support in the binary has been
-      # rolled.
-      #precompiled_header_type = "gcc"
+      precompiled_header_type = "gcc"
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "CXX {{output}}"
@@ -79,7 +73,7 @@
     tool("asm") {
       # For GCC we can just use the C compiler to compile assembly.
       depfile = "{{output}}.d"
-      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+      command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "ASM {{output}}"
       outputs = [
@@ -90,10 +84,7 @@
     tool("objc") {
       depfile = "{{output}}.d"
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
-
-      # TODO(andybons): enable this when GCC PCH support in the binary has been
-      # rolled.
-      #precompiled_header_type = "gcc"
+      precompiled_header_type = "gcc"
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} {{cflags_objc}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "OBJC {{output}}"
@@ -105,10 +96,7 @@
     tool("objcxx") {
       depfile = "{{output}}.d"
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}"
-
-      # TODO(andybons): enable this when GCC PCH support in the binary has been
-      # rolled.
-      #precompiled_header_type = "gcc"
+      precompiled_header_type = "gcc"
       depsformat = "gcc"
       description = "OBJCXX {{output}}"
       outputs = [
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index a054267..7a0ecbb 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -120,9 +120,7 @@
     }
 
     tool("asm") {
-      # TODO(brettw): "/safeseh" assembler argument is hardcoded here. Extract
-      # assembler flags to a variable like cflags. crbug.com/418613
-      command = "$python_path gyp-win-tool asm-wrapper $env ml.exe {{defines}} {{include_dirs}} /safeseh /c /Fo {{output}} {{source}}"
+      command = "$python_path gyp-win-tool asm-wrapper $env ml.exe {{defines}} {{include_dirs}} {{asmflags}} /c /Fo{{output}} {{source}}"
       description = "ASM {{output}}"
       outputs = [
         "{{target_out_dir}}/{{target_output_name}}/{{source_name_part}}.obj",
diff --git a/cc/base/histograms.h b/cc/base/histograms.h
index 542ae5d..8c8b467 100644
--- a/cc/base/histograms.h
+++ b/cc/base/histograms.h
@@ -70,8 +70,8 @@
 
 class CC_EXPORT ScopedUMAHistogramAreaTimerBase {
  public:
-  void AddArea(int area) { area_ += area; }
-  void SetArea(int area) { area_ = area; }
+  void AddArea(const base::CheckedNumeric<int>& area) { area_ += area; }
+  void SetArea(const base::CheckedNumeric<int>& area) { area_ = area; }
 
  protected:
   using Sample = base::HistogramBase::Sample;
diff --git a/cc/base/rtree.cc b/cc/base/rtree.cc
index 0828a34d..ca64e87 100644
--- a/cc/base/rtree.cc
+++ b/cc/base/rtree.cc
@@ -14,35 +14,6 @@
 
 RTree::~RTree() {}
 
-void RTree::Build(const std::vector<gfx::RectF>& rects) {
-  DCHECK_EQ(0u, num_data_elements_);
-
-  std::vector<Branch> branches;
-  branches.reserve(rects.size());
-
-  for (size_t i = 0; i < rects.size(); i++) {
-    const gfx::RectF& bounds = rects[i];
-    if (bounds.IsEmpty())
-      continue;
-
-    branches.push_back(Branch());
-    Branch& branch = branches.back();
-    branch.bounds = bounds;
-    branch.index = i;
-  }
-
-  num_data_elements_ = branches.size();
-  if (num_data_elements_ == 1) {
-    Node* node = AllocateNodeAtLevel(0);
-    node->num_children = 1;
-    node->children[0] = branches[0];
-    root_.subtree = node;
-    root_.bounds = branches[0].bounds;
-  } else if (num_data_elements_ > 1) {
-    root_ = BuildRecursive(&branches, 0);
-  }
-}
-
 RTree::Node* RTree::AllocateNodeAtLevel(int level) {
   nodes_.push_back(Node());
   Node& node = nodes_.back();
diff --git a/cc/base/rtree.h b/cc/base/rtree.h
index 17a1d8c..f765c353 100644
--- a/cc/base/rtree.h
+++ b/cc/base/rtree.h
@@ -38,7 +38,41 @@
   RTree();
   ~RTree();
 
-  void Build(const std::vector<gfx::RectF>& rects);
+  template <typename Container, typename Functor>
+  void Build(const Container& items, const Functor& bounds_getter) {
+    DCHECK_EQ(0u, num_data_elements_);
+
+    std::vector<Branch> branches;
+    branches.reserve(items.size());
+
+    for (size_t i = 0; i < items.size(); i++) {
+      const gfx::RectF& bounds = bounds_getter(items[i]);
+      if (bounds.IsEmpty())
+        continue;
+
+      branches.push_back(Branch());
+      Branch& branch = branches.back();
+      branch.bounds = bounds;
+      branch.index = i;
+    }
+
+    num_data_elements_ = branches.size();
+    if (num_data_elements_ == 1u) {
+      Node* node = AllocateNodeAtLevel(0);
+      node->num_children = 1;
+      node->children[0] = branches[0];
+      root_.subtree = node;
+      root_.bounds = branches[0].bounds;
+    } else if (num_data_elements_ > 1u) {
+      root_ = BuildRecursive(&branches, 0);
+    }
+  }
+
+  template <typename Container>
+  void Build(const Container& items) {
+    Build(items, [](const gfx::RectF& bounds) { return bounds; });
+  }
+
   void Search(const gfx::RectF& query, std::vector<size_t>* results) const;
 
  private:
diff --git a/cc/layers/draw_properties.cc b/cc/layers/draw_properties.cc
index 19c52451b..a683e913 100644
--- a/cc/layers/draw_properties.cc
+++ b/cc/layers/draw_properties.cc
@@ -10,6 +10,7 @@
     : opacity(0.f),
       screen_space_transform_is_animating(false),
       can_use_lcd_text(false),
+      is_clipped(false),
       render_target(nullptr),
       num_unclipped_descendants(0),
       layer_or_descendant_has_input_handler(false),
diff --git a/cc/layers/draw_properties.h b/cc/layers/draw_properties.h
index 3177dc0..a8f54fa 100644
--- a/cc/layers/draw_properties.h
+++ b/cc/layers/draw_properties.h
@@ -44,6 +44,9 @@
   // True if the layer can use LCD text.
   bool can_use_lcd_text;
 
+  // True if the layer needs to be clipped by clip_rect.
+  bool is_clipped;
+
   // The layer whose coordinate space this layer draws into. This can be
   // either the same layer (draw_properties_.render_target == this) or an
   // ancestor of this layer.
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 926c4852..4b9162ff 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -57,7 +57,6 @@
       property_tree_sequence_number_(-1),
       num_layer_or_descendants_with_copy_request_(0),
       should_flatten_transform_from_property_tree_(false),
-      is_clipped_(false),
       should_scroll_on_main_thread_(false),
       have_wheel_event_handlers_(false),
       have_scroll_event_handlers_(false),
@@ -1222,7 +1221,6 @@
       should_flatten_transform_from_property_tree_);
   layer->set_num_layer_or_descendant_with_copy_request(
       num_layer_or_descendants_with_copy_request_);
-  layer->set_is_clipped(is_clipped_);
   layer->set_draw_blend_mode(draw_blend_mode_);
   layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
   if (!layer->TransformIsAnimatingOnImplOnly() && !TransformIsAnimating())
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 0a21f57..800deff5 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -473,14 +473,6 @@
   const gfx::Rect& clip_rect() const { return clip_rect_; }
   void set_clip_rect(const gfx::Rect& rect) { clip_rect_ = rect; }
 
-  void set_is_clipped(bool is_clipped) {
-    if (is_clipped_ == is_clipped)
-      return;
-    is_clipped_ = is_clipped;
-    SetNeedsPushProperties();
-  }
-  bool is_clipped() const { return is_clipped_; }
-
   bool has_render_surface() const {
     return has_render_surface_;
   }
@@ -655,7 +647,6 @@
   int num_layer_or_descendants_with_copy_request_;
   gfx::Vector2dF offset_to_transform_parent_;
   bool should_flatten_transform_from_property_tree_ : 1;
-  bool is_clipped_ : 1;
   bool should_scroll_on_main_thread_ : 1;
   bool have_wheel_event_handlers_ : 1;
   bool have_scroll_event_handlers_ : 1;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index c2218f6e..087d831 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -61,7 +61,6 @@
       double_sided_(true),
       should_flatten_transform_(true),
       should_flatten_transform_from_property_tree_(false),
-      is_clipped_(false),
       layer_property_changed_(false),
       masks_to_bounds_(false),
       contents_opaque_(false),
@@ -317,8 +316,8 @@
 void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
   state->SetAll(draw_properties_.target_space_transform, bounds(),
                 draw_properties_.visible_layer_rect, draw_properties_.clip_rect,
-                is_clipped_, draw_properties_.opacity, draw_blend_mode_,
-                sorting_context_id_);
+                draw_properties_.is_clipped, draw_properties_.opacity,
+                draw_blend_mode_, sorting_context_id_);
 }
 
 void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state,
@@ -332,7 +331,7 @@
   scaled_visible_layer_rect.Intersect(gfx::Rect(scaled_bounds));
 
   state->SetAll(scaled_draw_transform, scaled_bounds, scaled_visible_layer_rect,
-                draw_properties().clip_rect, is_clipped_,
+                draw_properties().clip_rect, draw_properties().is_clipped,
                 draw_properties().opacity, draw_blend_mode_,
                 sorting_context_id_);
 }
@@ -571,7 +570,6 @@
   layer->SetShouldFlattenTransform(should_flatten_transform_);
   layer->set_should_flatten_transform_from_property_tree(
       should_flatten_transform_from_property_tree_);
-  layer->set_is_clipped(is_clipped_);
   layer->set_draw_blend_mode(draw_blend_mode_);
   layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
   layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 5a2da10b..0dc204c 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -196,11 +196,7 @@
     return should_flatten_transform_from_property_tree_;
   }
 
-  void set_is_clipped(bool is_clipped) {
-    is_clipped_ = is_clipped;
-    SetNeedsPushProperties();
-  }
-  bool is_clipped() const { return is_clipped_; }
+  bool is_clipped() const { return draw_properties_.is_clipped; }
 
   void UpdatePropertyTreeTransform();
   void UpdatePropertyTreeTransformIsAnimated(bool is_animated);
@@ -775,7 +771,6 @@
   bool double_sided_ : 1;
   bool should_flatten_transform_ : 1;
   bool should_flatten_transform_from_property_tree_ : 1;
-  bool is_clipped_ : 1;
 
   // Tracks if drawing-related properties have changed since last redraw.
   bool layer_property_changed_ : 1;
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index 937c5c2..67f83c65 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -243,7 +243,7 @@
 
   bool updated = false;
 
-  if (track_rect_.IsEmpty() || scaled_track_rect.IsEmpty()) {
+  if (scaled_track_rect.IsEmpty()) {
     if (track_resource_) {
       track_resource_ = nullptr;
       thumb_resource_ = nullptr;
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index d08d73d..6c215a3 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -88,15 +88,13 @@
   if (!host)
     return;
 
-  const LayerTreeSettings& settings = layer_tree_host()->settings();
-  if (!recording_source_) {
-    recording_source_.reset(
-        new DisplayListRecordingSource(settings.default_tile_grid_size));
-  }
+  if (!recording_source_)
+    recording_source_.reset(new DisplayListRecordingSource);
   recording_source_->SetSlowdownRasterScaleFactor(
       host->debug_state().slow_down_raster_scale_factor);
   // If we need to enable image decode tasks, then we have to generate the
   // discardable images metadata.
+  const LayerTreeSettings& settings = layer_tree_host()->settings();
   recording_source_->SetGenerateDiscardableImagesMetadata(
       settings.image_decode_tasks_enabled);
 }
@@ -178,10 +176,7 @@
     return skia::RefPtr<SkPicture>();
 
   gfx::Size layer_size = bounds();
-  const LayerTreeSettings& settings = layer_tree_host()->settings();
-
-  scoped_ptr<RecordingSource> recording_source(
-      new DisplayListRecordingSource(settings.default_tile_grid_size));
+  scoped_ptr<RecordingSource> recording_source(new DisplayListRecordingSource);
   Region recording_invalidation;
   recording_source->UpdateAndExpandInvalidation(
       client_, &recording_invalidation, layer_size, gfx::Rect(layer_size),
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc
index bac3aac3..6c45b09 100644
--- a/cc/layers/picture_layer_impl_perftest.cc
+++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -54,21 +54,22 @@
     host_impl_.InitializeRenderer(output_surface_.get());
   }
 
-  void SetupActiveTree(const gfx::Size& layer_bounds) {
+  void SetupPendingTree(const gfx::Size& layer_bounds) {
     scoped_refptr<FakeDisplayListRasterSource> raster_source =
         FakeDisplayListRasterSource::CreateFilled(layer_bounds);
-    LayerTreeImpl* active_tree = host_impl_.active_tree();
-    active_tree->DetachLayerTree();
+    host_impl_.CreatePendingTree();
+    LayerTreeImpl* pending_tree = host_impl_.pending_tree();
+    pending_tree->DetachLayerTree();
 
-    scoped_ptr<FakePictureLayerImpl> active_layer =
-        FakePictureLayerImpl::CreateWithRasterSource(active_tree, 7,
+    scoped_ptr<FakePictureLayerImpl> pending_layer =
+        FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 7,
                                                      raster_source);
-    active_layer->SetDrawsContent(true);
-    active_layer->SetHasRenderSurface(true);
-    active_tree->SetRootLayer(active_layer.Pass());
+    pending_layer->SetDrawsContent(true);
+    pending_layer->SetHasRenderSurface(true);
+    pending_tree->SetRootLayer(pending_layer.Pass());
 
-    active_layer_ = static_cast<FakePictureLayerImpl*>(
-        host_impl_.active_tree()->LayerById(7));
+    pending_layer_ = static_cast<FakePictureLayerImpl*>(
+        host_impl_.pending_tree()->LayerById(7));
   }
 
   void RunRasterQueueConstructAndIterateTest(const std::string& test_name,
@@ -76,13 +77,13 @@
                                              const gfx::Size& viewport_size) {
     host_impl_.SetViewportSize(viewport_size);
     bool update_lcd_text = false;
-    host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+    host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
 
     timer_.Reset();
     do {
       int count = num_tiles;
       scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
-          active_layer_->picture_layer_tiling_set(), false));
+          pending_layer_->picture_layer_tiling_set(), false));
       while (count--) {
         ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
         ASSERT_TRUE(queue->Top().tile()) << "count: " << count;
@@ -98,15 +99,15 @@
   void RunRasterQueueConstructTest(const std::string& test_name,
                                    const gfx::Rect& viewport) {
     host_impl_.SetViewportSize(viewport.size());
-    active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue(
+    pending_layer_->PushScrollOffsetFromMainThread(
         gfx::ScrollOffset(viewport.x(), viewport.y()));
     bool update_lcd_text = false;
-    host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+    host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
 
     timer_.Reset();
     do {
       scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll(
-          active_layer_->picture_layer_tiling_set(), false));
+          pending_layer_->picture_layer_tiling_set(), false));
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
@@ -119,15 +120,14 @@
       int num_tiles,
       const gfx::Size& viewport_size) {
     host_impl_.SetViewportSize(viewport_size);
-    active_layer_->MarkAllTilingsUsed();
     bool update_lcd_text = false;
-    host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+    host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
 
     timer_.Reset();
     do {
       int count = num_tiles;
       scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
-          active_layer_->picture_layer_tiling_set()));
+          pending_layer_->picture_layer_tiling_set()));
       while (count--) {
         ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count;
         ASSERT_TRUE(queue->Top().tile()) << "count: " << count;
@@ -144,16 +144,15 @@
   void RunEvictionQueueConstructTest(const std::string& test_name,
                                      const gfx::Rect& viewport) {
     host_impl_.SetViewportSize(viewport.size());
-    active_layer_->PushScrollOffsetFromMainThreadAndClobberActiveValue(
+    pending_layer_->PushScrollOffsetFromMainThread(
         gfx::ScrollOffset(viewport.x(), viewport.y()));
-    active_layer_->MarkAllTilingsUsed();
     bool update_lcd_text = false;
-    host_impl_.active_tree()->UpdateDrawProperties(update_lcd_text);
+    host_impl_.pending_tree()->UpdateDrawProperties(update_lcd_text);
 
     timer_.Reset();
     do {
       scoped_ptr<TilingSetEvictionQueue> queue(new TilingSetEvictionQueue(
-          active_layer_->picture_layer_tiling_set()));
+          pending_layer_->picture_layer_tiling_set()));
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
@@ -167,7 +166,7 @@
   FakeImplProxy proxy_;
   scoped_ptr<OutputSurface> output_surface_;
   FakeLayerTreeHostImpl host_impl_;
-  FakePictureLayerImpl* active_layer_;
+  FakePictureLayerImpl* pending_layer_;
   LapTimer timer_;
 
  private:
@@ -175,15 +174,15 @@
 };
 
 TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) {
-  SetupActiveTree(gfx::Size(10000, 10000));
+  SetupPendingTree(gfx::Size(10000, 10000));
 
   float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
 
-  active_layer_->AddTiling(low_res_factor);
-  active_layer_->AddTiling(0.3f);
-  active_layer_->AddTiling(0.7f);
-  active_layer_->AddTiling(1.0f);
-  active_layer_->AddTiling(2.0f);
+  pending_layer_->AddTiling(low_res_factor);
+  pending_layer_->AddTiling(0.3f);
+  pending_layer_->AddTiling(0.7f);
+  pending_layer_->AddTiling(1.0f);
+  pending_layer_->AddTiling(2.0f);
 
   RunRasterQueueConstructAndIterateTest("32_100x100", 32, gfx::Size(100, 100));
   RunRasterQueueConstructAndIterateTest("32_500x500", 32, gfx::Size(500, 500));
@@ -192,15 +191,15 @@
 }
 
 TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstruct) {
-  SetupActiveTree(gfx::Size(10000, 10000));
+  SetupPendingTree(gfx::Size(10000, 10000));
 
   float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
 
-  active_layer_->AddTiling(low_res_factor);
-  active_layer_->AddTiling(0.3f);
-  active_layer_->AddTiling(0.7f);
-  active_layer_->AddTiling(1.0f);
-  active_layer_->AddTiling(2.0f);
+  pending_layer_->AddTiling(low_res_factor);
+  pending_layer_->AddTiling(0.3f);
+  pending_layer_->AddTiling(0.7f);
+  pending_layer_->AddTiling(1.0f);
+  pending_layer_->AddTiling(2.0f);
 
   RunRasterQueueConstructTest("0_0_100x100", gfx::Rect(0, 0, 100, 100));
   RunRasterQueueConstructTest("5000_0_100x100", gfx::Rect(5000, 0, 100, 100));
@@ -208,16 +207,16 @@
 }
 
 TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstructAndIterate) {
-  SetupActiveTree(gfx::Size(10000, 10000));
+  SetupPendingTree(gfx::Size(10000, 10000));
 
   float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
 
   std::vector<Tile*> all_tiles;
-  AddTiling(low_res_factor, active_layer_, &all_tiles);
-  AddTiling(0.3f, active_layer_, &all_tiles);
-  AddTiling(0.7f, active_layer_, &all_tiles);
-  AddTiling(1.0f, active_layer_, &all_tiles);
-  AddTiling(2.0f, active_layer_, &all_tiles);
+  AddTiling(low_res_factor, pending_layer_, &all_tiles);
+  AddTiling(0.3f, pending_layer_, &all_tiles);
+  AddTiling(0.7f, pending_layer_, &all_tiles);
+  AddTiling(1.0f, pending_layer_, &all_tiles);
+  AddTiling(2.0f, pending_layer_, &all_tiles);
 
   ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
@@ -233,16 +232,16 @@
 }
 
 TEST_F(PictureLayerImplPerfTest, TilingSetEvictionQueueConstruct) {
-  SetupActiveTree(gfx::Size(10000, 10000));
+  SetupPendingTree(gfx::Size(10000, 10000));
 
   float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
 
   std::vector<Tile*> all_tiles;
-  AddTiling(low_res_factor, active_layer_, &all_tiles);
-  AddTiling(0.3f, active_layer_, &all_tiles);
-  AddTiling(0.7f, active_layer_, &all_tiles);
-  AddTiling(1.0f, active_layer_, &all_tiles);
-  AddTiling(2.0f, active_layer_, &all_tiles);
+  AddTiling(low_res_factor, pending_layer_, &all_tiles);
+  AddTiling(0.3f, pending_layer_, &all_tiles);
+  AddTiling(0.7f, pending_layer_, &all_tiles);
+  AddTiling(1.0f, pending_layer_, &all_tiles);
+  AddTiling(2.0f, pending_layer_, &all_tiles);
 
   ASSERT_TRUE(host_impl_.tile_manager() != nullptr);
   host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles);
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index bef73ee..cb73d15 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -80,7 +80,7 @@
 
 TEST(PictureLayerTest, SuitableForGpuRasterization) {
   scoped_ptr<FakeDisplayListRecordingSource> recording_source_owned(
-      new FakeDisplayListRecordingSource(gfx::Size(100, 100)));
+      new FakeDisplayListRecordingSource);
   FakeDisplayListRecordingSource* recording_source =
       recording_source_owned.get();
 
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 8fa66b1..f631fcea 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -791,6 +791,7 @@
   resource_count = 0;
   expected_created = 2;
   expected_deleted = 2;
+  scrollbar_layer->SetBounds(gfx::Size(0, 0));
   scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
   EXPECT_TRUE(scrollbar_layer->Update());
   EXPECT_EQ(0, scrollbar_layer->track_resource_id());
@@ -813,6 +814,7 @@
   resource_count = 2;
   expected_created = 4;
   expected_deleted = 2;
+  scrollbar_layer->SetBounds(gfx::Size(100, 15));
   scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
   EXPECT_TRUE(scrollbar_layer->Update());
   EXPECT_NE(0, scrollbar_layer->track_resource_id());
@@ -835,6 +837,7 @@
   resource_count = 0;
   expected_created = 5;
   expected_deleted = 5;
+  scrollbar_layer->SetBounds(gfx::Size(0, 0));
   scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
   EXPECT_TRUE(scrollbar_layer->Update());
   EXPECT_EQ(0, scrollbar_layer->track_resource_id());
@@ -846,15 +849,27 @@
   resource_count = 2;
   expected_created = 7;
   expected_deleted = 5;
+  scrollbar_layer->SetBounds(gfx::Size(100, 15));
   scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
   scrollbar_layer->fake_scrollbar()->set_has_thumb(true);
   EXPECT_TRUE(scrollbar_layer->Update());
   EXPECT_NE(0, scrollbar_layer->track_resource_id());
   EXPECT_NE(0, scrollbar_layer->thumb_resource_id());
 
-  resource_count = 1;
-  expected_created = 8;
+  resource_count = 2;
+  expected_created = 9;
   expected_deleted = 7;
+  scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 0, 0));
+  EXPECT_TRUE(scrollbar_layer->Update());
+  EXPECT_NE(0, scrollbar_layer->track_resource_id());
+  EXPECT_NE(0, scrollbar_layer->thumb_resource_id());
+  EXPECT_EQ(resource_count, layer_tree_host_->UIResourceCount());
+  EXPECT_EQ(expected_created, layer_tree_host_->TotalUIResourceCreated());
+  EXPECT_EQ(expected_deleted, layer_tree_host_->TotalUIResourceDeleted());
+
+  resource_count = 1;
+  expected_created = 10;
+  expected_deleted = 9;
   scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
   scrollbar_layer->fake_scrollbar()->set_has_thumb(false);
   scrollbar_layer->SetBounds(gfx::Size(90, 15));
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 53261d3..c1a1ec2 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -91,6 +91,12 @@
     NOTREACHED();
   }
 
+  LevelOfDetail getRequestedDetails() const override {
+    // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
+    // (crbug.com/499731).
+    return kObjectsBreakdowns_LevelOfDetail;
+  }
+
  private:
   // Helper to create allocator dumps.
   base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
@@ -190,11 +196,6 @@
 }
 
 OutputSurface::~OutputSurface() {
-  // Unregister any dump provider. Safe to call (no-op) if we have not yet
-  // registered.
-  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
-      this);
-
   if (client_)
     DetachFromClientInternal();
 }
@@ -226,7 +227,7 @@
   // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
   // Don't register a dump provider in these cases.
   // TODO(ericrk): Get this working in Android Webview. crbug.com/517156
-  if (base::ThreadTaskRunnerHandle::IsSet()) {
+  if (client_ && base::ThreadTaskRunnerHandle::IsSet()) {
     // Now that we are on the context thread, register a dump provider with this
     // thread's task runner. This will overwrite any previous dump provider
     // registered.
@@ -351,6 +352,12 @@
 void OutputSurface::DetachFromClientInternal() {
   DCHECK(client_thread_checker_.CalledOnValidThread());
   DCHECK(client_);
+
+  // Unregister any dump provider. Safe to call (no-op) if we have not yet
+  // registered.
+  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+      this);
+
   if (context_provider_.get()) {
     context_provider_->SetLostContextCallback(
         ContextProvider::LostContextCallback());
diff --git a/cc/output/overlay_strategy_common.cc b/cc/output/overlay_strategy_common.cc
index 243c1999..5048b1a 100644
--- a/cc/output/overlay_strategy_common.cc
+++ b/cc/output/overlay_strategy_common.cc
@@ -101,10 +101,6 @@
   quad_info->resource_size_in_pixels = quad.resource_size_in_pixels();
   quad_info->transform = overlay_transform;
   quad_info->uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
-  quad_info->quad_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
-      quad.shared_quad_state->quad_to_target_transform, quad.rect);
-  quad_info->clip_rect = quad.shared_quad_state->clip_rect;
-  quad_info->is_clipped = quad.shared_quad_state->is_clipped;
   return true;
 }
 
@@ -125,10 +121,6 @@
   quad_info->resource_id = quad.resource_id();
   quad_info->resource_size_in_pixels = quad.resource_size_in_pixels();
   quad_info->transform = overlay_transform;
-  quad_info->quad_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
-      quad.shared_quad_state->quad_to_target_transform, quad.rect);
-  quad_info->clip_rect = quad.shared_quad_state->clip_rect;
-  quad_info->is_clipped = quad.shared_quad_state->is_clipped;
 
   gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
   gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
@@ -170,10 +162,6 @@
   quad_info->resource_size_in_pixels = quad.io_surface_size;
   quad_info->transform = overlay_transform;
   quad_info->uv_rect = gfx::RectF(1.f, 1.f);
-  quad_info->quad_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
-      quad.shared_quad_state->quad_to_target_transform, quad.rect);
-  quad_info->clip_rect = quad.shared_quad_state->clip_rect;
-  quad_info->is_clipped = quad.shared_quad_state->is_clipped;
   return true;
 }
 
@@ -207,6 +195,10 @@
   quad_info->format = RGBA_8888;
   quad_info->display_rect = OverlayCandidate::GetOverlayRect(
       draw_quad.shared_quad_state->quad_to_target_transform, draw_quad.rect);
+  quad_info->quad_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
+      draw_quad.shared_quad_state->quad_to_target_transform, draw_quad.rect);
+  quad_info->clip_rect = draw_quad.shared_quad_state->clip_rect;
+  quad_info->is_clipped = draw_quad.shared_quad_state->is_clipped;
   return true;
 }
 
diff --git a/cc/output/overlay_strategy_sandwich.cc b/cc/output/overlay_strategy_sandwich.cc
index 446b4ef..1171edd 100644
--- a/cc/output/overlay_strategy_sandwich.cc
+++ b/cc/output/overlay_strategy_sandwich.cc
@@ -9,11 +9,29 @@
 #include "cc/output/overlay_candidate_validator.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/solid_color_draw_quad.h"
-#include "ui/gfx/geometry/dip_util.h"
-#include "ui/gfx/geometry/rect_conversions.h"
 
 namespace cc {
 
+namespace {
+
+void ClipDisplayAndUVRects(gfx::Rect* display_rect,
+                           gfx::RectF* uv_rect,
+                           const gfx::Rect& clip_rect) {
+  gfx::Rect display_cropped_rect =
+      gfx::IntersectRects(*display_rect, clip_rect);
+
+  gfx::RectF uv_cropped_rect = gfx::RectF(display_cropped_rect);
+  uv_cropped_rect -= gfx::Vector2dF(display_rect->x(), display_rect->y());
+  uv_cropped_rect.Scale(uv_rect->width() / display_rect->width(),
+                        uv_rect->height() / display_rect->height());
+  uv_cropped_rect += gfx::Vector2dF(uv_rect->x(), uv_rect->y());
+
+  *display_rect = display_cropped_rect;
+  *uv_rect = uv_cropped_rect;
+}
+
+}  // namespace
+
 OverlayStrategySandwich::~OverlayStrategySandwich() {}
 
 OverlayResult OverlayStrategySandwich::TryOverlay(
@@ -34,10 +52,14 @@
   if (!candidate_transform.GetInverse(&candidate_inverse_transform))
     return DID_NOT_CREATE_OVERLAY;
 
-  // Compute the candidate's rect in display space (pixels on the screen). The
-  // rect needs to be DIP-aligned, or we cannot use it.
-  const gfx::Rect candidate_pixel_rect =
-      gfx::ToNearestRect(candidate.display_rect);
+  // Compute the candidate's rect in display space (pixels on the screen).
+  gfx::Rect candidate_pixel_rect = candidate.quad_rect_in_target_space;
+  gfx::RectF candidate_uv_rect = candidate.uv_rect;
+  if (candidate.is_clipped &&
+      !candidate.clip_rect.Contains(candidate_pixel_rect)) {
+    ClipDisplayAndUVRects(&candidate_pixel_rect, &candidate_uv_rect,
+                          candidate.clip_rect);
+  }
 
   // Don't allow overlapping overlays for now.
   for (const OverlayCandidate& other_candidate : *candidate_list) {
@@ -54,8 +76,7 @@
        overlap_iter != *candidate_iter_in_quad_list; ++overlap_iter) {
     if (OverlayStrategyCommon::IsInvisibleQuad(*overlap_iter))
       continue;
-    // Compute the quad's bounds in display space, and ensure that it is rounded
-    // up to be DIP-aligned.
+    // Compute the quad's bounds in display space.
     gfx::Rect pixel_covered_rect = MathUtil::MapEnclosingClippedRect(
         overlap_iter->shared_quad_state->quad_to_target_transform,
         overlap_iter->rect);
@@ -70,7 +91,11 @@
   DCHECK(candidate.resource_id);
   OverlayCandidateList new_candidate_list = *candidate_list;
   new_candidate_list.push_back(candidate);
-  new_candidate_list.back().plane_z_order = 1;
+  OverlayCandidate& new_candidate = new_candidate_list.back();
+  new_candidate.plane_z_order = 1;
+  new_candidate.display_rect = gfx::RectF(candidate_pixel_rect);
+  new_candidate.quad_rect_in_target_space = candidate_pixel_rect;
+  new_candidate.uv_rect = candidate_uv_rect;
 
   // Add an overlay of the primary surface for any part of the candidate's
   // quad that was covered.
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 4e45aac..bfdfa9cd 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -60,9 +60,9 @@
 class SingleOverlayValidator : public OverlayCandidateValidator {
  public:
   void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
-    strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>(
+    strategies->push_back(make_scoped_ptr(
         new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop)));
-    strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>(
+    strategies->push_back(make_scoped_ptr(
         new OverlayStrategyCommon(this, new OverlayStrategyUnderlay)));
   }
   void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
@@ -88,10 +88,26 @@
   }
 };
 
+class SingleOnTopOverlayValidator : public SingleOverlayValidator {
+ public:
+  void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+    strategies->push_back(make_scoped_ptr(
+        new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop)));
+  }
+};
+
+class UnderlayOverlayValidator : public SingleOverlayValidator {
+ public:
+  void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+    strategies->push_back(make_scoped_ptr(
+        new OverlayStrategyCommon(this, new OverlayStrategyUnderlay)));
+  }
+};
+
 class SandwichOverlayValidator : public OverlayCandidateValidator {
  public:
   void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
-    strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>(
+    strategies->push_back(make_scoped_ptr(
         new OverlayStrategyCommon(this, new OverlayStrategySandwich)));
   }
   void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
@@ -100,24 +116,6 @@
   }
 };
 
-template <typename OverlayStrategyType>
-class SingleOverlayProcessor : public OverlayProcessor {
- public:
-  explicit SingleOverlayProcessor(OutputSurface* surface)
-      : OverlayProcessor(surface) {
-    EXPECT_EQ(surface, surface_);
-  }
-
-  // Virtual to allow testing different strategies.
-  void Initialize() override {
-    OverlayCandidateValidator* validator =
-        surface_->GetOverlayCandidateValidator();
-    ASSERT_TRUE(validator != NULL);
-    strategies_.push_back(scoped_ptr<Strategy>(
-        new OverlayStrategyCommon(validator, new OverlayStrategyType)));
-  }
-};
-
 class DefaultOverlayProcessor : public OverlayProcessor {
  public:
   explicit DefaultOverlayProcessor(OutputSurface* surface);
@@ -147,11 +145,8 @@
   // OutputSurface implementation
   void SwapBuffers(CompositorFrame* frame) override;
 
-  void InitWithSingleOverlayValidator() {
-    overlay_candidate_validator_.reset(new SingleOverlayValidator);
-  }
-  void InitWithSandwichOverlayValidator() {
-    overlay_candidate_validator_.reset(new SandwichOverlayValidator);
+  void SetOverlayCandidateValidator(OverlayCandidateValidator* validator) {
+    overlay_candidate_validator_.reset(validator);
   }
 
   OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
@@ -319,72 +314,15 @@
   }
 }
 
-TEST(OverlayTest, NoOverlaysByDefault) {
-  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
-  OverlayOutputSurface output_surface(provider);
-  EXPECT_EQ(NULL, output_surface.GetOverlayCandidateValidator());
-
-  output_surface.InitWithSingleOverlayValidator();
-  EXPECT_TRUE(output_surface.GetOverlayCandidateValidator() != NULL);
-}
-
-TEST(OverlayTest, OverlaysProcessorHasStrategy) {
-  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
-  OverlayOutputSurface output_surface(provider);
-  FakeOutputSurfaceClient client;
-  EXPECT_TRUE(output_surface.BindToClient(&client));
-  output_surface.InitWithSingleOverlayValidator();
-  EXPECT_TRUE(output_surface.GetOverlayCandidateValidator() != NULL);
-
-  scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
-      new TestSharedBitmapManager());
-  scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create(
-      &output_surface, shared_bitmap_manager.get());
-
-  scoped_ptr<DefaultOverlayProcessor> overlay_processor(
-      new DefaultOverlayProcessor(&output_surface));
-  overlay_processor->Initialize();
-  EXPECT_GE(2U, overlay_processor->GetStrategyCount());
-}
-
-template <typename OverlayStrategyType>
+template <typename OverlayCandidateValidatorType>
 class OverlayTest : public testing::Test {
  protected:
   void SetUp() override {
     provider_ = TestContextProvider::Create();
     output_surface_.reset(new OverlayOutputSurface(provider_));
     EXPECT_TRUE(output_surface_->BindToClient(&client_));
-    output_surface_->InitWithSingleOverlayValidator();
-    EXPECT_TRUE(output_surface_->GetOverlayCandidateValidator() != NULL);
-
-    shared_bitmap_manager_.reset(new TestSharedBitmapManager());
-    resource_provider_ = FakeResourceProvider::Create(
-        output_surface_.get(), shared_bitmap_manager_.get());
-
-    overlay_processor_.reset(
-        new SingleOverlayProcessor<OverlayStrategyType>(output_surface_.get()));
-    overlay_processor_->Initialize();
-  }
-
-  scoped_refptr<TestContextProvider> provider_;
-  scoped_ptr<OverlayOutputSurface> output_surface_;
-  FakeOutputSurfaceClient client_;
-  scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
-  scoped_ptr<ResourceProvider> resource_provider_;
-  scoped_ptr<SingleOverlayProcessor<OverlayStrategyType>> overlay_processor_;
-};
-
-typedef OverlayTest<OverlayStrategySingleOnTop> SingleOverlayOnTopTest;
-typedef OverlayTest<OverlayStrategyUnderlay> UnderlayTest;
-
-class SandwichTest : public testing::Test {
- protected:
-  void SetUp() override {
-    provider_ = TestContextProvider::Create();
-    output_surface_.reset(new OverlayOutputSurface(provider_));
-    EXPECT_TRUE(output_surface_->BindToClient(&client_));
-    output_surface_->InitWithSandwichOverlayValidator();
-    EXPECT_TRUE(output_surface_->GetOverlayCandidateValidator() != NULL);
+    output_surface_->SetOverlayCandidateValidator(
+        new OverlayCandidateValidatorType);
 
     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
     resource_provider_ = FakeResourceProvider::Create(
@@ -402,6 +340,37 @@
   scoped_ptr<OverlayProcessor> overlay_processor_;
 };
 
+typedef OverlayTest<SingleOnTopOverlayValidator> SingleOverlayOnTopTest;
+typedef OverlayTest<UnderlayOverlayValidator> UnderlayTest;
+typedef OverlayTest<SandwichOverlayValidator> SandwichTest;
+
+TEST(OverlayTest, NoOverlaysByDefault) {
+  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+  OverlayOutputSurface output_surface(provider);
+  EXPECT_EQ(NULL, output_surface.GetOverlayCandidateValidator());
+
+  output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
+  EXPECT_TRUE(output_surface.GetOverlayCandidateValidator() != NULL);
+}
+
+TEST(OverlayTest, OverlaysProcessorHasStrategy) {
+  scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+  OverlayOutputSurface output_surface(provider);
+  FakeOutputSurfaceClient client;
+  EXPECT_TRUE(output_surface.BindToClient(&client));
+  output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
+
+  scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
+      new TestSharedBitmapManager());
+  scoped_ptr<ResourceProvider> resource_provider = FakeResourceProvider::Create(
+      &output_surface, shared_bitmap_manager.get());
+
+  scoped_ptr<DefaultOverlayProcessor> overlay_processor(
+      new DefaultOverlayProcessor(&output_surface));
+  overlay_processor->Initialize();
+  EXPECT_GE(2U, overlay_processor->GetStrategyCount());
+}
+
 TEST_F(SandwichTest, SuccessfulSingleOverlay) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
   TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
@@ -438,6 +407,39 @@
   EXPECT_EQ(original_resource_id, candidate_list.back().resource_id);
 }
 
+TEST_F(SandwichTest, CroppedSingleOverlay) {
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+  pass->shared_quad_state_list.back()->is_clipped = true;
+  pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(0, 32, 64, 64);
+
+  TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back(),
+      pass.get());
+  original_quad->uv_top_left = gfx::PointF(0, 0);
+  original_quad->uv_bottom_right = gfx::PointF(1, 1);
+  unsigned candidate_id = original_quad->resource_id();
+
+  // Add something behind it.
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+  CreateFullscreenOpaqueQuad(resource_provider_.get(),
+                             pass->shared_quad_state_list.back(), pass.get());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+
+  // Ensure that the display and uv rects have cropping applied to them.
+  ASSERT_EQ(1U, pass_list.size());
+  ASSERT_EQ(2U, candidate_list.size());
+  EXPECT_EQ(candidate_id, candidate_list[1].resource_id);
+  EXPECT_EQ(gfx::RectF(0.f, 32.f, 64.f, 64.f), candidate_list[1].display_rect);
+  EXPECT_EQ(gfx::RectF(0.f, 0.25f, 0.5f, 0.5f), candidate_list[1].uv_rect);
+}
+
 TEST_F(SandwichTest, SuccessfulTwoOverlays) {
   scoped_ptr<RenderPass> pass = CreateRenderPass();
 
@@ -1241,7 +1243,7 @@
 
   void Init(bool use_validator) {
     if (use_validator)
-      output_surface_->InitWithSingleOverlayValidator();
+      output_surface_->SetOverlayCandidateValidator(new SingleOverlayValidator);
 
     renderer_ =
         make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
diff --git a/cc/playback/discardable_image_map.cc b/cc/playback/discardable_image_map.cc
index 36b1d00..a78ef5f 100644
--- a/cc/playback/discardable_image_map.cc
+++ b/cc/playback/discardable_image_map.cc
@@ -25,11 +25,11 @@
 
 // We're using an NWay canvas with no added canvases, so in effect
 // non-overridden functions are no-ops.
-class GatherDiscardableImageCanvas : public SkNWayCanvas {
+class DiscardableImagesMetadataCanvas : public SkNWayCanvas {
  public:
-  GatherDiscardableImageCanvas(int width,
-                               int height,
-                               std::vector<PositionImage>* image_set)
+  DiscardableImagesMetadataCanvas(int width,
+                                  int height,
+                                  std::vector<PositionImage>* image_set)
       : SkNWayCanvas(width, height),
         image_set_(image_set),
         canvas_bounds_(SkRect::MakeIWH(width, height)) {}
@@ -97,174 +97,40 @@
 
 }  // namespace
 
-DiscardableImageMap::DiscardableImageMap(const gfx::Size& cell_size)
-    : cell_size_(cell_size) {
-  DCHECK(!cell_size.IsEmpty());
-}
+DiscardableImageMap::DiscardableImageMap() {}
 
 DiscardableImageMap::~DiscardableImageMap() {}
 
-void DiscardableImageMap::GenerateDiscardableImagesMetadata(
-    SkPicture* picture,
-    const gfx::Rect& layer_rect) {
-  DCHECK(picture);
-
-  int min_x = std::numeric_limits<int>::max();
-  int min_y = std::numeric_limits<int>::max();
-  int max_x = 0;
-  int max_y = 0;
-
-  std::vector<PositionImage> images;
-  {
-    SkIRect picture_bounds = picture->cullRect().roundOut();
-    GatherDiscardableImageCanvas canvas(picture_bounds.right(),
-                                        picture_bounds.bottom(), &images);
-    canvas.drawPicture(picture);
-  }
-
-  for (auto& position_image : images) {
-    // The image rect is in space relative to the picture, but it can extend far
-    // beyond the picture itself (since it represents the rect of actual image
-    // contained within the picture, not clipped to picture bounds). We only
-    // care about image queries that intersect the picture, so insert only into
-    // the intersection of the two rects.
-    gfx::Rect rect_clipped_to_picture = gfx::IntersectRects(
-        gfx::ToEnclosingRect(gfx::SkRectToRectF(position_image.image_rect)),
-        gfx::Rect(layer_rect.size()));
-
-    gfx::Point min(MathUtil::UncheckedRoundDown(rect_clipped_to_picture.x(),
-                                                cell_size_.width()),
-                   MathUtil::UncheckedRoundDown(rect_clipped_to_picture.y(),
-                                                cell_size_.height()));
-    gfx::Point max(MathUtil::UncheckedRoundDown(rect_clipped_to_picture.right(),
-                                                cell_size_.width()),
-                   MathUtil::UncheckedRoundDown(
-                       rect_clipped_to_picture.bottom(), cell_size_.height()));
-
-    // We recorded the picture as if it was at (0, 0) by translating by layer
-    // rect origin. Add the rect origin back here. It really doesn't make much
-    // of a difference, since the query for pixel refs doesn't use this
-    // information. However, since picture pile / display list also returns this
-    // information, it would be nice to express it relative to the layer, not
-    // relative to the particular implementation of the raster source.
-    position_image.image_rect.offset(layer_rect.x(), layer_rect.y());
-
-    for (int y = min.y(); y <= max.y(); y += cell_size_.height()) {
-      for (int x = min.x(); x <= max.x(); x += cell_size_.width()) {
-        ImageMapKey key(x, y);
-        data_map_[key].push_back(position_image);
-      }
-    }
-
-    min_x = std::min(min_x, min.x());
-    min_y = std::min(min_y, min.y());
-    max_x = std::max(max_x, max.x());
-    max_y = std::max(max_y, max.y());
-  }
-
-  min_pixel_cell_ = gfx::Point(min_x, min_y);
-  max_pixel_cell_ = gfx::Point(max_x, max_y);
+scoped_ptr<SkCanvas> DiscardableImageMap::BeginGeneratingMetadata(
+    const gfx::Size& bounds) {
+  DCHECK(all_images_.empty());
+  return scoped_ptr<SkCanvas>(new DiscardableImagesMetadataCanvas(
+      bounds.width(), bounds.height(), &all_images_));
 }
 
-base::LazyInstance<DiscardableImageMap::Images>
-    DiscardableImageMap::Iterator::empty_images_;
-
-DiscardableImageMap::Iterator::Iterator()
-    : target_image_map_(NULL),
-      current_images_(empty_images_.Pointer()),
-      current_index_(0),
-      min_point_(-1, -1),
-      max_point_(-1, -1),
-      current_x_(0),
-      current_y_(0) {}
-
-DiscardableImageMap::Iterator::Iterator(const gfx::Rect& rect,
-                                        const DisplayItemList* display_list)
-    : target_image_map_(display_list->images_.get()),
-      current_images_(empty_images_.Pointer()),
-      current_index_(0) {
-  map_layer_rect_ = display_list->layer_rect_;
-  PointToFirstImage(rect);
+void DiscardableImageMap::EndGeneratingMetadata() {
+  images_rtree_.Build(all_images_, [](const PositionImage& image) {
+    return gfx::SkRectToRectF(image.image_rect);
+  });
 }
 
-DiscardableImageMap::Iterator::~Iterator() {}
-
-DiscardableImageMap::Iterator& DiscardableImageMap::Iterator::operator++() {
-  ++current_index_;
-  // If we're not at the end of the list, then we have the next item.
-  if (current_index_ < current_images_->size())
-    return *this;
-
-  DCHECK(current_y_ <= max_point_.y());
-  while (true) {
-    gfx::Size cell_size = target_image_map_->cell_size_;
-
-    // Advance the current grid cell.
-    current_x_ += cell_size.width();
-    if (current_x_ > max_point_.x()) {
-      current_y_ += cell_size.height();
-      current_x_ = min_point_.x();
-      if (current_y_ > max_point_.y()) {
-        current_images_ = empty_images_.Pointer();
-        current_index_ = 0;
-        break;
-      }
-    }
-
-    // If there are no pixel refs at this grid cell, keep incrementing.
-    ImageMapKey key(current_x_, current_y_);
-    ImageMap::const_iterator iter = target_image_map_->data_map_.find(key);
-    if (iter == target_image_map_->data_map_.end())
-      continue;
-
-    // We found a non-empty list: store it and get the first pixel ref.
-    current_images_ = &iter->second;
-    current_index_ = 0;
-    break;
-  }
-  return *this;
+void DiscardableImageMap::GetDiscardableImagesInRect(
+    const gfx::Rect& rect,
+    std::vector<PositionImage>* images) {
+  std::vector<size_t> indices;
+  images_rtree_.Search(gfx::RectF(rect), &indices);
+  for (size_t index : indices)
+    images->push_back(all_images_[index]);
 }
 
-void DiscardableImageMap::Iterator::PointToFirstImage(const gfx::Rect& rect) {
-  gfx::Rect query_rect(rect);
-  // Early out if the query rect doesn't intersect this picture.
-  if (!query_rect.Intersects(map_layer_rect_) || !target_image_map_) {
-    min_point_ = gfx::Point(0, 0);
-    max_point_ = gfx::Point(0, 0);
-    current_x_ = 1;
-    current_y_ = 1;
-    return;
-  }
+DiscardableImageMap::ScopedMetadataGenerator::ScopedMetadataGenerator(
+    DiscardableImageMap* image_map,
+    const gfx::Size& bounds)
+    : image_map_(image_map),
+      metadata_canvas_(image_map->BeginGeneratingMetadata(bounds)) {}
 
-  // First, subtract the layer origin as cells are stored in layer space.
-  query_rect.Offset(-map_layer_rect_.OffsetFromOrigin());
-
-  DCHECK(!target_image_map_->cell_size_.IsEmpty());
-  gfx::Size cell_size(target_image_map_->cell_size_);
-  // We have to find a cell_size aligned point that corresponds to
-  // query_rect. Point is a multiple of cell_size.
-  min_point_ = gfx::Point(
-      MathUtil::UncheckedRoundDown(query_rect.x(), cell_size.width()),
-      MathUtil::UncheckedRoundDown(query_rect.y(), cell_size.height()));
-  max_point_ = gfx::Point(
-      MathUtil::UncheckedRoundDown(query_rect.right() - 1, cell_size.width()),
-      MathUtil::UncheckedRoundDown(query_rect.bottom() - 1,
-                                   cell_size.height()));
-
-  // Limit the points to known pixel ref boundaries.
-  min_point_ = gfx::Point(
-      std::max(min_point_.x(), target_image_map_->min_pixel_cell_.x()),
-      std::max(min_point_.y(), target_image_map_->min_pixel_cell_.y()));
-  max_point_ = gfx::Point(
-      std::min(max_point_.x(), target_image_map_->max_pixel_cell_.x()),
-      std::min(max_point_.y(), target_image_map_->max_pixel_cell_.y()));
-
-  // Make the current x be cell_size.width() less than min point, so that
-  // the first increment will point at min_point_.
-  current_x_ = min_point_.x() - cell_size.width();
-  current_y_ = min_point_.y();
-  if (current_y_ <= max_point_.y())
-    ++(*this);
+DiscardableImageMap::ScopedMetadataGenerator::~ScopedMetadataGenerator() {
+  image_map_->EndGeneratingMetadata();
 }
 
 }  // namespace cc
diff --git a/cc/playback/discardable_image_map.h b/cc/playback/discardable_image_map.h
index 38ea3e6..e5928f7 100644
--- a/cc/playback/discardable_image_map.h
+++ b/cc/playback/discardable_image_map.h
@@ -11,7 +11,9 @@
 #include "base/containers/hash_tables.h"
 #include "base/lazy_instance.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
+#include "cc/base/rtree.h"
 #include "cc/playback/position_image.h"
 #include "third_party/skia/include/core/SkPicture.h"
 #include "ui/gfx/geometry/rect.h"
@@ -23,69 +25,41 @@
 
 class DisplayItemList;
 
-// This class is used to gather images which would happen after record. It takes
-// in |cell_size| to decide how big each grid cell should be.
+// This class is used for generating discardable images data (see PositionImage
+// for the type of data it stores). It allows the client to query a particular
+// rect and get back a list of PositionImages in that rect.
 class CC_EXPORT DiscardableImageMap {
  public:
   using Images = std::vector<PositionImage>;
 
-  explicit DiscardableImageMap(const gfx::Size& cell_size);
-  ~DiscardableImageMap();
-
-  void GenerateDiscardableImagesMetadata(SkPicture* picture,
-                                         const gfx::Rect& layer_rect);
-
-  bool empty() const { return data_map_.empty(); }
-
-  // This iterator imprecisely returns the set of images that are needed to
-  // raster this layer rect from this picture.  Internally, images are
-  // clumped into tile grid buckets, so there may be false positives.
-  class CC_EXPORT Iterator {
+  class CC_EXPORT ScopedMetadataGenerator {
    public:
-    // Default iterator constructor that is used as place holder for invalid
-    // Iterator.
-    Iterator();
-    Iterator(const gfx::Rect& layer_rect, const DisplayItemList* picture);
-    ~Iterator();
+    ScopedMetadataGenerator(DiscardableImageMap* image_map,
+                            const gfx::Size& bounds);
+    ~ScopedMetadataGenerator();
 
-    const PositionImage* operator->() const {
-      DCHECK_LT(current_index_, current_images_->size());
-      return &(*current_images_)[current_index_];
-    }
-
-    const PositionImage& operator*() const {
-      DCHECK_LT(current_index_, current_images_->size());
-      return (*current_images_)[current_index_];
-    }
-
-    Iterator& operator++();
-    operator bool() const { return current_index_ < current_images_->size(); }
+    SkCanvas* canvas() { return metadata_canvas_.get(); }
 
    private:
-    void PointToFirstImage(const gfx::Rect& query_rect);
-
-    static base::LazyInstance<Images> empty_images_;
-    const DiscardableImageMap* target_image_map_;
-    const Images* current_images_;
-    unsigned current_index_;
-
-    gfx::Rect map_layer_rect_;
-
-    gfx::Point min_point_;
-    gfx::Point max_point_;
-    int current_x_;
-    int current_y_;
+    DiscardableImageMap* image_map_;
+    scoped_ptr<SkCanvas> metadata_canvas_;
   };
 
+  DiscardableImageMap();
+  ~DiscardableImageMap();
+
+  bool empty() const { return all_images_.empty(); }
+  void GetDiscardableImagesInRect(const gfx::Rect& rect,
+                                  std::vector<PositionImage>* images);
+
  private:
-  gfx::Point min_pixel_cell_;
-  gfx::Point max_pixel_cell_;
-  gfx::Size cell_size_;
+  friend class ScopedMetadataGenerator;
 
-  using ImageMapKey = std::pair<int, int>;
-  using ImageMap = base::hash_map<ImageMapKey, Images>;
+  scoped_ptr<SkCanvas> BeginGeneratingMetadata(const gfx::Size& bounds);
+  void EndGeneratingMetadata();
 
-  ImageMap data_map_;
+  Images all_images_;
+  RTree images_rtree_;
 };
 
 }  // namespace cc
diff --git a/cc/playback/discardable_image_map_unittest.cc b/cc/playback/discardable_image_map_unittest.cc
index e11c3d0..65bf68e 100644
--- a/cc/playback/discardable_image_map_unittest.cc
+++ b/cc/playback/discardable_image_map_unittest.cc
@@ -34,11 +34,8 @@
       SkImage::NewFromGenerator(new TestImageGenerator(info)));
 }
 
-TEST(DiscardableImageMapTest, DiscardableImageMapIterator) {
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRect) {
   gfx::Rect visible_rect(2048, 2048);
-
-  gfx::Size tile_grid_size(512, 512);
-
   FakeContentLayerClient content_layer_client;
 
   // Discardable pixel refs are found in the following grids:
@@ -64,7 +61,7 @@
     }
   }
 
-  FakeDisplayListRecordingSource recording_source(tile_grid_size);
+  FakeDisplayListRecordingSource recording_source;
   Region invalidation(visible_rect);
   recording_source.SetGenerateDiscardableImagesMetadata(true);
   recording_source.UpdateAndExpandInvalidation(
@@ -72,101 +69,53 @@
       1, RecordingSource::RECORD_NORMALLY);
   DisplayItemList* display_list = recording_source.display_list();
 
-  // Default iterator does not have any pixel refs.
+  DiscardableImageMap image_map;
   {
-    DiscardableImageMap::Iterator iterator;
-    EXPECT_FALSE(iterator);
+    DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+                                                           visible_rect.size());
+    display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
   }
 
   for (int y = 0; y < 4; ++y) {
     for (int x = 0; x < 4; ++x) {
-      DiscardableImageMap::Iterator iterator(
-          gfx::Rect(x * 512, y * 512, 500, 500), display_list);
+      std::vector<PositionImage> images;
+      image_map.GetDiscardableImagesInRect(
+          gfx::Rect(x * 512, y * 512, 500, 500), &images);
       if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(iterator->image == discardable_image[y][x].get())
+        EXPECT_EQ(1u, images.size()) << x << " " << y;
+        EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
             << x << " " << y;
         EXPECT_EQ(gfx::RectF(x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
-                  gfx::SkRectToRectF(iterator->image_rect).ToString());
-        EXPECT_FALSE(++iterator) << x << " " << y;
+                  gfx::SkRectToRectF(images[0].image_rect).ToString());
       } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
+        EXPECT_EQ(0u, images.size()) << x << " " << y;
       }
     }
   }
 
   // Capture 4 pixel refs.
-  {
-    DiscardableImageMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
-                                           display_list);
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[1][2].get());
-    EXPECT_EQ(gfx::RectF(2 * 512 + 6, 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][1].get());
-    EXPECT_EQ(gfx::RectF(512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][3].get());
-    EXPECT_EQ(gfx::RectF(3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[3][2].get());
-    EXPECT_EQ(gfx::RectF(2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_FALSE(++iterator);
-  }
-
-  {
-    // Copy test.
-    DiscardableImageMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048),
-                                           display_list);
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[1][2].get());
-    EXPECT_EQ(gfx::RectF(2 * 512 + 6, 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][1].get());
-    EXPECT_EQ(gfx::RectF(512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-
-    // copy now points to the same spot as iterator,
-    // but both can be incremented independently.
-    DiscardableImageMap::Iterator copy = iterator;
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][3].get());
-    EXPECT_EQ(gfx::RectF(3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[3][2].get());
-    EXPECT_EQ(gfx::RectF(2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_FALSE(++iterator);
-
-    EXPECT_TRUE(copy);
-    EXPECT_TRUE(copy->image == discardable_image[2][1].get());
-    EXPECT_EQ(gfx::RectF(512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(copy->image == discardable_image[2][3].get());
-    EXPECT_EQ(gfx::RectF(3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(copy->image == discardable_image[3][2].get());
-    EXPECT_EQ(gfx::RectF(2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_FALSE(++copy);
-  }
+  std::vector<PositionImage> images;
+  image_map.GetDiscardableImagesInRect(gfx::Rect(512, 512, 2048, 2048),
+                                       &images);
+  EXPECT_EQ(4u, images.size());
+  EXPECT_TRUE(images[0].image == discardable_image[1][2].get());
+  EXPECT_EQ(gfx::RectF(2 * 512 + 6, 512 + 6, 500, 500).ToString(),
+            gfx::SkRectToRectF(images[0].image_rect).ToString());
+  EXPECT_TRUE(images[1].image == discardable_image[2][1].get());
+  EXPECT_EQ(gfx::RectF(512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+            gfx::SkRectToRectF(images[1].image_rect).ToString());
+  EXPECT_TRUE(images[2].image == discardable_image[2][3].get());
+  EXPECT_EQ(gfx::RectF(3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
+            gfx::SkRectToRectF(images[2].image_rect).ToString());
+  EXPECT_TRUE(images[3].image == discardable_image[3][2].get());
+  EXPECT_EQ(gfx::RectF(2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
+            gfx::SkRectToRectF(images[3].image_rect).ToString());
 }
 
-TEST(DiscardableImageMapTest, DiscardableImageMapIteratorNonZeroLayer) {
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectNonZeroLayer) {
   gfx::Rect visible_rect(1024, 0, 2048, 2048);
   // Make sure visible rect fits into the layer size.
   gfx::Size layer_size(visible_rect.right(), visible_rect.bottom());
-
-  gfx::Size tile_grid_size(512, 512);
-
   FakeContentLayerClient content_layer_client;
 
   // Discardable pixel refs are found in the following grids:
@@ -192,7 +141,7 @@
     }
   }
 
-  FakeDisplayListRecordingSource recording_source(tile_grid_size);
+  FakeDisplayListRecordingSource recording_source;
   Region invalidation(visible_rect);
   recording_source.set_pixel_record_distance(0);
   recording_source.SetGenerateDiscardableImagesMetadata(true);
@@ -201,120 +150,78 @@
       RecordingSource::RECORD_NORMALLY);
   DisplayItemList* display_list = recording_source.display_list();
 
-  // Default iterator does not have any pixel refs.
+  DiscardableImageMap image_map;
   {
-    DiscardableImageMap::Iterator iterator;
-    EXPECT_FALSE(iterator);
+    DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+                                                           layer_size);
+    display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
   }
 
   for (int y = 0; y < 4; ++y) {
     for (int x = 0; x < 4; ++x) {
-      DiscardableImageMap::Iterator iterator(
-          gfx::Rect(1024 + x * 512, y * 512, 500, 500), display_list);
+      std::vector<PositionImage> images;
+      image_map.GetDiscardableImagesInRect(
+          gfx::Rect(1024 + x * 512, y * 512, 500, 500), &images);
       if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(iterator->image == discardable_image[y][x].get());
+        EXPECT_EQ(1u, images.size()) << x << " " << y;
+        EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
+            << x << " " << y;
         EXPECT_EQ(
             gfx::RectF(1024 + x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
-            gfx::SkRectToRectF(iterator->image_rect).ToString());
-        EXPECT_FALSE(++iterator) << x << " " << y;
+            gfx::SkRectToRectF(images[0].image_rect).ToString());
       } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
+        EXPECT_EQ(0u, images.size()) << x << " " << y;
       }
     }
   }
   // Capture 4 pixel refs.
   {
-    DiscardableImageMap::Iterator iterator(
-        gfx::Rect(1024 + 512, 512, 2048, 2048), display_list);
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[1][2].get());
+    std::vector<PositionImage> images;
+    image_map.GetDiscardableImagesInRect(gfx::Rect(1024 + 512, 512, 2048, 2048),
+                                         &images);
+    EXPECT_EQ(4u, images.size());
+    EXPECT_TRUE(images[0].image == discardable_image[1][2].get());
     EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][1].get());
+              gfx::SkRectToRectF(images[0].image_rect).ToString());
+    EXPECT_TRUE(images[1].image == discardable_image[2][1].get());
     EXPECT_EQ(gfx::RectF(1024 + 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][3].get());
+              gfx::SkRectToRectF(images[1].image_rect).ToString());
+    EXPECT_TRUE(images[2].image == discardable_image[2][3].get());
     EXPECT_EQ(gfx::RectF(1024 + 3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[3][2].get());
+              gfx::SkRectToRectF(images[2].image_rect).ToString());
+    EXPECT_TRUE(images[3].image == discardable_image[3][2].get());
     EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_FALSE(++iterator);
-  }
-
-  // Copy test.
-  {
-    DiscardableImageMap::Iterator iterator(
-        gfx::Rect(1024 + 512, 512, 2048, 2048), display_list);
-    EXPECT_TRUE(iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[1][2].get());
-    EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][1].get());
-    EXPECT_EQ(gfx::RectF(1024 + 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-
-    // copy now points to the same spot as iterator,
-    // but both can be incremented independently.
-    DiscardableImageMap::Iterator copy = iterator;
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[2][3].get());
-    EXPECT_EQ(gfx::RectF(1024 + 3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_TRUE(++iterator);
-    EXPECT_TRUE(iterator->image == discardable_image[3][2].get());
-    EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(iterator->image_rect).ToString());
-    EXPECT_FALSE(++iterator);
-
-    EXPECT_TRUE(copy);
-    EXPECT_TRUE(copy->image == discardable_image[2][1].get());
-    EXPECT_EQ(gfx::RectF(1024 + 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(copy->image == discardable_image[2][3].get());
-    EXPECT_EQ(gfx::RectF(1024 + 3 * 512 + 6, 2 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_TRUE(++copy);
-    EXPECT_TRUE(copy->image == discardable_image[3][2].get());
-    EXPECT_EQ(gfx::RectF(1024 + 2 * 512 + 6, 3 * 512 + 6, 500, 500).ToString(),
-              gfx::SkRectToRectF(copy->image_rect).ToString());
-    EXPECT_FALSE(++copy);
+              gfx::SkRectToRectF(images[3].image_rect).ToString());
   }
 
   // Non intersecting rects
   {
-    DiscardableImageMap::Iterator iterator(gfx::Rect(0, 0, 1000, 1000),
-                                           display_list);
-    EXPECT_FALSE(iterator);
+    std::vector<PositionImage> images;
+    image_map.GetDiscardableImagesInRect(gfx::Rect(0, 0, 1000, 1000), &images);
+    EXPECT_EQ(0u, images.size());
   }
   {
-    DiscardableImageMap::Iterator iterator(gfx::Rect(3500, 0, 1000, 1000),
-                                           display_list);
-    EXPECT_FALSE(iterator);
+    std::vector<PositionImage> images;
+    image_map.GetDiscardableImagesInRect(gfx::Rect(3500, 0, 1000, 1000),
+                                         &images);
+    EXPECT_EQ(0u, images.size());
   }
   {
-    DiscardableImageMap::Iterator iterator(gfx::Rect(0, 1100, 1000, 1000),
-                                           display_list);
-    EXPECT_FALSE(iterator);
+    std::vector<PositionImage> images;
+    image_map.GetDiscardableImagesInRect(gfx::Rect(0, 1100, 1000, 1000),
+                                         &images);
+    EXPECT_EQ(0u, images.size());
   }
   {
-    DiscardableImageMap::Iterator iterator(gfx::Rect(3500, 1100, 1000, 1000),
-                                           display_list);
-    EXPECT_FALSE(iterator);
+    std::vector<PositionImage> images;
+    image_map.GetDiscardableImagesInRect(gfx::Rect(3500, 1100, 1000, 1000),
+                                         &images);
+    EXPECT_EQ(0u, images.size());
   }
 }
 
-TEST(DiscardableImageMapTest, DiscardableImageMapIteratorOnePixelQuery) {
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectOnePixelQuery) {
   gfx::Rect visible_rect(2048, 2048);
-
-  gfx::Size tile_grid_size(512, 512);
-
   FakeContentLayerClient content_layer_client;
 
   // Discardable pixel refs are found in the following grids:
@@ -340,7 +247,7 @@
     }
   }
 
-  FakeDisplayListRecordingSource recording_source(tile_grid_size);
+  FakeDisplayListRecordingSource recording_source;
   Region invalidation(visible_rect);
   recording_source.SetGenerateDiscardableImagesMetadata(true);
   recording_source.UpdateAndExpandInvalidation(
@@ -348,32 +255,33 @@
       1, RecordingSource::RECORD_NORMALLY);
   DisplayItemList* display_list = recording_source.display_list();
 
-  // Default iterator does not have any pixel refs.
+  DiscardableImageMap image_map;
   {
-    DiscardableImageMap::Iterator iterator;
-    EXPECT_FALSE(iterator);
+    DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+                                                           visible_rect.size());
+    display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
   }
 
   for (int y = 0; y < 4; ++y) {
     for (int x = 0; x < 4; ++x) {
-      DiscardableImageMap::Iterator iterator(
-          gfx::Rect(x * 512, y * 512 + 256, 1, 1), display_list);
+      std::vector<PositionImage> images;
+      image_map.GetDiscardableImagesInRect(
+          gfx::Rect(x * 512 + 256, y * 512 + 256, 1, 1), &images);
       if ((x + y) & 1) {
-        EXPECT_TRUE(iterator) << x << " " << y;
-        EXPECT_TRUE(iterator->image == discardable_image[y][x].get());
+        EXPECT_EQ(1u, images.size()) << x << " " << y;
+        EXPECT_TRUE(images[0].image == discardable_image[y][x].get())
+            << x << " " << y;
         EXPECT_EQ(gfx::RectF(x * 512 + 6, y * 512 + 6, 500, 500).ToString(),
-                  gfx::SkRectToRectF(iterator->image_rect).ToString());
-        EXPECT_FALSE(++iterator) << x << " " << y;
+                  gfx::SkRectToRectF(images[0].image_rect).ToString());
       } else {
-        EXPECT_FALSE(iterator) << x << " " << y;
+        EXPECT_EQ(0u, images.size()) << x << " " << y;
       }
     }
   }
 }
 
-TEST(DiscardableImageMapTest, DiscardableImageMapIteratorMassiveImage) {
+TEST(DiscardableImageMapTest, GetDiscardableImagesInRectMassiveImage) {
   gfx::Rect visible_rect(2048, 2048);
-  gfx::Size tile_grid_size(512, 512);
   FakeContentLayerClient content_layer_client;
 
   skia::RefPtr<SkImage> discardable_image;
@@ -382,7 +290,7 @@
   content_layer_client.add_draw_image(discardable_image.get(), gfx::Point(0, 0),
                                       paint);
 
-  FakeDisplayListRecordingSource recording_source(tile_grid_size);
+  FakeDisplayListRecordingSource recording_source;
   Region invalidation(visible_rect);
   recording_source.SetGenerateDiscardableImagesMetadata(true);
   recording_source.UpdateAndExpandInvalidation(
@@ -390,12 +298,18 @@
       1, RecordingSource::RECORD_NORMALLY);
   DisplayItemList* display_list = recording_source.display_list();
 
-  DiscardableImageMap::Iterator iterator(gfx::Rect(0, 0, 1, 1), display_list);
-  EXPECT_TRUE(iterator);
-  EXPECT_TRUE(iterator->image == discardable_image.get());
+  DiscardableImageMap image_map;
+  {
+    DiscardableImageMap::ScopedMetadataGenerator generator(&image_map,
+                                                           visible_rect.size());
+    display_list->Raster(generator.canvas(), nullptr, visible_rect, 1.f);
+  }
+  std::vector<PositionImage> images;
+  image_map.GetDiscardableImagesInRect(gfx::Rect(0, 0, 1, 1), &images);
+  EXPECT_EQ(1u, images.size());
+  EXPECT_TRUE(images[0].image == discardable_image.get());
   EXPECT_EQ(gfx::RectF(0, 0, 1 << 25, 1 << 25).ToString(),
-            gfx::SkRectToRectF(iterator->image_rect).ToString());
-  EXPECT_FALSE(++iterator);
+            gfx::SkRectToRectF(images[0].image_rect).ToString());
 }
 
 }  // namespace
diff --git a/cc/playback/display_item_list.cc b/cc/playback/display_item_list.cc
index f427f3a..a9fbfaa 100644
--- a/cc/playback/display_item_list.cc
+++ b/cc/playback/display_item_list.cc
@@ -269,17 +269,27 @@
           DisplayItemsTracingEnabled()));
 }
 
-void DisplayItemList::GenerateDiscardableImagesMetadata(
-    const gfx::Size& grid_cell_size) {
+void DisplayItemList::GenerateDiscardableImagesMetadata() {
   DCHECK(ProcessAppendedItemsCalled());
   // This should be only called once, and only after CreateAndCacheSkPicture.
   DCHECK(picture_);
-  DCHECK(!images_);
-  images_ = make_scoped_ptr(new DiscardableImageMap(grid_cell_size));
+  DCHECK(image_map_.empty());
   if (!picture_->willPlayBackBitmaps())
     return;
 
-  images_->GenerateDiscardableImagesMetadata(picture_.get(), layer_rect_);
+  // The cached picture is translated by -layer_rect_.origin during record,
+  // so we need to offset that back in order to get right positioning for
+  // images.
+  DiscardableImageMap::ScopedMetadataGenerator generator(
+      &image_map_, gfx::Size(layer_rect_.right(), layer_rect_.bottom()));
+  generator.canvas()->translate(layer_rect_.x(), layer_rect_.y());
+  generator.canvas()->drawPicture(picture_.get());
+}
+
+void DisplayItemList::GetDiscardableImagesInRect(
+    const gfx::Rect& rect,
+    std::vector<PositionImage>* images) {
+  image_map_.GetDiscardableImagesInRect(rect, images);
 }
 
 }  // namespace cc
diff --git a/cc/playback/display_item_list.h b/cc/playback/display_item_list.h
index 8b36ad63..12ad23c 100644
--- a/cc/playback/display_item_list.h
+++ b/cc/playback/display_item_list.h
@@ -76,7 +76,9 @@
 
   void EmitTraceSnapshot() const;
 
-  void GenerateDiscardableImagesMetadata(const gfx::Size& grid_cell_size);
+  void GenerateDiscardableImagesMetadata();
+  void GetDiscardableImagesInRect(const gfx::Rect& rect,
+                                  std::vector<PositionImage>* images);
 
  private:
   DisplayItemList(gfx::Rect layer_rect,
@@ -113,10 +115,9 @@
   // Memory usage due to external data held by display items.
   size_t external_memory_usage_;
 
-  scoped_ptr<DiscardableImageMap> images_;
+  DiscardableImageMap image_map_;
 
   friend class base::RefCountedThreadSafe<DisplayItemList>;
-  friend class DiscardableImageMap::Iterator;
   FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage);
   DISALLOW_COPY_AND_ASSIGN(DisplayItemList);
 };
diff --git a/cc/playback/display_list_raster_source.cc b/cc/playback/display_list_raster_source.cc
index 23432165..215f7d7 100644
--- a/cc/playback/display_list_raster_source.cc
+++ b/cc/playback/display_list_raster_source.cc
@@ -165,12 +165,7 @@
     const gfx::Rect& layer_rect,
     std::vector<PositionImage>* images) const {
   DCHECK_EQ(0u, images->size());
-
-  DiscardableImageMap::Iterator iterator(layer_rect, display_list_.get());
-  while (iterator) {
-    images->push_back(*iterator);
-    ++iterator;
-  }
+  display_list_->GetDiscardableImagesInRect(layer_rect, images);
 }
 
 bool DisplayListRasterSource::CoversRect(const gfx::Rect& layer_rect) const {
diff --git a/cc/playback/display_list_recording_source.cc b/cc/playback/display_list_recording_source.cc
index 63c0384..c790ebe 100644
--- a/cc/playback/display_list_recording_source.cc
+++ b/cc/playback/display_list_recording_source.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/numerics/safe_math.h"
 #include "cc/base/histograms.h"
 #include "cc/base/region.h"
 #include "cc/layers/content_layer_client.h"
@@ -41,8 +42,7 @@
 
 namespace cc {
 
-DisplayListRecordingSource::DisplayListRecordingSource(
-    const gfx::Size& grid_cell_size)
+DisplayListRecordingSource::DisplayListRecordingSource()
     : slow_down_raster_scale_factor_for_debug_(0),
       generate_discardable_images_metadata_(false),
       requires_clear_(false),
@@ -51,7 +51,6 @@
       solid_color_(SK_ColorTRANSPARENT),
       background_color_(SK_ColorTRANSPARENT),
       pixel_record_distance_(kPixelDistanceToRecord),
-      grid_cell_size_(grid_cell_size),
       painter_reported_memory_usage_(0) {}
 
 DisplayListRecordingSource::~DisplayListRecordingSource() {
@@ -149,8 +148,13 @@
   // Count the area that is being invalidated.
   Region recorded_invalidation(*invalidation);
   recorded_invalidation.Intersect(recorded_viewport_);
-  for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next())
-    timer.AddArea(it.rect().size().GetArea());
+  for (Region::Iterator it(recorded_invalidation); it.has_rect(); it.next()) {
+    // gfx::Size::GetArea might overflow in this case, so use an explicit
+    // CheckedNumeric instead.
+    base::CheckedNumeric<int> checked_area = it.rect().size().width();
+    checked_area *= it.rect().size().height();
+    timer.AddArea(checked_area);
+  }
 
   if (!updated && !invalidation->Intersects(recorded_viewport_))
     return false;
@@ -185,7 +189,7 @@
   DetermineIfSolidColor();
   display_list_->EmitTraceSnapshot();
   if (generate_discardable_images_metadata_)
-    display_list_->GenerateDiscardableImagesMetadata(grid_cell_size_);
+    display_list_->GenerateDiscardableImagesMetadata();
 
   return true;
 }
diff --git a/cc/playback/display_list_recording_source.h b/cc/playback/display_list_recording_source.h
index f61d8e2..b4250d0b 100644
--- a/cc/playback/display_list_recording_source.h
+++ b/cc/playback/display_list_recording_source.h
@@ -14,7 +14,7 @@
 
 class CC_EXPORT DisplayListRecordingSource : public RecordingSource {
  public:
-  explicit DisplayListRecordingSource(const gfx::Size& grid_cell_size);
+  DisplayListRecordingSource();
   ~DisplayListRecordingSource() override;
 
   // RecordingSource overrides.
@@ -55,7 +55,6 @@
   SkColor solid_color_;
   SkColor background_color_;
   int pixel_record_distance_;
-  gfx::Size grid_cell_size_;
 
   scoped_refptr<DisplayItemList> display_list_;
   size_t painter_reported_memory_usage_;
diff --git a/cc/playback/display_list_recording_source_unittest.cc b/cc/playback/display_list_recording_source_unittest.cc
index 0e4f8e3a..83d44036 100644
--- a/cc/playback/display_list_recording_source_unittest.cc
+++ b/cc/playback/display_list_recording_source_unittest.cc
@@ -15,14 +15,11 @@
 namespace {
 
 scoped_ptr<FakeDisplayListRecordingSource> CreateRecordingSource(
-    const gfx::Rect& viewport,
-    const gfx::Size& grid_cell_size) {
+    const gfx::Rect& viewport) {
   gfx::Rect layer_rect(viewport.right(), viewport.bottom());
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
       FakeDisplayListRecordingSource::CreateRecordingSource(viewport,
                                                             layer_rect.size());
-  recording_source->SetGridCellSize(grid_cell_size);
-
   return recording_source.Pass();
 }
 
@@ -34,13 +31,11 @@
 }
 
 TEST(DisplayListRecordingSourceTest, DiscardableImagesWithTransform) {
-  gfx::Size grid_cell_size(128, 128);
   gfx::Rect recorded_viewport(256, 256);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
       FakeDisplayListRecordingSource::CreateFilledRecordingSource(
           recorded_viewport.size());
-  recording_source->SetGridCellSize(grid_cell_size);
   skia::RefPtr<SkImage> discardable_image[2][2];
   gfx::Transform identity_transform;
   discardable_image[0][0] = CreateDiscardableImage(gfx::Size(32, 32));
@@ -92,7 +87,7 @@
   // Shifted tile sized iterators. These should find only one pixel ref.
   {
     std::vector<PositionImage> images;
-    raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 140, 128, 128),
+    raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 140, 128, 128),
                                               &images);
     EXPECT_EQ(1u, images.size());
     EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
@@ -103,7 +98,7 @@
   // The rotated bitmap would still be in the top right tile.
   {
     std::vector<PositionImage> images;
-    raster_source->GetDiscardableImagesInRect(gfx::Rect(140, 0, 128, 128),
+    raster_source->GetDiscardableImagesInRect(gfx::Rect(130, 0, 128, 128),
                                               &images);
     EXPECT_EQ(1u, images.size());
     EXPECT_TRUE(images[0].image == discardable_image[1][1].get());
@@ -111,36 +106,22 @@
               gfx::SkRectToRectF(images[0].image_rect).ToString());
   }
 
-  // Layer sized iterators. These should find all 6 pixel refs, including 1
-  // pixel ref bitmap[0][0], 1 pixel ref for bitmap[1][0], and 4 pixel refs for
-  // bitmap[1][1].
+  // Layer sized iterators. These should find all pixel refs.
   {
     std::vector<PositionImage> images;
     raster_source->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256),
                                               &images);
-    EXPECT_EQ(6u, images.size());
+    EXPECT_EQ(3u, images.size());
     // Top left tile with bitmap[0][0] and bitmap[1][1].
     EXPECT_TRUE(images[0].image == discardable_image[0][0].get());
-    EXPECT_TRUE(images[1].image == discardable_image[1][1].get());
-    // Top right tile with bitmap[1][1].
+    EXPECT_TRUE(images[1].image == discardable_image[1][0].get());
     EXPECT_TRUE(images[2].image == discardable_image[1][1].get());
-    // Bottom left tile with bitmap[1][0] and bitmap[1][1].
-    EXPECT_TRUE(images[3].image == discardable_image[1][0].get());
-    EXPECT_TRUE(images[4].image == discardable_image[1][1].get());
-    // Bottom right tile with bitmap[1][1].
-    EXPECT_TRUE(images[5].image == discardable_image[1][1].get());
     EXPECT_EQ(rect.ToString(),
               gfx::SkRectToRectF(images[0].image_rect).ToString());
-    EXPECT_EQ(rotate_rect.ToString(),
+    EXPECT_EQ(translate_rect.ToString(),
               gfx::SkRectToRectF(images[1].image_rect).ToString());
     EXPECT_EQ(rotate_rect.ToString(),
               gfx::SkRectToRectF(images[2].image_rect).ToString());
-    EXPECT_EQ(translate_rect.ToString(),
-              gfx::SkRectToRectF(images[3].image_rect).ToString());
-    EXPECT_EQ(rotate_rect.ToString(),
-              gfx::SkRectToRectF(images[4].image_rect).ToString());
-    EXPECT_EQ(rotate_rect.ToString(),
-              gfx::SkRectToRectF(images[5].image_rect).ToString());
   }
 }
 
@@ -242,8 +223,7 @@
 // right arguments.
 TEST(DisplayListRecordingSourceTest,
      ExposesEnoughNewAreaCalledWithCorrectArguments) {
-  gfx::Size grid_cell_size(128, 128);
-  DisplayListRecordingSource recording_source(grid_cell_size);
+  DisplayListRecordingSource recording_source;
   FakeContentLayerClient client;
   Region invalidation;
   gfx::Size layer_size(9000, 9000);
@@ -277,11 +257,10 @@
 }
 
 TEST(DisplayListRecordingSourceTest, NoGatherImageEmptyImages) {
-  gfx::Size grid_cell_size(128, 128);
   gfx::Rect recorded_viewport(0, 0, 256, 256);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
-      CreateRecordingSource(recorded_viewport, grid_cell_size);
+      CreateRecordingSource(recorded_viewport);
   recording_source->SetGenerateDiscardableImagesMetadata(false);
   recording_source->Rerecord();
 
@@ -298,11 +277,10 @@
 }
 
 TEST(DisplayListRecordingSourceTest, EmptyImages) {
-  gfx::Size grid_cell_size(128, 128);
   gfx::Rect recorded_viewport(0, 0, 256, 256);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
-      CreateRecordingSource(recorded_viewport, grid_cell_size);
+      CreateRecordingSource(recorded_viewport);
   recording_source->SetGenerateDiscardableImagesMetadata(true);
   recording_source->Rerecord();
 
@@ -333,11 +311,10 @@
 }
 
 TEST(DisplayListRecordingSourceTest, NoDiscardableImages) {
-  gfx::Size grid_cell_size(128, 128);
   gfx::Rect recorded_viewport(0, 0, 256, 256);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
-      CreateRecordingSource(recorded_viewport, grid_cell_size);
+      CreateRecordingSource(recorded_viewport);
 
   SkPaint simple_paint;
   simple_paint.setColor(SkColorSetARGB(255, 12, 23, 34));
@@ -392,11 +369,10 @@
 }
 
 TEST(DisplayListRecordingSourceTest, DiscardableImages) {
-  gfx::Size grid_cell_size(128, 128);
   gfx::Rect recorded_viewport(0, 0, 256, 256);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
-      CreateRecordingSource(recorded_viewport, grid_cell_size);
+      CreateRecordingSource(recorded_viewport);
 
   skia::RefPtr<SkImage> discardable_image[2][2];
   discardable_image[0][0] = CreateDiscardableImage(gfx::Size(32, 32));
@@ -470,11 +446,10 @@
 }
 
 TEST(DisplayListRecordingSourceTest, DiscardableImagesBaseNonDiscardable) {
-  gfx::Size grid_cell_size(256, 256);
   gfx::Rect recorded_viewport(0, 0, 512, 512);
 
   scoped_ptr<FakeDisplayListRecordingSource> recording_source =
-      CreateRecordingSource(recorded_viewport, grid_cell_size);
+      CreateRecordingSource(recorded_viewport);
 
   SkBitmap non_discardable_bitmap;
   non_discardable_bitmap.allocN32Pixels(512, 512);
diff --git a/cc/test/fake_display_list_recording_source.h b/cc/test/fake_display_list_recording_source.h
index 57298124..12121f5 100644
--- a/cc/test/fake_display_list_recording_source.h
+++ b/cc/test/fake_display_list_recording_source.h
@@ -21,9 +21,8 @@
 // display list.
 class FakeDisplayListRecordingSource : public DisplayListRecordingSource {
  public:
-  explicit FakeDisplayListRecordingSource(const gfx::Size& grid_cell_size)
-      : DisplayListRecordingSource(grid_cell_size),
-        force_unsuitable_for_gpu_rasterization_(false),
+  FakeDisplayListRecordingSource()
+      : force_unsuitable_for_gpu_rasterization_(false),
         playback_allowed_event_(nullptr) {}
   ~FakeDisplayListRecordingSource() override {}
 
@@ -31,8 +30,7 @@
       const gfx::Rect& recorded_viewport,
       const gfx::Size& layer_bounds) {
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     recording_source->SetRecordedViewport(recorded_viewport);
     recording_source->SetLayerBounds(layer_bounds);
     return recording_source;
@@ -41,8 +39,7 @@
   static scoped_ptr<FakeDisplayListRecordingSource> CreateFilledRecordingSource(
       const gfx::Size& layer_bounds) {
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     recording_source->SetRecordedViewport(gfx::Rect(layer_bounds));
     recording_source->SetLayerBounds(layer_bounds);
     return recording_source;
@@ -59,10 +56,6 @@
 
   void SetLayerBounds(const gfx::Size& layer_bounds) { size_ = layer_bounds; }
 
-  void SetGridCellSize(const gfx::Size& grid_cell_size) {
-    grid_cell_size_ = grid_cell_size;
-  }
-
   void SetClearCanvasWithDebugColor(bool clear) {
     clear_canvas_with_debug_color_ = clear;
   }
diff --git a/cc/test/fake_layer_tree_host_impl.cc b/cc/test/fake_layer_tree_host_impl.cc
index fba9a99..e210a76e6 100644
--- a/cc/test/fake_layer_tree_host_impl.cc
+++ b/cc/test/fake_layer_tree_host_impl.cc
@@ -12,38 +12,39 @@
 FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(Proxy* proxy,
                                              SharedBitmapManager* manager,
                                              TaskGraphRunner* task_graph_runner)
-    : LayerTreeHostImpl(LayerTreeSettings(),
-                        &client_,
-                        proxy,
-                        &stats_instrumentation_,
-                        manager,
-                        NULL,
-                        task_graph_runner,
-                        0) {
-  // Explicitly clear all debug settings.
-  SetDebugState(LayerTreeDebugState());
-  SetViewportSize(gfx::Size(100, 100));
-
-  // Start an impl frame so tests have a valid frame_time to work with.
-  base::TimeTicks time_ticks = base::TimeTicks::FromInternalValue(1);
-  WillBeginImplFrame(
-      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks));
-}
+    : FakeLayerTreeHostImpl(LayerTreeSettings(),
+                            proxy,
+                            manager,
+                            task_graph_runner,
+                            nullptr) {}
 
 FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(const LayerTreeSettings& settings,
                                              Proxy* proxy,
                                              SharedBitmapManager* manager,
                                              TaskGraphRunner* task_graph_runner)
+    : FakeLayerTreeHostImpl(settings,
+                            proxy,
+                            manager,
+                            task_graph_runner,
+                            nullptr) {}
+
+FakeLayerTreeHostImpl::FakeLayerTreeHostImpl(
+    const LayerTreeSettings& settings,
+    Proxy* proxy,
+    SharedBitmapManager* manager,
+    TaskGraphRunner* task_graph_runner,
+    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
     : LayerTreeHostImpl(settings,
                         &client_,
                         proxy,
                         &stats_instrumentation_,
                         manager,
-                        NULL,
+                        gpu_memory_buffer_manager,
                         task_graph_runner,
                         0) {
   // Explicitly clear all debug settings.
   SetDebugState(LayerTreeDebugState());
+  SetViewportSize(gfx::Size(100, 100));
 
   // Start an impl frame so tests have a valid frame_time to work with.
   base::TimeTicks time_ticks = base::TimeTicks::FromInternalValue(1);
diff --git a/cc/test/fake_layer_tree_host_impl.h b/cc/test/fake_layer_tree_host_impl.h
index e5a128c4..f47a098 100644
--- a/cc/test/fake_layer_tree_host_impl.h
+++ b/cc/test/fake_layer_tree_host_impl.h
@@ -10,6 +10,10 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/single_thread_proxy.h"
 
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
 namespace cc {
 
 class FakeLayerTreeHostImpl : public LayerTreeHostImpl {
@@ -21,6 +25,11 @@
                         Proxy* proxy,
                         SharedBitmapManager* manager,
                         TaskGraphRunner* task_graph_runner);
+  FakeLayerTreeHostImpl(const LayerTreeSettings& settings,
+                        Proxy* proxy,
+                        SharedBitmapManager* manager,
+                        TaskGraphRunner* task_graph_runner,
+                        gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
   ~FakeLayerTreeHostImpl() override;
 
   void ForcePrepareToDraw() {
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index dbe0f5e6..b9d3ab7 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -711,7 +711,11 @@
 
   if (was_canceled) {
     ++flush_stats_.canceled_count;
-    resource_pool_->ReleaseResource(resource, tile->invalidated_id());
+    // TODO(ericrk): If more partial raster work is done in the future, it may
+    // be worth returning the resource to the pool with its previous ID (not
+    // currently tracked). crrev.com/1370333002/#ps40001 has a possible method
+    // of achieving this.
+    resource_pool_->ReleaseResource(resource, 0 /* content_id */);
     return;
   }
 
@@ -729,9 +733,11 @@
   if (analysis.is_solid_color) {
     draw_info.set_solid_color(analysis.solid_color);
     if (resource) {
-      // Pass the old tile id here because the tile is solid color so we did not
-      // raster anything into the tile resource.
-      resource_pool_->ReleaseResource(resource, tile->invalidated_id());
+      // TODO(ericrk): If more partial raster work is done in the future, it may
+      // be worth returning the resource to the pool with its previous ID (not
+      // currently tracked). crrev.com/1370333002/#ps40001 has a possible method
+      // of achieving this.
+      resource_pool_->ReleaseResource(resource, 0 /* content_id */);
     }
   } else {
     DCHECK(resource);
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index 8b31016..e68ea1f 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -6,6 +6,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "cc/playback/display_list_raster_source.h"
 #include "cc/playback/display_list_recording_source.h"
+#include "cc/raster/raster_buffer.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/test/begin_frame_args_test.h"
 #include "cc/test/fake_display_list_raster_source.h"
@@ -17,6 +18,7 @@
 #include "cc/test/fake_picture_layer_impl.h"
 #include "cc/test/fake_picture_layer_tiling_client.h"
 #include "cc/test/fake_tile_manager.h"
+#include "cc/test/test_gpu_memory_buffer_manager.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/test/test_tile_priorities.h"
@@ -50,7 +52,8 @@
         host_impl_(LowResTilingsSettings(),
                    &proxy_,
                    &shared_bitmap_manager_,
-                   &task_graph_runner_) {}
+                   &task_graph_runner_,
+                   &gpu_memory_buffer_manager_) {}
 
   void SetTreePriority(TreePriority tree_priority) {
     GlobalStateThatImpactsTilePriority state;
@@ -150,6 +153,7 @@
 
   TestSharedBitmapManager shared_bitmap_manager_;
   TestTaskGraphRunner task_graph_runner_;
+  TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
   TileMemoryLimitPolicy memory_limit_policy_;
   int max_tiles_;
   bool ready_to_activate_;
@@ -1290,10 +1294,7 @@
   EXPECT_TRUE(have_tiles[TilePriority::EVENTUALLY]);
 }
 
-// TODO(vmpstr): Move these to LTHI tests, since they can't create real
-// resources and so they don't work with non-solid raster sources.
-// crbug.com/534911
-TEST_F(TileManagerTilePriorityQueueTest, DISABLED_SetIsLikelyToRequireADraw) {
+TEST_F(TileManagerTilePriorityQueueTest, SetIsLikelyToRequireADraw) {
   const gfx::Size layer_bounds(1000, 1000);
   host_impl_.SetViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
@@ -1309,11 +1310,8 @@
   EXPECT_TRUE(host_impl_.is_likely_to_require_a_draw());
 }
 
-// TODO(vmpstr): Move these to LTHI tests, since they can't create real
-// resources and so they don't work with non-solid raster sources.
-// crbug.com/534911
 TEST_F(TileManagerTilePriorityQueueTest,
-       DISABLED_SetIsLikelyToRequireADrawOnZeroMemoryBudget) {
+       SetIsLikelyToRequireADrawOnZeroMemoryBudget) {
   const gfx::Size layer_bounds(1000, 1000);
   host_impl_.SetViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
@@ -1333,11 +1331,8 @@
   EXPECT_FALSE(host_impl_.is_likely_to_require_a_draw());
 }
 
-// TODO(vmpstr): Move these to LTHI tests, since they can't create real
-// resources and so they don't work with non-solid raster sources.
-// crbug.com/534911
 TEST_F(TileManagerTilePriorityQueueTest,
-       DISABLED_SetIsLikelyToRequireADrawOnLimitedMemoryBudget) {
+       SetIsLikelyToRequireADrawOnLimitedMemoryBudget) {
   const gfx::Size layer_bounds(1000, 1000);
   host_impl_.SetViewportSize(layer_bounds);
   SetupDefaultTrees(layer_bounds);
@@ -1431,8 +1426,10 @@
   TileManagerTest()
       : output_surface_(FakeOutputSurface::CreateSoftware(
             make_scoped_ptr(new SoftwareOutputDevice))),
-        host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_) {
-    host_impl_.InitializeRenderer(output_surface_.get());
+        host_impl_(new MockLayerTreeHostImpl(&proxy_,
+                                             &shared_bitmap_manager_,
+                                             &task_graph_runner_)) {
+    host_impl_->InitializeRenderer(output_surface_.get());
   }
 
  protected:
@@ -1451,7 +1448,7 @@
   TestTaskGraphRunner task_graph_runner_;
   FakeImplProxy proxy_;
   scoped_ptr<OutputSurface> output_surface_;
-  MockLayerTreeHostImpl host_impl_;
+  scoped_ptr<MockLayerTreeHostImpl> host_impl_;
 };
 
 // Test to ensure that we call NotifyAllTileTasksCompleted when PrepareTiles is
@@ -1460,11 +1457,11 @@
   // Check with no tile work enqueued.
   {
     base::RunLoop run_loop;
-    EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
-    EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted())
+    EXPECT_FALSE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
+    EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
         .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
-    host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state());
-    EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
+    host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+    EXPECT_TRUE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
     run_loop.Run();
   }
 
@@ -1472,12 +1469,12 @@
   // callback.
   {
     base::RunLoop run_loop;
-    EXPECT_FALSE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
-    EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted())
+    EXPECT_FALSE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
+    EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
         .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
-    host_impl_.tile_manager()->PrepareTiles(host_impl_.global_tile_state());
-    host_impl_.tile_manager()->SetMoreTilesNeedToBeRasterizedForTesting();
-    EXPECT_TRUE(host_impl_.tile_manager()->HasScheduledTileTasksForTesting());
+    host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+    host_impl_->tile_manager()->SetMoreTilesNeedToBeRasterizedForTesting();
+    EXPECT_TRUE(host_impl_->tile_manager()->HasScheduledTileTasksForTesting());
     run_loop.Run();
   }
 }
@@ -1515,7 +1512,7 @@
     tiling_client.SetTileSize(size);
 
     scoped_ptr<PictureLayerImpl> layer =
-        PictureLayerImpl::Create(host_impl_.active_tree(), 1, false, nullptr);
+        PictureLayerImpl::Create(host_impl_->active_tree(), 1, false, nullptr);
     PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set();
 
     auto* tiling = tiling_set->AddTiling(1.0f, raster);
@@ -1529,14 +1526,14 @@
 
     // SMOOTHNESS_TAKES_PRIORITY ensures that we will actually raster
     // LOW_RESOLUTION tiles, otherwise they are skipped.
-    host_impl_.SetTreePriority(SMOOTHNESS_TAKES_PRIORITY);
+    host_impl_->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY);
 
     // Call PrepareTiles and wait for it to complete.
-    auto* tile_manager = host_impl_.tile_manager();
+    auto* tile_manager = host_impl_->tile_manager();
     base::RunLoop run_loop;
-    EXPECT_CALL(host_impl_, NotifyAllTileTasksCompleted())
+    EXPECT_CALL(*host_impl_, NotifyAllTileTasksCompleted())
         .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
-    tile_manager->PrepareTiles(host_impl_.global_tile_state());
+    tile_manager->PrepareTiles(host_impl_->global_tile_state());
     run_loop.Run();
     tile_manager->Flush();
 
@@ -1546,7 +1543,7 @@
     EXPECT_TRUE(tile->draw_info().IsReadyToDraw());
 
     ResourceProvider::ScopedReadLockSoftware lock(
-        host_impl_.resource_provider(), tile->draw_info().resource_id());
+        host_impl_->resource_provider(), tile->draw_info().resource_id());
     const SkBitmap* bitmap = lock.sk_bitmap();
     for (int x = 0; x < size.width(); ++x) {
       for (int y = 0; y < size.height(); ++y) {
@@ -1567,5 +1564,94 @@
   }
 }
 
+// Fake TileTaskRunner that just cancels all scheduled tasks immediately.
+class CancellingTileTaskRunner : public TileTaskRunner, public TileTaskClient {
+ public:
+  CancellingTileTaskRunner() {}
+
+  // TileTaskRunner methods.
+  void SetClient(TileTaskRunnerClient* client) override {}
+  void Shutdown() override {}
+  void CheckForCompletedTasks() override {}
+  ResourceFormat GetResourceFormat(bool must_support_alpha) const override {
+    return ResourceFormat::RGBA_8888;
+  }
+  bool GetResourceRequiresSwizzle(bool must_support_alpha) const override {
+    return false;
+  }
+
+  void ScheduleTasks(TileTaskQueue* queue) override {
+    // Just call CompleteOnOriginThread on each item in the queue. As none of
+    // these items have run yet, they will be treated as cancelled tasks.
+    for (const auto& task : queue->items) {
+      task.task->CompleteOnOriginThread(this);
+    }
+  }
+
+  // TileTaskClient methods.
+  scoped_ptr<RasterBuffer> AcquireBufferForRaster(
+      const Resource* resource,
+      uint64_t resource_content_id,
+      uint64_t previous_content_id) override {
+    NOTREACHED();
+    return nullptr;
+  }
+  void ReleaseBufferForRaster(scoped_ptr<RasterBuffer> buffer) override {}
+
+  ~CancellingTileTaskRunner() override {}
+};
+
+// Ensures that if a raster task is cancelled, it gets returned to the resource
+// pool with an invalid content ID, not with its invalidated content ID.
+TEST_F(TileManagerTest, CancelledTasksHaveNoContentId) {
+  // Create a CancellingTaskRunner and set it on the tile manager so that all
+  // scheduled work is immediately cancelled.
+  CancellingTileTaskRunner cancelling_runner;
+  host_impl_->tile_manager()->SetTileTaskRunnerForTesting(&cancelling_runner);
+
+  // Pick arbitrary IDs - they don't really matter as long as they're constant.
+  int layer_id = 7;
+  int invalidated_id = 43;
+
+  scoped_refptr<FakeDisplayListRasterSource> pending_raster_source =
+      FakeDisplayListRasterSource::CreateFilled(gfx::Size(128, 128));
+  host_impl_->CreatePendingTree();
+  LayerTreeImpl* pending_tree = host_impl_->pending_tree();
+
+  // Steal from the recycled tree.
+  scoped_ptr<FakePictureLayerImpl> pending_layer =
+      FakePictureLayerImpl::CreateWithRasterSource(pending_tree, layer_id,
+                                                   pending_raster_source);
+  pending_layer->SetDrawsContent(true);
+  pending_layer->SetHasRenderSurface(true);
+
+  // The bounds() just mirror the raster source size.
+  pending_layer->SetBounds(pending_layer->raster_source()->GetSize());
+  pending_tree->SetRootLayer(pending_layer.Pass());
+
+  // Add tilings/tiles for the layer.
+  host_impl_->pending_tree()->UpdateDrawProperties(false /* update_lcd_text */);
+
+  // Build the raster queue and invalidate the top tile.
+  scoped_ptr<RasterTilePriorityQueue> queue(host_impl_->BuildRasterQueue(
+      SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL));
+  EXPECT_FALSE(queue->IsEmpty());
+  queue->Top().tile()->SetInvalidated(gfx::Rect(), invalidated_id);
+
+  // PrepareTiles to schedule tasks. Due to the CancellingTileTaskRunner, these
+  // tasks will immediately be canceled.
+  host_impl_->tile_manager()->PrepareTiles(host_impl_->global_tile_state());
+
+  // Make sure that the tile we invalidated above was not returned to the pool
+  // with its invalidated resource ID.
+  host_impl_->resource_pool()->CheckBusyResources();
+  EXPECT_FALSE(host_impl_->resource_pool()->TryAcquireResourceWithContentId(
+      invalidated_id));
+
+  // Free our host_impl_ before the cancelling_runner we passed it, as it will
+  // use that class in clean up.
+  host_impl_ = nullptr;
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 9e7b390..2971304 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -812,6 +812,8 @@
       property_trees->transform_tree.Node(layer->transform_tree_index());
   const EffectNode* effect_node =
       property_trees->effect_tree.Node(layer->effect_tree_index());
+  const ClipNode* clip_node =
+      property_trees->clip_tree.Node(layer->clip_tree_index());
 
   draw_properties->target_space_transform =
       DrawTransformFromPropertyTreesInternal(layer, transform_node);
@@ -836,6 +838,7 @@
   draw_properties->can_use_lcd_text =
       LayerCanUseLcdText(layer, layers_always_allowed_lcd_text,
                          can_use_lcd_text, transform_node, effect_node);
+  draw_properties->is_clipped = clip_node->data.layers_are_clipped;
 
   gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
       draw_properties->target_space_transform, gfx::Rect(layer->bounds()));
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index bf4ad4f..f4231160 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -972,6 +972,8 @@
     scoped_refptr<Layer> page_scale_layer,
     scoped_refptr<Layer> inner_viewport_scroll_layer,
     scoped_refptr<Layer> outer_viewport_scroll_layer) {
+  DCHECK_IMPLIES(inner_viewport_scroll_layer,
+                 inner_viewport_scroll_layer != outer_viewport_scroll_layer);
   overscroll_elasticity_layer_ = overscroll_elasticity_layer;
   page_scale_layer_ = page_scale_layer;
   inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 28d59804..38b6a34 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -1949,7 +1949,7 @@
   // reduce how much would be drawn, and instead it would create unnecessary
   // changes to scissor state affecting GPU performance. Our clip information
   // is used in the recursion below, so we must set it beforehand.
-  DCHECK_EQ(layer_or_ancestor_clips_descendants, layer->is_clipped());
+  layer_draw_properties.is_clipped = layer_or_ancestor_clips_descendants;
   if (layer_or_ancestor_clips_descendants) {
     layer_draw_properties.clip_rect = clip_rect_in_target_space;
   } else {
@@ -2338,6 +2338,7 @@
 
   CHECK_EQ(current_layer->draw_opacity(), draw_properties.opacity);
   CHECK_EQ(current_layer->can_use_lcd_text(), draw_properties.can_use_lcd_text);
+  CHECK_EQ(current_layer->is_clipped(), draw_properties.is_clipped);
   CHECK_EQ(current_layer->screen_space_transform_is_animating(),
            draw_properties.screen_space_transform_is_animating);
 
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index cab0d5c..66e18ccc 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -1,4 +1,4 @@
-//// Copyright 2011 The Chromium Authors. All rights reserved.
+// Copyright 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.
 
@@ -1468,8 +1468,8 @@
   EXPECT_EQ(parent->id(), render_surface_layer_list_impl()->at(0)->id());
 }
 
-TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectly) {
-  // Layer's IsClipped() property is set to true when:
+TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectlyLayerImpl) {
+  // Tests that LayerImpl's IsClipped() property is set to true when:
   //  - the layer clips its subtree, e.g. masks to bounds,
   //  - the layer is clipped by an ancestor that contributes to the same
   //    render target,
@@ -1483,143 +1483,6 @@
   //    and propagates the clip to the subtree.
 
   const gfx::Transform identity_matrix;
-  scoped_refptr<Layer> root = Layer::Create(layer_settings());
-  scoped_refptr<Layer> parent = Layer::Create(layer_settings());
-  scoped_refptr<Layer> child1 = Layer::Create(layer_settings());
-  scoped_refptr<Layer> child2 = Layer::Create(layer_settings());
-  scoped_refptr<Layer> grand_child = Layer::Create(layer_settings());
-  scoped_refptr<LayerWithForcedDrawsContent> leaf_node1 =
-      make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-  scoped_refptr<LayerWithForcedDrawsContent> leaf_node2 =
-      make_scoped_refptr(new LayerWithForcedDrawsContent(layer_settings()));
-  root->AddChild(parent);
-  parent->AddChild(child1);
-  parent->AddChild(child2);
-  child1->AddChild(grand_child);
-  child2->AddChild(leaf_node2);
-  grand_child->AddChild(leaf_node1);
-
-  host()->SetRootLayer(root);
-
-  child2->SetForceRenderSurface(true);
-
-  SetLayerPropertiesForTesting(root.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(parent.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(child1.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(child2.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(grand_child.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(leaf_node1.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-  SetLayerPropertiesForTesting(leaf_node2.get(),
-                               identity_matrix,
-                               gfx::Point3F(),
-                               gfx::PointF(),
-                               gfx::Size(100, 100),
-                               true,
-                               false);
-
-  // Case 1: nothing is clipped except the root render surface.
-  {
-    LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root.get(),
-                                                        parent->bounds());
-    LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
-    ASSERT_TRUE(root->has_render_surface());
-    ASSERT_TRUE(child2->has_render_surface());
-
-    EXPECT_FALSE(root->is_clipped());
-    EXPECT_FALSE(parent->is_clipped());
-    EXPECT_FALSE(child1->is_clipped());
-    EXPECT_FALSE(child2->is_clipped());
-    EXPECT_FALSE(grand_child->is_clipped());
-    EXPECT_FALSE(leaf_node1->is_clipped());
-    EXPECT_FALSE(leaf_node2->is_clipped());
-  }
-
-  // Case 2: parent masksToBounds, so the parent, child1, and child2's
-  // surface are clipped. But layers that contribute to child2's surface are
-  // not clipped explicitly because child2's surface already accounts for
-  // that clip.
-  {
-    parent->SetMasksToBounds(true);
-    LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root.get(),
-                                                        parent->bounds());
-    LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
-    ASSERT_TRUE(root->has_render_surface());
-    ASSERT_TRUE(child2->has_render_surface());
-
-    EXPECT_FALSE(root->is_clipped());
-    EXPECT_TRUE(parent->is_clipped());
-    EXPECT_TRUE(child1->is_clipped());
-    EXPECT_FALSE(child2->is_clipped());
-    EXPECT_TRUE(grand_child->is_clipped());
-    EXPECT_TRUE(leaf_node1->is_clipped());
-    EXPECT_FALSE(leaf_node2->is_clipped());
-  }
-
-  // Case 3: child2 masksToBounds. The layer and subtree are clipped, and
-  // child2's render surface is not clipped.
-  {
-    parent->SetMasksToBounds(false);
-    child2->SetMasksToBounds(true);
-    LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(root.get(),
-                                                        parent->bounds());
-    LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
-    ASSERT_TRUE(root->has_render_surface());
-    ASSERT_TRUE(child2->has_render_surface());
-
-    EXPECT_FALSE(root->is_clipped());
-    EXPECT_FALSE(parent->is_clipped());
-    EXPECT_FALSE(child1->is_clipped());
-    EXPECT_TRUE(child2->is_clipped());
-    EXPECT_FALSE(grand_child->is_clipped());
-    EXPECT_FALSE(leaf_node1->is_clipped());
-    EXPECT_TRUE(leaf_node2->is_clipped());
-  }
-}
-
-TEST_F(LayerTreeHostCommonTest, IsClippedIsSetCorrectlyLayerImpl) {
-  // This is identical to the IsClippedIsSetCorrectly test,
-  // but tests render surfaces instead of the layers.
-
-  const gfx::Transform identity_matrix;
   LayerImpl* root = root_layer();
   LayerImpl* parent = AddChild<LayerImpl>(root);
   LayerImpl* child1 = AddChild<LayerImpl>(parent);
@@ -1676,11 +1539,6 @@
   // that clip.
   {
     parent->SetMasksToBounds(true);
-
-    parent->set_is_clipped(true);
-    child1->set_is_clipped(true);
-    grand_child->set_is_clipped(true);
-    leaf_node1->set_is_clipped(true);
     host_impl()->active_tree()->property_trees()->needs_rebuild = true;
 
     ExecuteCalculateDrawProperties(root);
@@ -1688,22 +1546,23 @@
     ASSERT_TRUE(root->render_surface());
     ASSERT_TRUE(child2->render_surface());
 
+    EXPECT_FALSE(root->is_clipped());
     EXPECT_TRUE(root->render_surface()->is_clipped());
+    EXPECT_TRUE(parent->is_clipped());
+    EXPECT_TRUE(child1->is_clipped());
+    EXPECT_FALSE(child2->is_clipped());
     EXPECT_TRUE(child2->render_surface()->is_clipped());
+    EXPECT_TRUE(grand_child->is_clipped());
+    EXPECT_TRUE(leaf_node1->is_clipped());
+    EXPECT_FALSE(leaf_node2->is_clipped());
 
     parent->SetMasksToBounds(false);
-    parent->set_is_clipped(false);
-    child1->set_is_clipped(false);
-    grand_child->set_is_clipped(false);
-    leaf_node1->set_is_clipped(false);
   }
 
   // Case 3: child2 masksToBounds. The layer and subtree are clipped, and
   // child2's render surface is not clipped.
   {
     child2->SetMasksToBounds(true);
-    child2->set_is_clipped(true);
-    leaf_node2->set_is_clipped(true);
     host_impl()->active_tree()->property_trees()->needs_rebuild = true;
 
     ExecuteCalculateDrawProperties(root);
@@ -7983,6 +7842,45 @@
   EXPECT_EQ(gfx::Rect(30, 30), test_layer2->visible_layer_rect());
 }
 
+TEST_F(LayerTreeHostCommonTest, UnclippedClipParent) {
+  LayerImpl* root = root_layer();
+  LayerImpl* clip_parent = AddChildToRoot<LayerImpl>();
+  LayerImpl* render_surface = AddChild<LayerImpl>(clip_parent);
+  LayerImpl* clip_child = AddChild<LayerImpl>(render_surface);
+
+  const gfx::Transform identity_matrix;
+  clip_parent->SetDrawsContent(true);
+  render_surface->SetMasksToBounds(true);
+  render_surface->SetDrawsContent(true);
+  clip_child->SetDrawsContent(true);
+
+  clip_child->SetClipParent(clip_parent);
+  scoped_ptr<std::set<LayerImpl*>> clip_children(new std::set<LayerImpl*>);
+  clip_children->insert(clip_child);
+  clip_parent->SetClipChildren(clip_children.release());
+
+  SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false,
+                               true);
+  SetLayerPropertiesForTesting(clip_parent, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false,
+                               false);
+  SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), true, false,
+                               true);
+  SetLayerPropertiesForTesting(clip_child, identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), true, false,
+                               false);
+
+  ExecuteCalculateDrawProperties(root);
+
+  // The clip child should inherit its clip parent's clipping state, not its
+  // tree parent's clipping state.
+  EXPECT_FALSE(clip_parent->is_clipped());
+  EXPECT_TRUE(render_surface->is_clipped());
+  EXPECT_FALSE(clip_child->is_clipped());
+}
+
 TEST_F(LayerTreeHostCommonTest,
        LayerClipRectLargerThanClippingRenderSurfaceRect) {
   LayerImpl* root = root_layer();
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 02bcb10..ab75b9c 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -181,7 +181,6 @@
       tree_resources_for_gpu_rasterization_dirty_(false),
       input_handler_client_(NULL),
       did_lock_scrolling_layer_(false),
-      should_bubble_scrolls_(false),
       wheel_scrolling_(false),
       scroll_affects_scroll_handler_(false),
       scroll_layer_id_when_mouse_over_scrollbar_(0),
@@ -498,8 +497,7 @@
   LayerImpl* scrolling_layer = CurrentlyScrollingLayer();
   if (!scrolling_layer)
     return false;
-  return scrolling_layer == InnerViewportScrollLayer() ||
-         scrolling_layer == OuterViewportScrollLayer();
+  return scrolling_layer == InnerViewportScrollLayer();
 }
 
 bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt(
@@ -2372,11 +2370,14 @@
 
   // Falling back to the root scroll layer ensures generation of root overscroll
   // notifications while preventing scroll updates from being unintentionally
-  // forwarded to the main thread.
+  // forwarded to the main thread. The inner viewport layer represents the
+  // viewport during scrolling.
   if (!potentially_scrolling_layer_impl)
-    potentially_scrolling_layer_impl = OuterViewportScrollLayer()
-                                           ? OuterViewportScrollLayer()
-                                           : InnerViewportScrollLayer();
+    potentially_scrolling_layer_impl = InnerViewportScrollLayer();
+
+  // The inner viewport layer represents the viewport.
+  if (potentially_scrolling_layer_impl == OuterViewportScrollLayer())
+    potentially_scrolling_layer_impl = InnerViewportScrollLayer();
 
   return potentially_scrolling_layer_impl;
 }
@@ -2401,7 +2402,6 @@
   top_controls_manager_->ScrollBegin();
 
   active_tree_->SetCurrentlyScrollingLayer(scrolling_layer_impl);
-  should_bubble_scrolls_ = (type != NON_BUBBLING_GESTURE);
   wheel_scrolling_ = (type == WHEEL);
   client_->RenewTreePriority();
   UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
@@ -2467,8 +2467,9 @@
   if (scroll_status == SCROLL_STARTED) {
     gfx::Vector2dF pending_delta = scroll_delta;
     for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl;
-         layer_impl = layer_impl->parent()) {
-      if (!layer_impl->scrollable())
+         layer_impl = NextLayerInScrollOrder(layer_impl)) {
+      // The inner viewport layer represents the viewport.
+      if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer())
         continue;
 
       gfx::ScrollOffset current_offset = layer_impl->CurrentScrollOffset();
@@ -2649,12 +2650,8 @@
 
   if (!scrolled)
     return;
-  // When scrolls are allowed to bubble, it's important that the original
-  // scrolling layer be preserved. This ensures that, after a scroll
-  // bubbles, the user can reverse scroll directions and immediately resume
-  // scrolling the original layer that scrolled.
-  if (!scroll_state->should_propagate())
-    scroll_state->set_current_native_scrolling_layer(layer);
+
+  scroll_state->set_current_native_scrolling_layer(layer);
 }
 
 InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
@@ -2668,7 +2665,7 @@
       top_controls_manager_->ControlsTopOffset();
   ScrollState scroll_state(
       scroll_delta.x(), scroll_delta.y(), viewport_point.x(),
-      viewport_point.y(), should_bubble_scrolls_ /* should_propagate */,
+      viewport_point.y(), false /* should_propagate */,
       did_lock_scrolling_layer_ /* delta_consumed_for_scroll_sequence */,
       !wheel_scrolling_ /* is_direct_manipulation */);
   scroll_state.set_current_native_scrolling_layer(CurrentlyScrollingLayer());
@@ -2745,10 +2742,10 @@
                                                ScrollDirection direction) {
   DCHECK(wheel_scrolling_);
 
-  for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
-       layer_impl;
-       layer_impl = layer_impl->parent()) {
-    if (!layer_impl->scrollable())
+  for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl;
+       layer_impl = NextLayerInScrollOrder(layer_impl)) {
+    // The inner viewport layer represents the viewport.
+    if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer())
       continue;
 
     if (!layer_impl->HasScrollbar(VERTICAL))
@@ -2810,17 +2807,6 @@
 InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
   if (!CurrentlyScrollingLayer())
     return SCROLL_IGNORED;
-
-  bool currently_scrolling_viewport =
-      CurrentlyScrollingLayer() == OuterViewportScrollLayer() ||
-      CurrentlyScrollingLayer() == InnerViewportScrollLayer();
-  if (!wheel_scrolling_ && !currently_scrolling_viewport) {
-    // Allow the fling to lock to the first layer that moves after the initial
-    // fling |ScrollBy()| event, unless we're already scrolling the viewport.
-    did_lock_scrolling_layer_ = false;
-    should_bubble_scrolls_ = false;
-  }
-
   return SCROLL_STARTED;
 }
 
@@ -2910,13 +2896,8 @@
   pinch_gesture_active_ = true;
   client_->RenewTreePriority();
   pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer();
-  if (active_tree_->OuterViewportScrollLayer()) {
-    active_tree_->SetCurrentlyScrollingLayer(
-        active_tree_->OuterViewportScrollLayer());
-  } else {
-    active_tree_->SetCurrentlyScrollingLayer(
-        active_tree_->InnerViewportScrollLayer());
-  }
+  active_tree_->SetCurrentlyScrollingLayer(
+      active_tree_->InnerViewportScrollLayer());
   top_controls_manager_->PinchBegin();
 }
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f804743d..f2d5dfaa 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -722,7 +722,6 @@
 
   InputHandlerClient* input_handler_client_;
   bool did_lock_scrolling_layer_;
-  bool should_bubble_scrolls_;
   bool wheel_scrolling_;
   bool scroll_affects_scroll_handler_;
   int scroll_layer_id_when_mouse_over_scrollbar_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 4939c27..3d47528b 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -102,6 +102,7 @@
     settings.minimum_occlusion_tracking_size = gfx::Size();
     settings.renderer_settings.texture_id_allocation_chunk_size = 1;
     settings.gpu_rasterization_enabled = true;
+    settings.verify_property_trees = true;
     return settings;
   }
 
@@ -302,6 +303,7 @@
   LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
     LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
         host_impl_->active_tree(), content_size);
+    host_impl_->active_tree()->BuildPropertyTreesForTesting();
     host_impl_->active_tree()->DidBecomeActive();
     return scroll_layer;
   }
@@ -350,11 +352,23 @@
 
   void DrawFrame() {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
 
+  void RebuildPropertyTrees() {
+    host_impl_->active_tree()->property_trees()->needs_rebuild = true;
+    host_impl_->active_tree()->BuildPropertyTreesForTesting();
+  }
+
+  DrawResult PrepareToDrawFrame(LayerTreeHostImpl::FrameData* frame) {
+    // We need to build property trees here before drawing the frame as they are
+    // not built on the impl thread.
+    RebuildPropertyTrees();
+    return host_impl_->PrepareToDraw(frame);
+  }
+
   void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
   void pinch_zoom_pan_viewport_test(float device_scale_factor);
   void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
@@ -410,7 +424,7 @@
 
   void DrawOneFrame() {
     LayerTreeHostImpl::FrameData frame_data;
-    host_impl_->PrepareToDraw(&frame_data);
+    PrepareToDrawFrame(&frame_data);
     host_impl_->DidDrawAllLayers(frame_data);
   }
 
@@ -658,6 +672,7 @@
     child_layer->SetPosition(gfx::PointF(0, 20));
     child_layer->SetBounds(gfx::Size(50, 50));
     scroll->AddChild(child_layer.Pass());
+    RebuildPropertyTrees();
   }
 
   // Touch handler regions determine whether touch events block scroll.
@@ -740,6 +755,7 @@
     scrollable_child_1->SetHaveScrollEventHandlers(true);
     scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
     root_child->AddChild(scrollable_child_clip_1.Pass());
+    RebuildPropertyTrees();
   }
 
   LayerImpl* child2 = 0;
@@ -754,6 +770,7 @@
     scrollable_child_2->SetHaveScrollEventHandlers(true);
     scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
     root_child->AddChild(scrollable_child_clip_2.Pass());
+    RebuildPropertyTrees();
   }
 
   // Scroll-blocks-on on a layer affects scrolls that hit that layer.
@@ -1055,19 +1072,19 @@
 
   host_impl_->ScrollBy(scroll_position, scroll_delta);
   host_impl_->ScrollEnd();
-  EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
 
   overflow->set_user_scrollable_vertical(false);
 
   EXPECT_EQ(InputHandler::SCROLL_STARTED,
             host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
-  EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
 
   host_impl_->ScrollBy(scroll_position, scroll_delta);
   host_impl_->ScrollEnd();
-  EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
+  EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), scroll_layer->CurrentScrollOffset());
   EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
 }
 
@@ -1252,6 +1269,7 @@
       gfx::Vector2dF(500, 500),
       outer_scroll_layer->MaxScrollOffset());
 
+  RebuildPropertyTrees();
   host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
@@ -1312,6 +1330,7 @@
       gfx::Vector2dF(500, 500),
       outer_scroll_layer->MaxScrollOffset());
 
+  RebuildPropertyTrees();
   host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
   host_impl_->PinchGestureBegin();
 
@@ -1367,6 +1386,7 @@
 
   // Pinch in within the margins. The scroll should stay exactly locked to the
   // bottom and right.
+  RebuildPropertyTrees();
   host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(2, anchor);
@@ -1444,6 +1464,7 @@
   // Zoom into the page by a 2X factor
   float min_page_scale = 1.f, max_page_scale = 4.f;
   float page_scale_factor = 2.f;
+  RebuildPropertyTrees();
   host_impl_->active_tree()->PushPageScaleFromMainThread(
       page_scale_factor, min_page_scale, max_page_scale);
   host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
@@ -1507,16 +1528,15 @@
   EXPECT_EQ(latency_info.trace_id(), scroll_info->swap_promises[0]->TraceId());
 }
 
-// Test that scrolls targeting a layer with a non-null scroll_parent() bubble
-// up to the scroll_parent, rather than the stacking parent.
-TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
+// Test that scrolls targeting a layer with a non-null scroll_parent() don't
+// bubble up.
+TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) {
   LayerImpl* viewport_scroll =
       SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->SetViewportSize(gfx::Size(50, 50));
 
   // Set up two scrolling children of the root, one of which is a scroll parent
-  // to the other. Scrolls bubbling from the child should bubble to the parent,
-  // not the viewport.
+  // to the other. Scrolls shouldn't bubbling from the child.
   LayerImpl *parent;
   LayerImpl *child;
   LayerImpl *child_clip;
@@ -1542,20 +1562,23 @@
   viewport_scroll->AddChild(scroll_child_clip.Pass());
 
   child_clip->SetScrollParent(parent);
+  scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
+  scroll_children->insert(child_clip);
+  parent->SetScrollChildren(scroll_children.release());
 
   DrawFrame();
 
   {
     host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
     host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
-    host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+    host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(100, 100));
     host_impl_->ScrollEnd();
 
     // The child should be fully scrolled by the first ScrollBy.
     EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
 
-    // The scroll_parent should receive the bubbled up second ScrollBy.
-    EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
+    // The scroll_parent shouldn't receive the second ScrollBy.
+    EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), parent->CurrentScrollOffset());
 
     // The viewport shouldn't have been scrolled at all.
     EXPECT_VECTOR_EQ(
@@ -1570,14 +1593,16 @@
     host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
     host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
     host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+    host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
+    host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
     host_impl_->ScrollEnd();
 
-    // The first ScrollBy should scroll the parent to its extent.
+    // The ScrollBy's should scroll the parent to its extent.
     EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
 
-    // The viewport should now be next in bubbling order.
+    // The viewport shouldn't receive any scroll delta.
     EXPECT_VECTOR_EQ(
-        gfx::Vector2dF(2, 1),
+        gfx::Vector2dF(0, 0),
         host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
     EXPECT_VECTOR_EQ(
         gfx::Vector2dF(0, 0),
@@ -2597,7 +2622,7 @@
 
   {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
 
@@ -2614,7 +2639,7 @@
     layer->set_will_draw_returns_false();
     layer->ClearDidDrawCheck();
 
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
 
@@ -2646,7 +2671,7 @@
   EXPECT_FALSE(layer->did_draw_called());
 
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -2661,7 +2686,7 @@
   EXPECT_FALSE(layer->will_draw_called());
   EXPECT_FALSE(layer->did_draw_called());
 
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -2700,7 +2725,7 @@
   EXPECT_FALSE(top_layer->will_draw_called());
   EXPECT_FALSE(top_layer->did_draw_called());
 
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -2735,7 +2760,7 @@
   LayerTreeHostImpl::FrameData frame;
   FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
       host_impl_->active_tree()->root_layer());
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -2885,7 +2910,7 @@
   root->SetHasRenderSurface(true);
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   host_impl_->SwapBuffers(frame);
@@ -2933,7 +2958,7 @@
       host_impl_->SetRequiresHighResToDraw();
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(testcase.expected_result, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
     host_impl_->SwapBuffers(frame);
@@ -2972,7 +2997,7 @@
   root->SetHasRenderSurface(true);
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   host_impl_->SwapBuffers(frame);
@@ -3020,7 +3045,7 @@
       host_impl_->SetRequiresHighResToDraw();
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(testcase.expected_result, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
     host_impl_->SwapBuffers(frame);
@@ -3670,7 +3695,8 @@
   EXPECT_EQ(InputHandler::SCROLL_STARTED,
             host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
-  EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
+
+  EXPECT_EQ(host_impl_->InnerViewportScrollLayer(),
             host_impl_->CurrentlyScrollingLayer());
   host_impl_->ScrollEnd();
 
@@ -3684,7 +3710,7 @@
   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
 
   EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
-  EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
+  EXPECT_EQ(host_impl_->InnerViewportScrollLayer(),
             host_impl_->CurrentlyScrollingLayer());
 
   host_impl_->ScrollEnd();
@@ -4003,6 +4029,7 @@
   LayerImpl* grand_child = child->children()[0];
 
   // Set new page scale on impl thread by pinching.
+  RebuildPropertyTrees();
   host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
   host_impl_->PinchGestureBegin();
   host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
@@ -4013,7 +4040,7 @@
   // Make sure all the layers are drawn with the page scale delta applied, i.e.,
   // the page scale delta on the root layer is applied hierarchically.
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -4068,8 +4095,7 @@
 
 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
   // Scroll a child layer beyond its maximum scroll range and make sure the
-  // parent layer is scrolled on the axis on which the child was unable to
-  // scroll.
+  // parent layer isn't scrolled.
   gfx::Size surface_size(10, 10);
   gfx::Size content_size(20, 20);
   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
@@ -4108,9 +4134,8 @@
     EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
                                    gfx::Vector2d(0, -5)));
 
-    // The child should have only scrolled on the other axis.
-    EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
-                                   gfx::Vector2d(-3, 0)));
+    // The child should not have scrolled.
+    ExpectNone(*scroll_info.get(), child->id());
   }
 }
 
@@ -4304,6 +4329,7 @@
   host_impl_->active_tree()->DidBecomeActive();
 
   // Scrolling should still work even though we did not draw yet.
+  RebuildPropertyTrees();
   EXPECT_EQ(InputHandler::SCROLL_STARTED,
             host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
 }
@@ -4409,8 +4435,7 @@
     host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
     host_impl_->ScrollEnd();
 
-    // The child layer should have scrolled down in its local coordinates an
-    // amount proportional to the angle between it and the input scroll delta.
+    // The child layer shouldn't have scrolled.
     gfx::Vector2d expected_scroll_delta(
         0, -gesture_scroll_delta.x() *
                std::sin(MathUtil::Deg2Rad(child_layer_angle)));
@@ -4419,14 +4444,8 @@
     EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
                                    expected_scroll_delta));
 
-    // The root scroll layer should have scrolled more, since the input scroll
-    // delta was mostly orthogonal to the child layer's vertical scroll axis.
-    gfx::Vector2d expected_root_scroll_delta(
-        gesture_scroll_delta.x() *
-            std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
-        0);
-    EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
-                                   expected_root_scroll_delta));
+    // The root scroll layer shouldn't have scrolled.
+    ExpectNone(*scroll_info.get(), scroll_layer->id());
   }
 }
 
@@ -4513,7 +4532,7 @@
   int scale = 2;
   gfx::Transform scale_transform;
   scale_transform.Scale(scale, scale);
-  scroll_layer->SetTransform(scale_transform);
+  scroll_layer->parent()->SetTransform(scale_transform);
 
   gfx::Size surface_size(50, 50);
   host_impl_->SetViewportSize(surface_size);
@@ -4748,7 +4767,7 @@
 
   // Check scroll delta reflected in layer.
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   EXPECT_FALSE(frame.has_no_damage);
@@ -5153,7 +5172,7 @@
   layer1->SetContentsOpaque(true);
   layer1->SetExpectation(false, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5162,7 +5181,7 @@
   layer1->SetContentsOpaque(false);
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5172,7 +5191,7 @@
   layer1->SetOpacity(0.5f);
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5182,7 +5201,7 @@
   layer1->SetOpacity(0.5f);
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5204,7 +5223,7 @@
   layer2->SetOpacity(1.f);
   layer2->SetExpectation(false, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5217,7 +5236,7 @@
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
   layer2->SetExpectation(false, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5231,7 +5250,7 @@
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
   layer2->SetExpectation(false, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5251,7 +5270,7 @@
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
   FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
       host_impl_->active_tree()->root_layer());
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5268,7 +5287,7 @@
   layer2->SetOpacity(0.5f);
   layer2->SetExpectation(true, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5283,7 +5302,7 @@
   layer2->SetOpacity(1.f);
   layer2->SetExpectation(true, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5299,7 +5318,7 @@
   layer2->SetOpacity(1.f);
   layer2->SetExpectation(false, false);
   layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   EXPECT_TRUE(layer2->quads_appended());
@@ -5312,7 +5331,7 @@
   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5324,7 +5343,7 @@
   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5336,7 +5355,7 @@
   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   layer1->SetExpectation(true, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5349,7 +5368,7 @@
   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   layer1->SetExpectation(false, false);
   layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
@@ -5393,7 +5412,7 @@
     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     ASSERT_EQ(1u, frame.render_passes.size());
 
     EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5413,7 +5432,7 @@
     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     ASSERT_EQ(1u, frame.render_passes.size());
 
     EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5433,7 +5452,7 @@
     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     ASSERT_EQ(1u, frame.render_passes.size());
 
     EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5454,7 +5473,7 @@
     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     ASSERT_EQ(1u, frame.render_passes.size());
 
     EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
@@ -5625,7 +5644,7 @@
   LayerTreeHostImpl::FrameData frame;
   host_impl_->SetViewportSize(gfx::Size(10, 10));
   host_impl_->active_tree()->SetDeviceScaleFactor(1.f);
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(provider->TestContext3d()->reshape_called());
   EXPECT_EQ(provider->TestContext3d()->width(), 10);
@@ -5635,7 +5654,7 @@
   provider->TestContext3d()->clear_reshape_called();
 
   host_impl_->SetViewportSize(gfx::Size(20, 30));
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(provider->TestContext3d()->reshape_called());
   EXPECT_EQ(provider->TestContext3d()->width(), 20);
@@ -5645,7 +5664,7 @@
   provider->TestContext3d()->clear_reshape_called();
 
   host_impl_->active_tree()->SetDeviceScaleFactor(2.f);
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   EXPECT_TRUE(provider->TestContext3d()->reshape_called());
   EXPECT_EQ(provider->TestContext3d()->width(), 20);
@@ -5752,7 +5771,7 @@
 
   LayerTreeHostImpl::FrameData frame;
 
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   EXPECT_EQ(1u, frame.render_surface_layer_list->size());
   EXPECT_EQ(1u, frame.render_passes.size());
   host_impl_->DidDrawAllLayers(frame);
@@ -5888,7 +5907,7 @@
   harness.MustSetNoScissor();
   {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
@@ -5901,8 +5920,7 @@
   harness.MustSetScissor(0, 0, 10, 10);
   {
     LayerTreeHostImpl::FrameData frame;
-    host_impl_->active_tree()->BuildPropertyTreesForTesting();
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
@@ -5924,7 +5942,7 @@
   harness.MustDrawSolidQuad();
   {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
@@ -5939,7 +5957,7 @@
   harness.MustDrawSolidQuad();
   {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
@@ -6113,7 +6131,7 @@
   EXPECT_EQ(0u, context3d->NumTextures());
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   host_impl_->SwapBuffers(frame);
@@ -6156,7 +6174,7 @@
   EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
       .Times(1);
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   Mock::VerifyAndClearExpectations(&mock_context);
@@ -6164,7 +6182,7 @@
   // Verify no quads are drawn when transparent background is set.
   host_impl_->active_tree()->set_has_transparent_background(true);
   host_impl_->SetFullRootLayerDamage();
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   Mock::VerifyAndClearExpectations(&mock_context);
@@ -6181,7 +6199,7 @@
     bool expect_to_draw = !expected_damage.IsEmpty();
 
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
 
     if (!expect_to_draw) {
       // With no damage, we don't draw, and no quads are created.
@@ -6321,6 +6339,7 @@
   scrolling_layer->SetScrollClipLayer(root->id());
   scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
 
+  host_impl_->pending_tree()->BuildPropertyTreesForTesting();
   host_impl_->ActivateSyncTree();
 
   bool update_lcd_text = false;
@@ -6328,7 +6347,7 @@
   ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
 
   ASSERT_EQ(1u, frame.render_passes.size());
   ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
@@ -6366,7 +6385,7 @@
   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
   {
     LayerTreeHostImpl::FrameData frame;
-    EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+    EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
   }
@@ -6460,7 +6479,7 @@
   SetupRootLayerImpl(root_layer.Pass());
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -6643,7 +6662,7 @@
   root->set_num_layer_or_descendant_with_copy_request(1);
 
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
@@ -6706,7 +6725,7 @@
   }
 }
 
-TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
+TEST_F(LayerTreeHostImplTest, TouchFlingShouldContinueScrollingCurrentLayer) {
   // Scroll a child layer beyond its maximum scroll range and make sure the
   // the scroll doesn't bubble up to the parent layer.
   gfx::Size surface_size(10, 10);
@@ -6748,40 +6767,35 @@
         ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
 
-    // The child should have received the bubbled delta, but the locked
-    // scrolling layer should remain set as the grand child.
-    EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+    // The locked scrolling layer should remain set as the grand child.
+    EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
     scroll_info = host_impl_->ProcessScrollDeltas();
-    ASSERT_EQ(2u, scroll_info->scrolls.size());
+    ASSERT_EQ(1u, scroll_info->scrolls.size());
     EXPECT_TRUE(
         ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
-    EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
+    ExpectNone(*scroll_info, child->id());
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
 
-    // The first |ScrollBy| after the fling should re-lock the scrolling
-    // layer to the first layer that scrolled, which is the child.
     EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
-    EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
-    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
+    EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
 
-    // The child should have scrolled up to its limit.
+    // The child should not have scrolled.
     scroll_info = host_impl_->ProcessScrollDeltas();
-    ASSERT_EQ(2u, scroll_info->scrolls.size());
+    ASSERT_EQ(1u, scroll_info->scrolls.size());
     EXPECT_TRUE(
         ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
-    EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
-                                   scroll_delta + scroll_delta));
+    ExpectNone(*scroll_info, child->id());
 
     // As the locked layer is at it's limit, no further scrolling can occur.
     EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
-    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
     host_impl_->ScrollEnd();
   }
 }
 
-TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
-  // When flinging via wheel, the root should eventually scroll (we should
-  // bubble).
+TEST_F(LayerTreeHostImplTest, WheelFlingShouldntBubble) {
+  // When flinging via wheel, we shouldn't bubble.
   gfx::Size surface_size(10, 10);
   gfx::Size content_size(20, 20);
   scoped_ptr<LayerImpl> root_clip =
@@ -6815,10 +6829,9 @@
     scoped_ptr<ScrollAndScaleSet> scroll_info =
         host_impl_->ProcessScrollDeltas();
 
-    // The root should have scrolled.
-    ASSERT_EQ(2u, scroll_info->scrolls.size());
-    EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
-                                   gfx::Vector2d(0, 10)));
+    // The root shouldn't have scrolled.
+    ASSERT_EQ(1u, scroll_info->scrolls.size());
+    ExpectNone(*scroll_info.get(), root_scroll_id);
   }
 }
 
@@ -7040,7 +7053,7 @@
 
   gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   EXPECT_TRUE(host_impl_->SwapBuffers(frame));
@@ -7087,7 +7100,7 @@
 
   gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
   LayerTreeHostImpl::FrameData frame;
-  EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
+  EXPECT_EQ(DRAW_SUCCESS, PrepareToDrawFrame(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
   EXPECT_TRUE(host_impl_->SwapBuffers(frame));
@@ -7755,15 +7768,15 @@
     // currently scrolling layer.
     EXPECT_EQ(InputHandler::SCROLL_STARTED,
               host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
     EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
 
     gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f,
                                inner_viewport.height() / 2.f);
     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
     inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
-    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
 
     host_impl_->ScrollEnd();
     EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
@@ -7774,17 +7787,17 @@
     // Fling past the inner viewport boundry, make sure outer viewport scrolls.
     EXPECT_EQ(InputHandler::SCROLL_STARTED,
               host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
     EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
 
     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
     inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
 
     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
     outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
-    EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
+    EXPECT_EQ(inner_scroll, host_impl_->CurrentlyScrollingLayer());
 
     host_impl_->ScrollEnd();
     EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
@@ -7847,7 +7860,7 @@
 }
 
 TEST_F(LayerTreeHostImplVirtualViewportTest,
-       TouchFlingCanLockToViewportLayerAfterBubbling) {
+       TouchFlingDoesntSwitchScrollingLayer) {
   gfx::Size content_size = gfx::Size(100, 160);
   gfx::Size outer_viewport = gfx::Size(50, 80);
   gfx::Size inner_viewport = gfx::Size(25, 40);
@@ -7880,25 +7893,23 @@
         ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
 
-    // The first |ScrollBy| after the fling should re-lock the scrolling
-    // layer to the first layer that scrolled, the inner viewport scroll layer.
+    // The fling have no effect on the currently scrolling layer.
     EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
-    EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
-    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+    EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
     EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
                                                         InputHandler::GESTURE));
 
-    // The inner viewport should have scrolled up to its limit.
+    // The inner viewport shouldn't have scrolled.
     scroll_info = host_impl_->ProcessScrollDeltas();
-    ASSERT_EQ(2u, scroll_info->scrolls.size());
+    ASSERT_EQ(1u, scroll_info->scrolls.size());
     EXPECT_TRUE(
         ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
-    EXPECT_TRUE(
-        ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
+    ExpectNone(*scroll_info, inner_scroll->id());
 
     // As the locked layer is at its limit, no further scrolling can occur.
     EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
-    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
     host_impl_->ScrollEnd();
     EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
         gfx::Point(), InputHandler::GESTURE));
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index fa97535..fe10a47 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1213,14 +1213,12 @@
     client_.set_fill_with_nonsolid_color(true);
 
     scoped_ptr<FakeDisplayListRecordingSource> recording(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     root_layer_ = FakePictureLayer::CreateWithRecordingSource(
         layer_settings(), &client_, recording.Pass());
     root_layer_->SetBounds(gfx::Size(50, 50));
 
-    recording.reset(new FakeDisplayListRecordingSource(
-        LayerTreeSettings().default_tile_grid_size));
+    recording.reset(new FakeDisplayListRecordingSource);
     child_layer_ = FakePictureLayer::CreateWithRecordingSource(
         layer_settings(), &client_, recording.Pass());
     child_layer_->SetBounds(gfx::Size(25, 25));
@@ -4435,7 +4433,7 @@
     LayerTreeHostTest::SetupTree();
 
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(gfx::Size(10, 10)));
+        new FakeDisplayListRecordingSource);
     recording_source_ = recording_source.get();
 
     scoped_refptr<FakePictureLayer> layer =
@@ -4490,7 +4488,7 @@
     LayerTreeHostTest::SetupTree();
 
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(gfx::Size()));
+        new FakeDisplayListRecordingSource);
     recording_source_ = recording_source.get();
 
     scoped_refptr<FakePictureLayer> layer =
@@ -4547,7 +4545,7 @@
     LayerTreeHostTest::SetupTree();
 
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(gfx::Size(10, 10)));
+        new FakeDisplayListRecordingSource);
     recording_source_ = recording_source.get();
 
     scoped_refptr<FakePictureLayer> layer =
@@ -4616,7 +4614,7 @@
     LayerTreeHostTest::SetupTree();
 
     scoped_ptr<FakeDisplayListRecordingSource> recording_source(
-        new FakeDisplayListRecordingSource(gfx::Size(100, 100)));
+        new FakeDisplayListRecordingSource);
     recording_source_ = recording_source.get();
 
     scoped_refptr<FakePictureLayer> layer =
@@ -5059,8 +5057,7 @@
     root->AddChild(pinch);
 
     scoped_ptr<FakeDisplayListRecordingSource> recording(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     recording->SetPlaybackAllowedEvent(&playback_allowed_event_);
     scoped_refptr<FakePictureLayer> layer =
         FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
@@ -5071,7 +5068,7 @@
     // pinch.
     pinch->AddChild(layer);
 
-    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
+    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, nullptr);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
     layer_tree_host()->SetRootLayer(root);
     LayerTreeHostTest::SetupTree();
@@ -5263,8 +5260,7 @@
     root->SetBounds(gfx::Size(500, 500));
 
     scoped_ptr<FakeDisplayListRecordingSource> recording(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     scoped_refptr<FakePictureLayer> layer =
         FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
                                                     recording.Pass());
@@ -5305,8 +5301,7 @@
     client_.set_fill_with_nonsolid_color(true);
 
     scoped_ptr<FakeDisplayListRecordingSource> recording(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     scoped_refptr<FakePictureLayer> root =
         FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
                                                     recording.Pass());
@@ -5358,8 +5353,7 @@
     root->AddChild(pinch);
 
     scoped_ptr<FakeDisplayListRecordingSource> recording(
-        new FakeDisplayListRecordingSource(
-            LayerTreeSettings().default_tile_grid_size));
+        new FakeDisplayListRecordingSource);
     recording->SetPlaybackAllowedEvent(&playback_allowed_event_);
     scoped_refptr<FakePictureLayer> layer =
         FakePictureLayer::CreateWithRecordingSource(layer_settings(), &client_,
@@ -5370,7 +5364,7 @@
     // pinch.
     pinch->AddChild(layer);
 
-    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, pinch);
+    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch, nullptr);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
     layer_tree_host()->SetRootLayer(root);
     LayerTreeHostTest::SetupTree();
diff --git a/cc/trees/layer_tree_host_unittest_picture.cc b/cc/trees/layer_tree_host_unittest_picture.cc
index 646b3a0..9c5d00e 100644
--- a/cc/trees/layer_tree_host_unittest_picture.cc
+++ b/cc/trees/layer_tree_host_unittest_picture.cc
@@ -410,7 +410,7 @@
     picture_->SetBounds(gfx::Size(100, 100));
     pinch_->AddChild(picture_);
 
-    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, pinch_);
+    layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, nullptr);
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
     layer_tree_host()->SetRootLayer(root);
     LayerTreeHostPictureTest::SetupTree();
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 90efa38..7cf7ddb 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -266,6 +266,8 @@
 }
 
 void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) {
+  DCHECK_IMPLIES(layer, layer != OuterViewportScrollLayer());
+
   int new_id = layer ? layer->id() : Layer::INVALID_ID;
   if (currently_scrolling_layer_id_ == new_id)
     return;
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 312ec33..414abb3 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -48,7 +48,6 @@
       background_animation_rate(1.0),
       default_tile_size(gfx::Size(256, 256)),
       max_untiled_layer_size(gfx::Size(512, 512)),
-      default_tile_grid_size(gfx::Size(256, 256)),
       minimum_occlusion_tracking_size(gfx::Size(160, 160)),
       // 3000 pixels should give sufficient area for prepainting.
       tiling_interest_area_padding(3000),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 664bbd1..f6656d5b 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -64,7 +64,6 @@
   double background_animation_rate;
   gfx::Size default_tile_size;
   gfx::Size max_untiled_layer_size;
-  gfx::Size default_tile_grid_size;
   gfx::Size minimum_occlusion_tracking_size;
   size_t tiling_interest_area_padding;
   float skewport_target_time_in_seconds;
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 2950775..d45d065 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -104,7 +104,8 @@
       use_only_parent_clip(false),
       layer_clipping_uses_only_local_clip(false),
       layer_visibility_uses_only_local_clip(false),
-      render_surface_is_clipped(false) {}
+      render_surface_is_clipped(false),
+      layers_are_clipped(false) {}
 
 EffectNodeData::EffectNodeData()
     : opacity(1.f),
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index b636595..49d159e 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -164,6 +164,7 @@
   bool layer_clipping_uses_only_local_clip : 1;
   bool layer_visibility_uses_only_local_clip : 1;
   bool render_surface_is_clipped : 1;
+  bool layers_are_clipped : 1;
 };
 
 typedef TreeNode<ClipNodeData> ClipNode;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index be6d8985..a5e209c 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -43,7 +43,6 @@
   bool affected_by_inner_viewport_bounds_delta;
   bool affected_by_outer_viewport_bounds_delta;
   bool should_flatten;
-  bool ancestor_clips_subtree;
   const gfx::Transform* device_transform;
   gfx::Vector2dF scroll_compensation_adjustment;
   int sequence_number;
@@ -100,25 +99,24 @@
   ClipNode* parent = GetClipParent(data_from_ancestor, layer);
   int parent_id = parent->id;
 
-  bool ancestor_clips_subtree =
-      data_from_ancestor.ancestor_clips_subtree ||
-      (layer->clip_parent() && layer->clip_parent()->is_clipped());
+  bool is_root = !layer->parent();
+  bool ancestor_clips_subtree = is_root || parent->data.layers_are_clipped;
 
-  data_for_children->ancestor_clips_subtree = false;
+  bool layers_are_clipped = false;
   bool has_unclipped_surface = false;
 
   if (layer->has_render_surface()) {
     if (ancestor_clips_subtree && layer->num_unclipped_descendants() > 0)
-      data_for_children->ancestor_clips_subtree = true;
+      layers_are_clipped = true;
     else if (!ancestor_clips_subtree)
       has_unclipped_surface = true;
   } else {
-    data_for_children->ancestor_clips_subtree = ancestor_clips_subtree;
+    layers_are_clipped = ancestor_clips_subtree;
   }
 
   bool layer_clips_subtree = LayerClipsSubtree(layer);
   if (layer_clips_subtree)
-    data_for_children->ancestor_clips_subtree = true;
+    layers_are_clipped = true;
 
   if (has_unclipped_surface) {
     parent_id = kUnclippedRootClipTreeNodeId;
@@ -129,6 +127,8 @@
                         ancestor_clips_subtree)) {
     // Unclipped surfaces reset the clip rect.
     data_for_children->clip_tree_parent = parent_id;
+    DCHECK_EQ(layers_are_clipped, data_for_children->clip_tree->Node(parent_id)
+                                      ->data.layers_are_clipped);
   } else {
     LayerType* transform_parent = data_for_children->transform_tree_parent;
     if (layer->position_constraint().is_fixed_position() &&
@@ -171,6 +171,7 @@
     node.data.render_surface_is_clipped = layer->has_render_surface() &&
                                           ancestor_clips_subtree &&
                                           !layer->num_unclipped_descendants();
+    node.data.layers_are_clipped = layers_are_clipped;
 
     data_for_children->clip_tree_parent =
         data_for_children->clip_tree->Insert(node, parent_id);
@@ -178,8 +179,6 @@
 
   layer->SetClipTreeIndex(data_for_children->clip_tree_parent);
 
-  layer->set_is_clipped(data_for_children->ancestor_clips_subtree);
-
   // TODO(awoloszyn): Right now when we hit a node with a replica, we reset the
   // clip for all children since we may need to draw. We need to figure out a
   // better way, since we will need both the clipped and unclipped versions.
@@ -533,7 +532,6 @@
   data_for_recursion.affected_by_inner_viewport_bounds_delta = false;
   data_for_recursion.affected_by_outer_viewport_bounds_delta = false;
   data_for_recursion.should_flatten = false;
-  data_for_recursion.ancestor_clips_subtree = true;
   data_for_recursion.device_transform = &device_transform;
 
   data_for_recursion.transform_tree->clear();
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index cefc074..49f614c 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -128,7 +128,6 @@
 
   if (scheduler_on_impl_thread_)
     scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
-  // Changing visibility could change ShouldComposite().
 }
 
 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
diff --git a/chrome/VERSION b/chrome/VERSION
index 46e4512..0994289 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=47
 MINOR=0
-BUILD=2522
+BUILD=2524
 PATCH=0
diff --git a/chrome/android/java/proguard.flags b/chrome/android/java/proguard.flags
index 79df662ea..42f25bd 100644
--- a/chrome/android/java/proguard.flags
+++ b/chrome/android/java/proguard.flags
@@ -113,6 +113,10 @@
   *;
 }
 
+-keepnames class jp.tomorrowkey.android.gifplayer.** {
+  public *;
+}
+
 # Used in tests.
 -keep class android.support.v4.view.ViewCompat {
   public static int getLayoutDirection(android.view.View);
diff --git a/chrome/android/java/res/layout/contextual_search_context_view.xml b/chrome/android/java/res/layout/contextual_search_context_view.xml
index 6027c48e..f96bb622 100644
--- a/chrome/android/java/res/layout/contextual_search_context_view.xml
+++ b/chrome/android/java/res/layout/contextual_search_context_view.xml
@@ -11,15 +11,10 @@
     android:gravity="center" >
     <!-- Search Bar Text -->
     <TextView
-        android:id="@+id/surrounding_text_start"
-        style="@style/ContextualSearchContextTextView"
-        android:layout_marginStart="7dp"
-        android:gravity="end" />
-    <TextView
         android:id="@+id/selected_text"
         style="@style/ContextualSearchTextView"
         android:layout_width="wrap_content"
-        android:layout_marginStart="5dp"
+        android:layout_marginStart="7dp"
         android:layout_marginEnd="5dp"
         android:gravity="center_horizontal" />
     <TextView
diff --git a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
new file mode 100644
index 0000000..c80f1357
--- /dev/null
+++ b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 The Chromium Authors. All rights reserved.
+
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+<org.chromium.chrome.browser.firstrun.DataReductionProxyView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginBottom="57dp"
+        android:fillViewport="true"
+        android:scrollbarStyle="outsideOverlay" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:orientation="vertical" >
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/fre_margin"
+                android:gravity="center"
+                android:lineSpacingMultiplier="1.4"
+                android:text="@string/data_reduction_promo_title"
+                android:textColor="@color/fre_title_color"
+                android:textSize="@dimen/fre_title_text_size" />
+
+            <LinearLayout
+                android:id="@+id/fre_content"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/fre_margin"
+                android:gravity="center_horizontal" >
+
+                <ImageView
+                    android:layout_width="wrap_content"
+                    android:layout_height="@dimen/fre_image_carousel_height"
+                    android:layout_marginBottom="@dimen/fre_margin"
+                    android:contentDescription="@null"
+                    android:src="@drawable/data_reduction_illustration" />
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginBottom="@dimen/fre_margin"
+                    android:orientation="vertical"
+                    android:gravity="center_horizontal"
+                    android:paddingEnd="24dp"
+                    android:paddingStart="24dp" >
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginBottom="@dimen/fre_margin"
+                        android:gravity="start"
+                        android:lineSpacingMultiplier="1.4"
+                        android:text="@string/data_reduction_promo_summary"
+                        android:textColor="@color/fre_text_color"
+                        android:textSize="@dimen/fre_normal_text_size" />
+
+                    <Switch
+                        android:id="@+id/enable_data_saver_switch"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:gravity="start"
+                        android:lineSpacingMultiplier="1.4"
+                        android:showText="false"
+                        android:textOff="@string/data_reduction_disabled_switch"
+                        android:text="@string/data_reduction_enabled_switch"
+                        android:textColor="@color/fre_text_color"
+                        android:textSize="@dimen/fre_normal_text_size"
+                        android:fontFamily="sans-serif-medium" />
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+    </ScrollView>
+
+    <View
+        style="@style/ButtonBarTopDivider"
+        android:layout_gravity="bottom"
+        android:layout_marginBottom="56dp" />
+
+    <Button
+        android:id="@+id/next_button"
+        android:layout_width="match_parent"
+        android:layout_height="56dp"
+        android:layout_gravity="bottom"
+        android:background="?attr/listChoiceBackgroundIndicator"
+        android:padding="16dp"
+        android:text="@string/next"
+        android:textAllCaps="true"
+        android:textColor="@color/light_active_color"
+        android:textSize="@dimen/fre_button_text_size" />
+
+</org.chromium.chrome.browser.firstrun.DataReductionProxyView>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 3764bee..65bd1d7 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -295,5 +295,5 @@
     <dimen name="media_session_icon_size">48dp</dimen>
 
     <!-- Offline pages dimensions -->
-    <dimen name="offline_page_item_vertical_spacing">40dp</dimen>
+    <dimen name="offline_page_item_vertical_spacing">16dp</dimen>
 </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java b/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java
index 79bdda7..446f8bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/CertificateViewer.java
@@ -77,7 +77,7 @@
 
         TextView title = new TextView(mContext);
         title.setText(R.string.certtitle);
-        title.setTextAppearance(mContext, android.R.style.TextAppearance_Large);
+        ApiCompatibilityUtils.setTextAppearance(title, android.R.style.TextAppearance_Large);
         title.setTypeface(title.getTypeface(), Typeface.BOLD);
         title.setPadding(mPadding, mPadding, mPadding, mPadding / 2);
         dialogContainer.addView(title);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 3a2e74e..91956e10 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser;
 
 import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.SearchManager;
 import android.app.assist.AssistContent;
@@ -117,6 +118,7 @@
 import org.chromium.chrome.browser.toolbar.Toolbar;
 import org.chromium.chrome.browser.toolbar.ToolbarControlContainer;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.webapps.AddToHomescreenDialog;
 import org.chromium.chrome.browser.widget.ControlContainer;
@@ -485,6 +487,11 @@
             }
 
             @Override
+            public void onShown(Tab tab) {
+                setStatusBarColor(tab, tab.getThemeColor());
+            }
+
+            @Override
             public void onHidden(Tab tab) {
                 mLoFiBarPopupController.dismissLoFiBar();
             }
@@ -514,9 +521,10 @@
 
             @Override
             public void onDidChangeThemeColor(Tab tab, int color) {
-                if (getToolbarManager() == null) return;
                 if (getActivityTab() != tab) return;
+                setStatusBarColor(tab, color);
 
+                if (getToolbarManager() == null) return;
                 getToolbarManager().updatePrimaryColor(color);
 
                 ControlContainer controlContainer =
@@ -549,6 +557,17 @@
         mCompositorViewHolder.resetFlags();
     }
 
+    /**
+     * Set device status bar to a given color.
+     * @param tab The tab that is currently showing.
+     * @param color The color that the status bar should be set to.
+     */
+    protected void setStatusBarColor(Tab tab, int color) {
+        int statusBarColor = (tab != null && tab.getDefaultThemeColor() == color)
+                ? Color.BLACK : ColorUtils.getDarkenedColorForStatusBar(color);
+        ApiCompatibilityUtils.setStatusBarColor(getWindow(), statusBarColor);
+    }
+
     private void createContextReporterIfNeeded() {
         if (mContextReporter != null || getActivityTab() == null) return;
 
@@ -698,10 +717,8 @@
         if (mSnackbarManager != null) mSnackbarManager.dismissSnackbar(false);
     }
 
-    // @TargetApi(Build.VERSION_CODES.M) TODO(sgurun) add method document once API is public
-    // crbug/512264
-    // @Override
     @Override
+    @TargetApi(Build.VERSION_CODES.M)
     public void onProvideAssistContent(AssistContent outContent) {
         if (getAssistStatusHandler() == null || !getAssistStatusHandler().isAssistSupported()) {
             // No information is provided in incognito mode.
@@ -1358,6 +1375,8 @@
         if (id == R.id.preferences_id) {
             PreferencesLauncher.launchSettingsPage(this, null);
             RecordUserAction.record("MobileMenuSettings");
+        } else if (id == R.id.show_menu) {
+            showAppMenuForKeyboardEvent();
         }
 
         // All the code below assumes currentTab is not null, so return early if it is null.
@@ -1421,8 +1440,6 @@
             HelpAndFeedback.getInstance(this)
                     .show(this, helpContextId, currentTab.getProfile(), currentTab.getUrl());
             RecordUserAction.record("MobileMenuFeedback");
-        } else if (id == R.id.show_menu) {
-            showAppMenuForKeyboardEvent();
         } else {
             return false;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 7e7c276..70be34d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -9,6 +9,7 @@
 import android.app.SearchManager;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Color;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -21,6 +22,7 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.CommandLine;
 import org.chromium.base.Log;
 import org.chromium.base.MemoryPressureListener;
@@ -1262,16 +1264,26 @@
     public void onOverviewModeStartedShowing(boolean showToolbar) {
         if (mFindToolbarManager != null) mFindToolbarManager.hideToolbar();
         if (getAssistStatusHandler() != null) getAssistStatusHandler().updateAssistState();
+        ApiCompatibilityUtils.setStatusBarColor(getWindow(), Color.BLACK);
     }
 
     @Override
     public void onOverviewModeFinishedShowing() {}
 
     @Override
-    public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {}
+    public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
+    }
 
     @Override
     public void onOverviewModeFinishedHiding() {
         if (getAssistStatusHandler() != null) getAssistStatusHandler().updateAssistState();
+        if (getActivityTab() != null) {
+            setStatusBarColor(getActivityTab(), getActivityTab().getThemeColor());
+        }
+    }
+
+    @Override
+    protected void setStatusBarColor(Tab tab, int color) {
+        super.setStatusBarColor(tab, isInOverviewMode() ? Color.BLACK : color);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
index 4c64f16..ab5eda0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
@@ -126,6 +126,8 @@
         findMatchRectsDetails.rects[index] = rect;
     }
 
+    protected static native void nativeOnRendererUnresponsive(WebContents webContents);
+    protected static native void nativeOnRendererResponsive(WebContents webContents);
     protected static native boolean nativeIsCapturingAudio(WebContents webContents);
     protected static native boolean nativeIsCapturingVideo(WebContents webContents);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
index 23bcf84..8db380e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/EmbedContentViewActivity.java
@@ -17,6 +17,7 @@
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.webapps.FullScreenActivity;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -111,6 +112,11 @@
     }
 
     @Override
+    protected void setStatusBarColor(Tab tab, int color) {
+        // Intentionally do nothing as EmbedContentViewActivity does not set status bar color.
+    }
+
+    @Override
     protected TabDelegate createTabDelegate(boolean incognito) {
         return new TabDelegate(incognito) {
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
index e920b4ca..fb192fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
@@ -204,7 +204,7 @@
             } else {
                 view.setBackground(null);
                 if (!isEnabled(position)) {
-                    view.setTextColor(getContext().getResources().getColor(
+                    view.setTextColor(ApiCompatibilityUtils.getColor(getContext().getResources(),
                             R.color.primary_text_disabled_material_light));
                 } else {
                     view.setTextColor(mDefaultTextColor);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java
index 7cddae98..975372f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java
@@ -22,7 +22,6 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
@@ -280,8 +279,8 @@
         text.setPadding(hPadding, vPadding, hPadding, vPadding);
 
         mStoreLocallyTooltipPopup.setContentView(text);
-        mStoreLocallyTooltipPopup.setWindowLayoutMode(
-                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+        mStoreLocallyTooltipPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+        mStoreLocallyTooltipPopup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
         mStoreLocallyTooltipPopup.setOutsideTouchable(true);
         mStoreLocallyTooltipPopup.setBackgroundDrawable(ApiCompatibilityUtils.getDrawable(
                 resources, R.drawable.store_locally_tooltip_background));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmark/AsyncTaskFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmark/AsyncTaskFragment.java
index cfa1d60..5bb8a97 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmark/AsyncTaskFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmark/AsyncTaskFragment.java
@@ -7,6 +7,7 @@
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.ProgressDialog;
+import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
@@ -160,6 +161,8 @@
         }
     }
 
+    // TODO: remove this than we only support Build.VERSION_CODES.M and newer.
+    @SuppressWarnings("deprecation")
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
@@ -167,6 +170,12 @@
     }
 
     @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        showDialog();
+    }
+
+    @Override
     public void onDetach() {
         super.onDetach();
         hideDialog();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/BottomBarTextControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/BottomBarTextControl.java
deleted file mode 100644
index 3b24383..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/BottomBarTextControl.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2015 The Chromium 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.compositor.bottombar.contextualsearch;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnDrawListener;
-import android.widget.TextView;
-
-import org.chromium.chrome.R;
-import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
-
-
-/**
- * Root ControlContainer for the Contextual Search panel.
- * Handles user interaction with the bottom bar text.
- * Based on ToolbarControlContainer.
- */
-public class BottomBarTextControl {
-    /**
-     * Object Replacement Character that is used in place of HTML objects that cannot be represented
-     * as text (e.g. images). Contextual search panel should not be displaying such characters as
-     * they get shown as [obj] character.
-     */
-    private static final String OBJ_CHARACTER = "\uFFFC";
-
-    private Context mContext;
-    private ViewGroup mContainer;
-
-    private ViewGroup mSearchContextView;
-    private TextView mSelectedText;
-    private TextView mStartText;
-    private TextView mEndText;
-    private ViewResourceAdapter mSearchContextResourceAdapter;
-    private boolean mIsSearchContextDirty;
-
-    private ViewGroup mSearchTermView;
-    private TextView mSearchTermText;
-    private ViewResourceAdapter mSearchTermResourceAdapter;
-    private boolean mIsSearchTermDirty;
-
-    /**
-     * Constructs a new bottom bar control container by inflating views from XML.
-     *
-     * @param context The context used to build this view.
-     * @param container The parent view for the bottom bar views.
-     */
-    public BottomBarTextControl(Context context, ViewGroup container) {
-        mContext = context;
-        mContainer = container;
-
-        // TODO(pedrosimonetti): For now, we're still relying on a Android View
-        // to render the text that appears in the Search Bar. The View will be
-        // invisible and will not capture events. Consider rendering the text
-        // in the Compositor and get rid of the View entirely.
-        // TODO(twellington): Make this class more generic so that it can be reused by ReaderMode.
-        LayoutInflater.from(mContext).inflate(R.layout.contextual_search_term_view, container);
-        mSearchTermView = (ViewGroup) container.findViewById(R.id.contextual_search_term_view);
-        mSearchTermText = (TextView) container.findViewById(R.id.contextual_search_term);
-        mSearchTermResourceAdapter = new ViewResourceAdapter(mSearchTermView);
-
-        // mSearchTermResourceAdapter needs to be invalidated in OnDraw after it has been measured.
-        // Without this OnDrawListener, the search text view wasn't always appearing on the panel
-        // for RTL text.
-        mSearchTermView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
-            @Override
-            public void onDraw() {
-                if (mIsSearchTermDirty) {
-                    mSearchTermResourceAdapter.invalidate(null);
-                    mIsSearchTermDirty = false;
-                }
-            }
-        });
-
-        LayoutInflater.from(mContext).inflate(R.layout.contextual_search_context_view, container);
-        mSearchContextView = (ViewGroup) container.findViewById(
-                R.id.contextual_search_context_view);
-        mSelectedText = (TextView) mSearchContextView.findViewById(R.id.selected_text);
-        mStartText = (TextView) mSearchContextView.findViewById(R.id.surrounding_text_start);
-        mEndText = (TextView) mSearchContextView.findViewById(R.id.surrounding_text_end);
-        mSearchContextResourceAdapter = new ViewResourceAdapter(mSearchContextView);
-
-        // mSearchContextResourceAdapter needs to be invalidated in OnDraw after it has been
-        // measured. Without this OnDrawListener, the selected text view was occasionally getting
-        // ellipsized.
-        mSearchContextView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
-            @Override
-            public void onDraw() {
-                if (mIsSearchContextDirty) {
-                    mSearchContextResourceAdapter.invalidate(null);
-                    mIsSearchContextDirty = false;
-                }
-            }
-        });
-    }
-
-    /**
-     * @return The {@link ViewResourceAdapter} that exposes the search context view as a CC
-     *         resource.
-     */
-    public ViewResourceAdapter getSearchContextResourceAdapter() {
-        return mSearchContextResourceAdapter;
-    }
-
-    /**
-     * @return The {@link ViewResourceAdapter} that exposes the search term view as a CC resource.
-     */
-    public ViewResourceAdapter getSearchTermResourceAdapter() {
-        return mSearchTermResourceAdapter;
-    }
-
-    /**
-     * @param width The width of the container.
-     */
-    public void setWidth(int width) {
-        mSearchContextView.getLayoutParams().width = width;
-        mSearchContextView.requestLayout();
-        mSearchTermView.getLayoutParams().width = width;
-        mSearchTermView.requestLayout();
-    }
-
-    /**
-     * Removes the bottom bar views from the parent container.
-     */
-    public void removeFromContainer() {
-        mContainer.removeView(mSearchTermView);
-        mContainer.removeView(mSearchContextView);
-    }
-
-    /**
-     * Sets the search context to display in the control.
-     * @param selection The portion of the context that represents the user's selection.
-     * @param start The portion of the context from its start to the selection.
-     * @param end The portion of the context the selection to its end.
-     */
-    public void setSearchContext(String selection, String start, String end) {
-        mSelectedText.setText(sanitizeText(selection));
-        mStartText.setText(sanitizeText(start));
-        mEndText.setText(sanitizeText(end));
-        mIsSearchContextDirty = true;
-    }
-
-    /**
-     * Sets the search term to display in the control.
-     * @param searchTerm The string that represents the search term.
-     */
-    public void setSearchTerm(String searchTerm) {
-        mSearchTermText.setText(searchTerm);
-        mIsSearchTermDirty = true;
-    }
-
-    private String sanitizeText(String text) {
-        if (text == null) return null;
-        return text.replace(OBJ_CHARACTER, " ");
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
new file mode 100644
index 0000000..b99ed07b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
@@ -0,0 +1,78 @@
+// Copyright 2015 The Chromium 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.compositor.bottombar.contextualsearch;
+
+import android.content.Context;
+import android.view.ViewGroup;
+
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+
+/**
+ * Controls the Search Bar in the Contextual Search Panel.
+ */
+public class ContextualSearchBarControl {
+    /**
+     * The {@link ContextualSearchContextControl} used to control the Search Context View.
+     */
+    private final ContextualSearchContextControl mContextControl;
+
+    /**
+     * The {@link ContextualSearchTermControl} used to control the Search Term View.
+     */
+    private final ContextualSearchTermControl mSearchTermControl;
+
+    /**
+     * Constructs a new bottom bar control container by inflating views from XML.
+     *
+     * @param panel     The panel delegate.
+     * @param context   The context used to build this view.
+     * @param container The parent view for the bottom bar views.
+     * @param loader    The resource loader that will handle the snapshot capturing.
+     */
+    public ContextualSearchBarControl(ContextualSearchPanelDelegate panel, Context context,
+                                      ViewGroup container, DynamicResourceLoader loader) {
+        mContextControl = new ContextualSearchContextControl(panel, context, container, loader);
+        mSearchTermControl = new ContextualSearchTermControl(panel, context, container, loader);
+    }
+
+    /**
+     * Removes the bottom bar views from the parent container.
+     */
+    public void destroy() {
+        mContextControl.destroy();
+        mSearchTermControl.destroy();
+    }
+
+    /**
+     * Sets the search context to display in the control.
+     * @param selection The portion of the context that represents the user's selection.
+     * @param end The portion of the context after the selection.
+     */
+    public void setSearchContext(String selection, String end) {
+        mContextControl.setSearchContext(selection, end);
+    }
+
+    /**
+     * Sets the search term to display in the control.
+     * @param searchTerm The string that represents the search term.
+     */
+    public void setSearchTerm(String searchTerm) {
+        mSearchTermControl.setSearchTerm(searchTerm);
+    }
+
+    /**
+     * @return The Id of the Search Context View.
+     */
+    public int getSearchContextViewId() {
+        return mContextControl.getViewId();
+    }
+
+    /**
+     * @return The Id of the Search Term View.
+     */
+    public int getSearchTermViewId() {
+        return mSearchTermControl.getViewId();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchContextControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchContextControl.java
new file mode 100644
index 0000000..c11331683
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchContextControl.java
@@ -0,0 +1,65 @@
+// Copyright 2015 The Chromium 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.compositor.bottombar.contextualsearch;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+
+/**
+ * Controls the Search Context View that is used as a dynamic resource.
+ */
+public class ContextualSearchContextControl extends ContextualSearchInflater {
+    /**
+     * The selected text View.
+     */
+    private TextView mSelectedText;
+
+    /**
+     * The end of the surrounding text View.
+     */
+    private TextView mEndText;
+
+    /**
+     * @param panel             The panel delegate.
+     * @param context           The Android Context used to inflate the View.
+     * @param container         The container View used to inflate the View.
+     * @param resourceLoader    The resource loader that will handle the snapshot capturing.
+     */
+    public ContextualSearchContextControl(ContextualSearchPanelDelegate panel,
+                                          Context context,
+                                          ViewGroup container,
+                                          DynamicResourceLoader resourceLoader) {
+        super(panel, R.layout.contextual_search_context_view, R.id.contextual_search_context_view,
+                context, container, resourceLoader);
+    }
+
+    /**
+     * Sets the search context to display in the control.
+     * @param selection The portion of the context that represents the user's selection.
+     * @param end The portion of the context after the selection.
+     */
+    public void setSearchContext(String selection, String end) {
+        inflate();
+
+        mSelectedText.setText(sanitizeText(selection));
+        mEndText.setText(sanitizeText(end));
+
+        invalidate();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        View view = getView();
+        mSelectedText = (TextView) view.findViewById(R.id.selected_text);
+        mEndText = (TextView) view.findViewById(R.id.surrounding_text_end);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchInflater.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchInflater.java
new file mode 100644
index 0000000..9f78de4
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchInflater.java
@@ -0,0 +1,96 @@
+// Copyright 2015 The Chromium 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.compositor.bottombar.contextualsearch;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+import org.chromium.ui.resources.dynamics.ViewResourceInflater;
+
+/**
+ * A helper class for inflating Contextual Search Views.
+ */
+abstract class ContextualSearchInflater extends ViewResourceInflater {
+
+    /**
+     * The panel delegate used to get information about the panel layout.
+     */
+    private ContextualSearchPanelDelegate mSearchPanelDelegate;
+
+    /**
+     * Object Replacement Character that is used in place of HTML objects that cannot be represented
+     * as text (e.g. images). Contextual search panel should not be displaying such characters as
+     * they get shown as [obj] character.
+     */
+    private static final String OBJ_CHARACTER = "\uFFFC";
+
+    /**
+     * @param panelDelegate     The panel delegate.
+     * @param layoutId          The XML Layout that declares the View.
+     * @param viewId            The id of the root View of the Layout.
+     * @param context           The Android Context used to inflate the View.
+     * @param container         The container View used to inflate the View.
+     * @param resourceLoader    The resource loader that will handle the snapshot capturing.
+     */
+    public ContextualSearchInflater(ContextualSearchPanelDelegate panelDelegate,
+                                    int layoutId,
+                                    int viewId,
+                                    Context context,
+                                    ViewGroup container,
+                                    DynamicResourceLoader resourceLoader) {
+        super(layoutId, viewId, context, container, resourceLoader);
+
+        mSearchPanelDelegate = panelDelegate;
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+
+        mSearchPanelDelegate = null;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        if (!mSearchPanelDelegate.isFullscreenSizePanel()) {
+            setWidth(mSearchPanelDelegate.getMaximumWidthPx());
+        }
+    }
+
+    @Override
+    protected int getWidthMeasureSpec() {
+        return View.MeasureSpec.makeMeasureSpec(
+                mSearchPanelDelegate.getMaximumWidthPx(), View.MeasureSpec.EXACTLY);
+    }
+
+    /**
+     * @param width The width of the view to be inforced.
+     */
+    private void setWidth(int width) {
+        // When the view is attached, we need to force the layout to have a specific width
+        // because the container is "full-width" (as wide as a tab). When not attached,
+        // ViewResourceInflater#layout() will properly resize the view offscreen.
+        if (shouldAttachView()) {
+            View view = getView();
+            if (view != null) {
+                view.getLayoutParams().width = width;
+                view.requestLayout();
+            }
+        }
+    }
+
+    /**
+     * Sanitizes a string to be displayed on the Contextual Search Bar.
+     * @param text The text to be sanitized.
+     * @return The sanitized text.
+     */
+    public static String sanitizeText(String text) {
+        if (text == null) return null;
+        return text.replace(OBJ_CHARACTER, " ").trim();
+    }
+
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index 66b191f..7ac8418 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.compositor.bottombar.OverlayContentProgressObserver;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
 import org.chromium.content.browser.ContentViewClient;
 import org.chromium.content.browser.ContentViewCore;
 
@@ -35,6 +36,7 @@
 
     /**
      * The reason for a change in the Contextual Search Panel's state.
+     * TODO(mdjones): Separate generic reasons from Contextual Search reasons.
      */
     public static enum StateChangeReason {
         UNKNOWN,
@@ -57,9 +59,11 @@
         CLOSE_BUTTON;
     }
 
-    // The animation duration of a URL being promoted to a tab when triggered by an
-    // intercept navigation. This is faster than the standard tab promotion animation
-    // so that it completes before the navigation.
+    /**
+     * The animation duration of a URL being promoted to a tab when triggered by an
+     * intercept navigation. This is faster than the standard tab promotion animation
+     * so that it completes before the navigation.
+     */
     private static final long INTERCEPT_NAVIGATION_PROMOTION_ANIMATION_DURATION_MS = 40;
 
     /**
@@ -107,6 +111,16 @@
      */
     private OverlayPanelContent mOverlayPanelContent;
 
+    /**
+     * Used for logging state changes.
+     */
+    private ContextualSearchPanelMetrics mPanelMetrics;
+
+    /**
+     * The object for handling global Contextual Search management duties
+     */
+    private ContextualSearchManagementDelegate mManagementDelegate;
+
     // ============================================================================================
     // Constructor
     // ============================================================================================
@@ -117,6 +131,7 @@
      */
     public ContextualSearchPanel(Context context, LayoutUpdateHost updateHost) {
         super(context, updateHost);
+        mPanelMetrics = new ContextualSearchPanelMetrics();
     }
 
     /**
@@ -124,7 +139,7 @@
      */
     public OverlayPanelContent createNewOverlayPanelContent() {
         OverlayPanelContent overlayPanelContent = new OverlayPanelContent(
-                getManagementDelegate().getOverlayContentDelegate(), new PanelProgressObserver(),
+                mManagementDelegate.getOverlayContentDelegate(), new PanelProgressObserver(),
                 mActivity);
 
         // Adds a ContentViewClient to override the default fullscreen size.
@@ -179,6 +194,61 @@
     }
 
     // ============================================================================================
+    // Contextual Search Manager Integration
+    // ============================================================================================
+
+    /**
+     * Sets the {@code ContextualSearchManagementDelegate} associated with this panel.
+     * @param delegate The {@code ContextualSearchManagementDelegate}.
+     */
+    public void setManagementDelegate(ContextualSearchManagementDelegate delegate) {
+        if (mManagementDelegate != delegate) {
+            mManagementDelegate = delegate;
+            if (delegate != null) {
+                initializeUiState();
+            }
+        }
+    }
+
+    /**
+     * @return The {@code ContextualSearchManagementDelegate} associated with this Layout.
+     */
+    public ContextualSearchManagementDelegate getManagementDelegate() {
+        return mManagementDelegate;
+    }
+
+    // ============================================================================================
+    // Logging of panel state information.
+    // ============================================================================================
+
+    @Override
+    public void setPanelState(PanelState toState, StateChangeReason reason) {
+        // Store the previous state of the panel for when super changes it. 'super' should be the
+        // first thing with significant logic that runs in this method which is why
+        // onPanelStateChanged is not called here.
+        PanelState fromState = getPanelState();
+        super.setPanelState(toState, reason);
+        mPanelMetrics.onPanelStateChanged(fromState, toState, reason);
+    }
+
+    // ============================================================================================
+    // Promo Host
+    // ============================================================================================
+
+    @Override
+    public void onPromoPreferenceClick() {
+        super.onPromoPreferenceClick();
+        setIsPromoActive(false);
+    }
+
+    @Override
+    public void onPromoButtonClick(boolean accepted) {
+        super.onPromoButtonClick(accepted);
+        mManagementDelegate.logPromoOutcome();
+        setIsPromoActive(false);
+    }
+
+    // ============================================================================================
     // Layout Integration
     // ============================================================================================
 
@@ -196,29 +266,23 @@
 
     @Override
     public void setPreferenceState(boolean enabled) {
-        if (getManagementDelegate() != null) {
-            getManagementDelegate().setPreferenceState(enabled);
+        if (mManagementDelegate != null) {
+            mManagementDelegate.setPreferenceState(enabled);
         }
     }
 
     @Override
     protected boolean isPromoAvailable() {
-        return getManagementDelegate() != null && getManagementDelegate().isPromoAvailable();
-    }
-
-    @Override
-    public void onPromoButtonClick(boolean accepted) {
-        super.onPromoButtonClick(accepted);
-        getManagementDelegate().logPromoOutcome();
-        setIsPromoActive(false);
+        return mManagementDelegate != null && mManagementDelegate.isPromoAvailable();
     }
 
     @Override
     protected void onClose(StateChangeReason reason) {
+        destroySearchBarControl();
         if (mOverlayPanelContent != null) {
             mOverlayPanelContent.destroyContentView();
         }
-        getManagementDelegate().onCloseContextualSearch(reason);
+        mManagementDelegate.onCloseContextualSearch(reason);
     }
 
     // ============================================================================================
@@ -292,8 +356,8 @@
             closePanel(StateChangeReason.BASE_PAGE_TAP, true);
         } else if (isCoordinateInsideSearchBar(x, y)) {
             if (isPeeking()) {
-                if (getManagementDelegate().isRunningInCompatibilityMode()) {
-                    getManagementDelegate().openResolvedSearchUrlInNewTab();
+                if (mManagementDelegate.isRunningInCompatibilityMode()) {
+                    mManagementDelegate.openResolvedSearchUrlInNewTab();
                 } else {
                     if (isFullscreenSizePanel()) {
                         expandPanel(StateChangeReason.SEARCH_BAR_TAP);
@@ -412,7 +476,7 @@
 
         if (mShouldPromoteToTabAfterMaximizing && getPanelState() == PanelState.MAXIMIZED) {
             mShouldPromoteToTabAfterMaximizing = false;
-            getManagementDelegate().promoteToTab();
+            mManagementDelegate.promoteToTab();
         }
     }
 
@@ -451,9 +515,48 @@
     }
 
     // ============================================================================================
+    // ContextualSearchPanelBase methods.
+    // ============================================================================================
+
+    @Override
+    public boolean isCustomTab() {
+        return mManagementDelegate.isCustomTab();
+    }
+
+    @Override
+    public int getControlContainerHeightResource() {
+        return mManagementDelegate.getControlContainerHeightResource();
+    }
+
+    // ============================================================================================
     // Panel Delegate
     // ============================================================================================
 
+    /**
+     * Sets that the Search Content View was seen.
+     */
+    @Override
+    public void setWasSearchContentViewSeen() {
+        mPanelMetrics.setWasSearchContentViewSeen();
+    }
+
+    /**
+     * Sets whether the promo is active.
+     */
+    @Override
+    public void setIsPromoActive(boolean shown) {
+        mPanelMetrics.setIsPromoActive(shown);
+    }
+
+    /**
+     * Records timing information when the search results have fully loaded.
+     * @param wasPrefetch Whether the request was prefetch-enabled.
+     */
+    @Override
+    public void onSearchResultsLoaded(boolean wasPrefetch) {
+        mPanelMetrics.onSearchResultsLoaded(wasPrefetch);
+    }
+
     @Override
     public boolean isFullscreenSizePanel() {
         // NOTE(pedrosimonetti): exposing superclass method to the interface.
@@ -543,41 +646,11 @@
     }
 
     @Override
-    public void setDidSearchInvolvePromo() {
-        // NOTE(pedrosimonetti): exposing superclass method to the interface.
-        super.setDidSearchInvolvePromo();
-    }
-
-    @Override
-    public void setWasSearchContentViewSeen() {
-        // NOTE(pedrosimonetti): exposing superclass method to the interface.
-        super.setWasSearchContentViewSeen();
-    }
-
-    @Override
-    public void setIsPromoActive(boolean shown) {
-        // NOTE(pedrosimonetti): exposing superclass method to the interface.
-        super.setIsPromoActive(shown);
-    }
-
-    @Override
     public boolean didTouchSearchContentView() {
         return mHasSearchContentViewBeenTouched;
     }
 
     @Override
-    public void onSearchResultsLoaded(boolean wasPrefetch) {
-        // NOTE(pedrosimonetti): exposing superclass method to the interface.
-        super.onSearchResultsLoaded(wasPrefetch);
-    }
-
-    @Override
-    public BottomBarTextControl getBottomBarTextControl() {
-        // NOTE(pedrosimonetti): exposing superclass method to the interface.
-        return super.getBottomBarTextControl();
-    }
-
-    @Override
     public boolean shouldAnimatePanelCloseOnPromoteToTab() {
         return mSearchPanelFeatures.shouldAnimatePanelCloseOnPromoteToTab();
     }
@@ -585,20 +658,20 @@
     @Override
     public void displaySearchTerm(String searchTerm) {
         cancelSearchTermResolutionAnimation();
-        getBottomBarTextControl().setSearchTerm(searchTerm);
-        resetBottomBarSearchTermVisibility();
+        getSearchBarControl().setSearchTerm(searchTerm);
+        resetSearchBarTermOpacity();
     }
 
     @Override
-    public void displaySearchContext(String selection, String start, String end) {
+    public void displaySearchContext(String selection, String end) {
         cancelSearchTermResolutionAnimation();
-        getBottomBarTextControl().setSearchContext(selection, start, end);
-        resetBottomBarSearchContextVisibility();
+        getSearchBarControl().setSearchContext(selection, end);
+        resetSearchBarContextOpacity();
     }
 
     @Override
     public void onSearchTermResolutionResponse(String searchTerm) {
-        getBottomBarTextControl().setSearchTerm(searchTerm);
+        getSearchBarControl().setSearchTerm(searchTerm);
         animateSearchTermResolution();
     }
 
@@ -618,6 +691,11 @@
     }
 
     @Override
+    public boolean didLoadAnyUrl() {
+        return mOverlayPanelContent != null && mOverlayPanelContent.didLoadAnyUrl();
+    }
+
+    @Override
     public void updateTopControlState() {
         if (mOverlayPanelContent == null) return;
 
@@ -636,10 +714,110 @@
     }
 
     @Override
-    public boolean didLoadAnyUrl() {
-        return mOverlayPanelContent != null && mOverlayPanelContent.didLoadAnyUrl();
+    public void setDidSearchInvolvePromo() {
+        mPanelMetrics.setDidSearchInvolvePromo();
     }
 
+    // ============================================================================================
+    // ContextualSearchBarControl
+    // ============================================================================================
+
+    private ContextualSearchBarControl mContextualSearchBarControl;
+    private float mSearchBarContextOpacity = 1.f;
+    private float mSearchBarTermOpacity = 1.f;
+
+    /**
+     * @return The opacity of the SearchBar's search context.
+     */
+    public float getSearchBarContextOpacity() {
+        return mSearchBarContextOpacity;
+    }
+
+    /**
+     * @return The opacity of the SearchBar's search term.
+     */
+    public float getSearchBarTermOpacity() {
+        return mSearchBarTermOpacity;
+    }
+
+    /**
+     * @return The Id of the Search Context View.
+     */
+    public int getSearchContextViewId() {
+        return getSearchBarControl().getSearchContextViewId();
+    }
+
+    /**
+     * @return The Id of the Search Term View.
+     */
+    public int getSearchTermViewId() {
+        return getSearchBarControl().getSearchTermViewId();
+    }
+
+    /**
+     * Creates the ContextualSearchBarControl, if needed. The Views are set to INVISIBLE, because
+     * they won't actually be displayed on the screen (their snapshots will be displayed instead).
+     */
+    protected ContextualSearchBarControl getSearchBarControl() {
+        assert mContainerView != null;
+        assert mResourceLoader != null;
+
+        if (mContextualSearchBarControl == null) {
+            mContextualSearchBarControl =
+                    new ContextualSearchBarControl(this, mContext, mContainerView, mResourceLoader);
+        }
+
+        assert mContextualSearchBarControl != null;
+        return mContextualSearchBarControl;
+    }
+
+    /**
+     * Destroys the ContextualSearchBarControl.
+     */
+    protected void destroySearchBarControl() {
+        if (mContextualSearchBarControl != null) {
+            mContextualSearchBarControl.destroy();
+            mContextualSearchBarControl = null;
+        }
+    }
+
+    @Override
+    protected void updateSearchBarTextOpacity(float percentage) {
+        // The search context will start fading out before the search term starts fading in.
+        // They will both be partially visible for overlapPercentage of the animation duration.
+        float overlapPercentage = .75f;
+        float fadingOutPercentage = Math.max(1 - (percentage / overlapPercentage), 0.f);
+        float fadingInPercentage =
+                Math.max(percentage - (1 - overlapPercentage), 0.f) / overlapPercentage;
+
+        mSearchBarContextOpacity = fadingOutPercentage;
+        mSearchBarTermOpacity = fadingInPercentage;
+    }
+
+    /**
+     * Resets the SearchBar text opacity when a new search context is set. The search
+     * context is made visible and the search term invisible.
+     */
+    private void resetSearchBarContextOpacity() {
+        mSearchBarContextOpacity = 1.f;
+        mSearchBarTermOpacity = 0.f;
+    }
+
+    /**
+     * Resets the SearchBar text opacity when a new search term is set. The search
+     * term is made visible and the search context invisible.
+     */
+    private void resetSearchBarTermOpacity() {
+        mSearchBarContextOpacity = 0.f;
+        mSearchBarTermOpacity = 1.f;
+    }
+
+    // ============================================================================================
+    // Panel Content
+    // ============================================================================================
+
+    // TODO(pedrosimonetti): move content code to its own section.
+
     @Override
     public ContentViewCore getContentViewCore() {
         // Expose OverlayPanelContent method.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
index c1ef52d9..e7bc024 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java
@@ -97,6 +97,18 @@
     }
 
     // ============================================================================================
+    // Custom Animations
+    // ============================================================================================
+
+    /**
+     * Updates the UI state for the SearchBar text. The search context view will fade out
+     * while the search term fades in.
+     *
+     * @param percentage The visibility percentage of the search term view.
+     */
+    protected abstract void updateSearchBarTextOpacity(float percentage);
+
+    // ============================================================================================
     // Animation API
     // ============================================================================================
 
@@ -366,7 +378,7 @@
         } else if (prop == Property.PROMO_VISIBILITY) {
             setPromoVisibilityForOptInAnimation(value);
         } else if (prop == Property.BOTTOM_BAR_TEXT_VISIBILITY) {
-            updateBottomBarTextVisibility(value);
+            updateSearchBarTextOpacity(value);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java
index c9695ca4..3af21450 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelBase.java
@@ -16,18 +16,20 @@
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchOptOutPromo.ContextualSearchPromoHost;
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.PanelState;
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.StateChangeReason;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.privacy.ContextualSearchPreferenceFragment;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Base abstract class for the Contextual Search Panel.
  */
-abstract class ContextualSearchPanelBase extends ContextualSearchPanelStateHandler
-        implements ContextualSearchPromoHost {
+abstract class ContextualSearchPanelBase implements ContextualSearchPromoHost {
     /**
      * The side padding of Search Bar icons in dps.
      */
@@ -189,18 +191,30 @@
     /**
      * The current context.
      */
-    private final Context mContext;
-
-    /**
-     * The object for handling global Contextual Search management duties
-     */
-    private ContextualSearchManagementDelegate mManagementDelegate;
+    protected final Context mContext;
 
     /**
      * The {@link ContextualSearchPanelFeatures} for this panel.
      */
     protected ContextualSearchPanelFeatures mSearchPanelFeatures;
 
+    /**
+     * The current state of the Contextual Search Panel.
+     */
+    private PanelState mPanelState = PanelState.UNDEFINED;
+
+    /**
+     * Valid previous states for the Panel.
+     */
+    protected static final Map<PanelState, PanelState> PREVIOUS_STATES;
+    static {
+        Map<PanelState, PanelState> states = new HashMap<PanelState, PanelState>();
+        // Pairs are of the form <Current, Previous>.
+        states.put(PanelState.PEEKED, PanelState.CLOSED);
+        states.put(PanelState.EXPANDED, PanelState.PEEKED);
+        states.put(PanelState.MAXIMIZED, PanelState.EXPANDED);
+        PREVIOUS_STATES = Collections.unmodifiableMap(states);
+    }
 
     // ============================================================================================
     // Constructor
@@ -242,8 +256,7 @@
     protected abstract void animatePromoAcceptance();
 
     /**
-     * Animates the BottomBar text visibility. The BottomBar context text fades out while the
-     * BottomBar search text fades in.
+     * Animates the search term resolution.
      */
     protected abstract void animateSearchTermResolution();
 
@@ -259,28 +272,22 @@
     protected abstract void onClose(StateChangeReason reason);
 
     // ============================================================================================
-    // Contextual Search Manager Integration
+    // General methods from Contextual Search Manager
     // ============================================================================================
 
     /**
-     * Sets the {@code ContextualSearchManagementDelegate} associated with this panel.
-     * @param delegate The {@code ContextualSearchManagementDelegate}.
+     * TODO(mdjones): This method should be removed from this class.
+     * @return True if the tab hosting the panel is a custom tab.
      */
-    public void setManagementDelegate(ContextualSearchManagementDelegate delegate) {
-        if (mManagementDelegate != delegate) {
-            mManagementDelegate = delegate;
-            if (delegate != null) {
-                initializeUiState();
-            }
-        }
-    }
+    public abstract boolean isCustomTab();
 
     /**
-     * @return The {@code ContextualSearchManagementDelegate} associated with this Layout.
+     * TODO(mdjones): This method should be removed from this class.
+     * @return The resource id that contains how large the top controls are.
      */
-    public ContextualSearchManagementDelegate getManagementDelegate() {
-        return mManagementDelegate;
-    }
+    public abstract int getControlContainerHeightResource();
+
+
 
     // ============================================================================================
     // Layout Integration
@@ -539,8 +546,6 @@
     // --------------------------------------------------------------------------------------------
     private float mSearchBarMarginSide;
     private float mSearchBarHeight;
-    private float mBottomBarSearchContextOpacity = 1.f;
-    private float mBottomBarSearchTermOpacity = 1.f;
     private boolean mIsSearchBarBorderVisible;
     private float mSearchBarBorderY;
     private float mSearchBarBorderHeight;
@@ -568,20 +573,6 @@
     }
 
     /**
-     * @return The opacity of the BottomBar search context view.
-     */
-    public float getBottomBarSearchContextOpacity() {
-        return mBottomBarSearchContextOpacity;
-    }
-
-    /**
-     * @return The opacity of the BottomBar search term view.
-     */
-    public float getBottomBarSearchTermOpacity() {
-        return mBottomBarSearchTermOpacity;
-    }
-
-    /**
      * @return Whether the Search Bar border is visible.
      */
     public boolean isSearchBarBorderVisible() {
@@ -799,6 +790,53 @@
     }
 
     // ============================================================================================
+    // State Handler
+    // ============================================================================================
+
+    /**
+     * @return The panel's state.
+     */
+    public PanelState getPanelState() {
+        return mPanelState;
+    }
+
+    /**
+     * @return The {@code PanelState} that is before the |state| in the order of states.
+     */
+    public PanelState getPreviousPanelState(PanelState state) {
+        PanelState prevState = PREVIOUS_STATES.get(state);
+        return prevState != null ? prevState : PanelState.UNDEFINED;
+    }
+
+    /**
+     * Sets the panel's state.
+     * @param state The panel state to transition to.
+     * @param reason The reason for a change in the panel's state.
+     */
+    public void setPanelState(PanelState state, StateChangeReason reason) {
+        mPanelState = state;
+
+        if (state == PanelState.CLOSED) {
+            mIsShowing = false;
+            destroyPromoView();
+            onClose(reason);
+        } else if (state == PanelState.EXPANDED && isFullscreenSizePanel()
+                || (state == PanelState.MAXIMIZED && !isFullscreenSizePanel())) {
+            showPromoViewAtYPosition(getPromoYPx());
+        }
+    }
+
+    /**
+     * Determine if a specific {@code PanelState} is a valid state in the current environment.
+     * @param state The state being evaluated.
+     * @return whether the state is valid.
+     */
+    public boolean isValidState(PanelState state) {
+        // MAXIMIZED is not the previous state of anything, but it's a valid state.
+        return PREVIOUS_STATES.values().contains(state) || state == PanelState.MAXIMIZED;
+    }
+
+    // ============================================================================================
     // Helpers
     // ============================================================================================
 
@@ -806,14 +844,14 @@
      * Initializes the UI state.
      */
     protected void initializeUiState() {
-        mSearchPanelFeatures = new ContextualSearchPanelFeatures(mManagementDelegate.isCustomTab());
+        mSearchPanelFeatures = new ContextualSearchPanelFeatures(isCustomTab());
         mIsShowing = false;
 
         // Static values.
         mPxToDp = 1.f / mContext.getResources().getDisplayMetrics().density;
 
         mToolbarHeight = mContext.getResources().getDimension(
-                mManagementDelegate.getControlContainerHeightResource()) * mPxToDp;
+                getControlContainerHeightResource()) * mPxToDp;
 
         mSearchBarPaddingTop = PANEL_SHADOW_HEIGHT_DP;
 
@@ -910,21 +948,6 @@
         setPanelHeight(clampedHeight);
     }
 
-    @Override
-    protected void setPanelState(PanelState state, StateChangeReason reason) {
-        super.setPanelState(state, reason);
-
-        if (state == PanelState.CLOSED) {
-            mIsShowing = false;
-            destroyPromoView();
-            destroyBottomBarTextControl();
-            onClose(reason);
-        } else if (state == PanelState.EXPANDED && isFullscreenSizePanel()
-                || (state == PanelState.MAXIMIZED && !isFullscreenSizePanel())) {
-            showPromoViewAtYPosition(getPromoYPx());
-        }
-    }
-
     /**
      * Sets the panel height.
      *
@@ -1309,8 +1332,8 @@
     // Resource Loader
     // ============================================================================================
 
-    private ViewGroup mContainerView;
-    private DynamicResourceLoader mResourceLoader;
+    protected ViewGroup mContainerView;
+    protected DynamicResourceLoader mResourceLoader;
 
     /**
      * @param resourceLoader The {@link DynamicResourceLoader} to register and unregister the view.
@@ -1318,13 +1341,6 @@
     public void setDynamicResourceLoader(DynamicResourceLoader resourceLoader) {
         mResourceLoader = resourceLoader;
 
-        if (mBottomBarTextControl != null) {
-            mResourceLoader.registerResource(R.id.contextual_search_context_view,
-                    mBottomBarTextControl.getSearchContextResourceAdapter());
-            mResourceLoader.registerResource(R.id.contextual_search_term_view,
-                    mBottomBarTextControl.getSearchTermResourceAdapter());
-        }
-
         if (mPromoView != null) {
             mResourceLoader.registerResource(R.id.contextual_search_opt_out_promo,
                     mPromoView.getResourceAdapter());
@@ -1341,86 +1357,6 @@
     }
 
     // ============================================================================================
-    // BottomBarTextControl
-    // ============================================================================================
-
-    private BottomBarTextControl mBottomBarTextControl;
-
-    /**
-     * Creates the BottomBarTextControl, if needed. The Views are set to INVISIBLE, because they
-     * won't actually be displayed on the screen (their snapshots will be displayed instead).
-     */
-    protected BottomBarTextControl getBottomBarTextControl() {
-        assert mContainerView != null;
-
-        if (mBottomBarTextControl == null) {
-            mBottomBarTextControl = new BottomBarTextControl(mContext, mContainerView);
-
-            // Adjust size for small Panel.
-            if (!isFullscreenSizePanel()) {
-                mBottomBarTextControl.setWidth(getMaximumWidthPx());
-            }
-
-            if (mResourceLoader != null) {
-                mResourceLoader.registerResource(R.id.contextual_search_context_view,
-                        mBottomBarTextControl.getSearchContextResourceAdapter());
-                mResourceLoader.registerResource(R.id.contextual_search_term_view,
-                        mBottomBarTextControl.getSearchTermResourceAdapter());
-            }
-        }
-
-        assert mBottomBarTextControl != null;
-        return mBottomBarTextControl;
-    }
-
-    protected void destroyBottomBarTextControl() {
-        if (mBottomBarTextControl != null) {
-            mBottomBarTextControl.removeFromContainer();
-            mBottomBarTextControl = null;
-            if (mResourceLoader != null) {
-                mResourceLoader.unregisterResource(R.id.contextual_search_context_view);
-                mResourceLoader.unregisterResource(R.id.contextual_search_term_view);
-            }
-        }
-    }
-
-    /**
-     * Updates the UI state for the BottomBar text. The BottomBar search context view will fade out
-     * while the search term fades in.
-     *
-     * @param percentage The visibility percentage of the BottomBar search term view.
-     */
-    protected void updateBottomBarTextVisibility(float percentage) {
-        // The search context will start fading out before the search term starts fading in.
-        // They will both be partially visible for overlapPercentage of the animation duration.
-        float overlapPercentage = .75f;
-        float fadingOutPercentage = Math.max(1 - (percentage / overlapPercentage), 0.f);
-        float fadingInPercentage =
-                Math.max(percentage - (1 - overlapPercentage), 0.f) / overlapPercentage;
-
-        mBottomBarSearchContextOpacity = fadingOutPercentage;
-        mBottomBarSearchTermOpacity = fadingInPercentage;
-    }
-
-    /**
-     * Resets the BottomBar text visibility when a new search context is set. The BottomBar search
-     * context is made visible and the BottomBar search text invisible.
-     */
-    protected void resetBottomBarSearchContextVisibility() {
-        mBottomBarSearchContextOpacity = 1.f;
-        mBottomBarSearchTermOpacity = 0.f;
-    }
-
-    /**
-     * Resets the BottomBar text visibility when a new search term is set. The BottomBar search
-     * term is made visible and the BottomBar search context invisible.
-     */
-    protected void resetBottomBarSearchTermVisibility() {
-        mBottomBarSearchContextOpacity = 0.f;
-        mBottomBarSearchTermOpacity = 1.f;
-    }
-
-    // ============================================================================================
     // Promo Host
     // ============================================================================================
 
@@ -1429,7 +1365,6 @@
         new Handler().post(new Runnable() {
             @Override
             public void run() {
-                setIsPromoActive(false);
                 PreferencesLauncher.launchSettingsPage(mContext,
                         ContextualSearchPreferenceFragment.class.getName());
             }
@@ -1473,6 +1408,7 @@
         assert mContainerView != null;
 
         if (mPromoView == null) {
+            // TODO(pedrosimonetti): Refactor promo code to use ViewResourceInflater.
             LayoutInflater.from(mContext).inflate(
                     R.layout.contextual_search_opt_out_promo, mContainerView);
             mPromoView = (ContextualSearchOptOutPromo)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelDelegate.java
index 59cddb3..5966c82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelDelegate.java
@@ -130,22 +130,21 @@
     void removeLastHistoryEntry(String historyUrl, long urlTimeMs);
 
     /**
-     * Shows the search term in the BottomBar. This should be called when the search term is set
-     * without resolving a search context.
+     * Shows the search term in the SearchBar. This should be called when the search term is set
+     * without search term resolution.
      * @param searchTerm The string that represents the search term.
      */
     void displaySearchTerm(String searchTerm);
 
     /**
-     * Shows the search context in the BottomBar.
+     * Shows the search context in the SearchBar.
      * @param selection The portion of the context that represents the user's selection.
-     * @param start The portion of the context from its start to the selection.
-     * @param end The portion of the context the selection to its end.
+     * @param end The portion of the context from the selection to its end.
      */
-    void displaySearchContext(String selection, String start, String end);
+    void displaySearchContext(String selection, String end);
 
     /**
-     * Handles showing the resolved search term in the BottomBarTextControl.
+     * Handles showing the resolved search term in the SearchBar.
      * @param searchTerm The string that represents the search term.
      */
     void onSearchTermResolutionResponse(String searchTerm);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
similarity index 72%
rename from chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java
rename to chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
index 7cf9f2b..601b219d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
@@ -8,29 +8,12 @@
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.StateChangeReason;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
- * Holds the state of the Contextual Search Panel.
+ * This class is responsible for all the logging related to Contextual Search.
  */
-abstract class ContextualSearchPanelStateHandler {
+public class ContextualSearchPanelMetrics {
 
-    // Valid previous states for the Panel.
-    private static final Map<PanelState, PanelState> PREVIOUS_STATES;
-    static {
-        Map<PanelState, PanelState> states = new HashMap<PanelState, PanelState>();
-        // Pairs are of the form <Current, Previous>.
-        states.put(PanelState.PEEKED, PanelState.CLOSED);
-        states.put(PanelState.EXPANDED, PanelState.PEEKED);
-        states.put(PanelState.MAXIMIZED, PanelState.EXPANDED);
-        PREVIOUS_STATES = Collections.unmodifiableMap(states);
-    }
-
-    // The current state of the Contextual Search Panel.
-    private PanelState mPanelState = PanelState.UNDEFINED;
+    // Flags for logging.
     private boolean mDidSearchInvolvePromo;
     private boolean mWasSearchContentViewSeen;
     private boolean mIsPromoActive;
@@ -45,37 +28,19 @@
     private long mSearchStartTimeNs;
     private long mSearchViewStartTimeNs;
 
-    // --------------------------------------------------------------------------------------------
-    // Contextual Search Panel states
-    // --------------------------------------------------------------------------------------------
-
     /**
-     * @return The panel's state.
+     * Log information when the panel's state has changed.
+     * @param fromState The state the panel is transitioning from.
+     * @param toState The state that the panel is transitioning to.
+     * @param reason The reason for the state change.
      */
-    PanelState getPanelState() {
-        return mPanelState;
-    }
-
-    /**
-     * @return The {@code PanelState} that is before the |state| in the order of states.
-     */
-    PanelState getPreviousPanelState(PanelState state) {
-        PanelState prevState = PREVIOUS_STATES.get(state);
-        return prevState != null ? prevState : PanelState.UNDEFINED;
-    }
-
-    /**
-     * Sets the panel's state.
-     * @param toState The panel state to transition to.
-     * @param reason The reason for a change in the panel's state.
-     */
-    protected void setPanelState(PanelState toState, StateChangeReason reason) {
+    public void onPanelStateChanged(PanelState fromState, PanelState toState,
+            StateChangeReason reason) {
         // Note: the logging within this function includes the promo, unless specifically
         // excluded.
-        PanelState fromState = mPanelState;
         boolean isStartingSearch = isStartingNewContextualSearch(toState, reason);
-        boolean isEndingSearch = isEndingContextualSearch(toState, isStartingSearch);
-        boolean isChained = isStartingSearch && isOngoingContextualSearch();
+        boolean isEndingSearch = isEndingContextualSearch(fromState, toState, isStartingSearch);
+        boolean isChained = isStartingSearch && isOngoingContextualSearch(fromState);
         boolean isSameState = fromState == toState;
         boolean isFirstExitFromPeeking = fromState == PanelState.PEEKED && !mHasExitedPeeking
                 && (!isSameState || isStartingSearch);
@@ -140,8 +105,6 @@
             mHasExitedMaximized = true;
         }
 
-        mPanelState = toState;
-
         if (toState == PanelState.EXPANDED) {
             mHasExpanded = true;
         } else if (toState == PanelState.MAXIMIZED) {
@@ -170,44 +133,30 @@
     }
 
     /**
-     * Determine if a specific {@code PanelState} is a valid state in the current environment.
-     * @param state The state being evaluated.
-     * @return whether the state is valid.
-     */
-    boolean isValidState(PanelState state) {
-        ArrayList<PanelState> validStates =
-                new ArrayList<PanelState>(PREVIOUS_STATES.values());
-        // MAXIMIZED is not the previous state of anything, but it's a valid state.
-        validStates.add(PanelState.MAXIMIZED);
-
-        return validStates.contains(state);
-    }
-
-    /**
      * Sets that the contextual search involved the promo.
      */
-    void setDidSearchInvolvePromo() {
+    public void setDidSearchInvolvePromo() {
         mDidSearchInvolvePromo = true;
     }
 
     /**
      * Sets that the Search Content View was seen.
      */
-    void setWasSearchContentViewSeen() {
+    public void setWasSearchContentViewSeen() {
         mWasSearchContentViewSeen = true;
     }
 
     /**
      * Sets whether the promo is active.
      */
-    void setIsPromoActive(boolean shown) {
+    public void setIsPromoActive(boolean shown) {
         mIsPromoActive = shown;
     }
 
     /**
      * Gets whether the promo is active.
      */
-    boolean getIsPromoActive() {
+    private boolean getIsPromoActive() {
         return mIsPromoActive;
     }
 
@@ -215,7 +164,7 @@
      * Records timing information when the search results have fully loaded.
      * @param wasPrefetch Whether the request was prefetch-enabled.
      */
-    void onSearchResultsLoaded(boolean wasPrefetch) {
+    public void onSearchResultsLoaded(boolean wasPrefetch) {
         if (mHasExpanded || mHasMaximized) {
             // Already opened, log how long it took.
             assert mSearchViewStartTimeNs != 0;
@@ -240,10 +189,6 @@
         }
     }
 
-    // --------------------------------------------------------------------------------------------
-    // Helpers
-    // --------------------------------------------------------------------------------------------
-
     /**
      * Determine whether a new contextual search is starting.
      * @param toState The contextual search state that will be transitioned to.
@@ -258,19 +203,23 @@
 
     /**
      * Determine whether a contextual search is ending.
+     * @param fromState The contextual search state that will be transitioned from.
      * @param toState The contextual search state that will be transitioned to.
      * @param isStartingSearch Whether a new contextual search is starting.
      * @return Whether a contextual search is ending.
      */
-    private boolean isEndingContextualSearch(PanelState toState, boolean isStartingSearch) {
-        return isOngoingContextualSearch() && (toState == PanelState.CLOSED || isStartingSearch);
+    private boolean isEndingContextualSearch(PanelState fromState, PanelState toState,
+            boolean isStartingSearch) {
+        return isOngoingContextualSearch(fromState)
+                && (toState == PanelState.CLOSED || isStartingSearch);
     }
 
     /**
+     * @param fromState The state the panel is transitioning from.
      * @return Whether there is an ongoing contextual search.
      */
-    private boolean isOngoingContextualSearch() {
-        return mPanelState != PanelState.UNDEFINED && mPanelState != PanelState.CLOSED;
+    private boolean isOngoingContextualSearch(PanelState fromState) {
+        return fromState != PanelState.UNDEFINED && fromState != PanelState.CLOSED;
     }
 
     /**
@@ -282,3 +231,4 @@
         ContextualSearchUma.logSearchPanelLoadDuration(wasPrefetch, durationMs);
     }
 }
+
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchTermControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchTermControl.java
new file mode 100644
index 0000000..27e0813
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchTermControl.java
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium 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.compositor.bottombar.contextualsearch;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+
+/**
+ * Controls the Search Term View that is used as a dynamic resource.
+ */
+public class ContextualSearchTermControl extends ContextualSearchInflater {
+    /**
+     * The search term View.
+     */
+    private TextView mSearchTerm;
+
+    /**
+     * @param panel             The panel delegate.
+     * @param context           The Android Context used to inflate the View.
+     * @param container         The container View used to inflate the View.
+     * @param resourceLoader    The resource loader that will handle the snapshot capturing.
+     */
+    public ContextualSearchTermControl(ContextualSearchPanelDelegate panel,
+                                          Context context,
+                                          ViewGroup container,
+                                          DynamicResourceLoader resourceLoader) {
+        super(panel, R.layout.contextual_search_term_view, R.id.contextual_search_term_view,
+                context, container, resourceLoader);
+    }
+
+    /**
+     * Sets the search term to display in the control.
+     * @param searchTerm The string that represents the search term.
+     */
+    public void setSearchTerm(String searchTerm) {
+        inflate();
+
+        mSearchTerm.setText(sanitizeText(searchTerm));
+
+        invalidate();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        View view = getView();
+        mSearchTerm = (TextView) view.findViewById(R.id.contextual_search_term);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
index 1b216d3..c071d90 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -36,6 +36,9 @@
      * @param resourceManager
      */
     public void update(@Nullable ContentViewCore contentViewCore, ResourceManager resourceManager) {
+        int searchContextViewId = mSearchPanel.getSearchContextViewId();
+        int searchTermViewId = mSearchPanel.getSearchTermViewId();
+
         boolean searchPromoVisible = mSearchPanel.getPromoVisible();
         float searchPromoHeightPx = mSearchPanel.getPromoHeightPx();
         float searchPromoOpacity = mSearchPanel.getPromoOpacity();
@@ -47,8 +50,8 @@
 
         float searchBarMarginSide = mSearchPanel.getSearchBarMarginSide();
         float searchBarHeight = mSearchPanel.getSearchBarHeight();
-        float searchContextOpacity = mSearchPanel.getBottomBarSearchContextOpacity();
-        float searchTermOpacity = mSearchPanel.getBottomBarSearchTermOpacity();
+        float searchContextOpacity = mSearchPanel.getSearchBarContextOpacity();
+        float searchTermOpacity = mSearchPanel.getSearchBarTermOpacity();
 
         boolean searchBarBorderVisible = mSearchPanel.isSearchBarBorderVisible();
         float searchBarBorderY = mSearchPanel.getSearchBarBorderY();
@@ -70,8 +73,8 @@
 
         nativeUpdateContextualSearchLayer(mNativePtr,
                 R.drawable.contextual_search_bar_background,
-                R.id.contextual_search_context_view,
-                R.id.contextual_search_term_view,
+                searchContextViewId,
+                searchTermViewId,
                 R.drawable.contextual_search_bar_shadow,
                 R.drawable.google_icon,
                 R.drawable.breadcrumb_arrow,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index f0bc5d9..80fb1011 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -643,14 +643,13 @@
 
     /**
      * Called when surrounding text is available.
-     * @param beforeText to be shown before the selected word.
      * @param afterText to be shown after the selected word.
      */
     @CalledByNative
-    private void onSurroundingTextAvailable(final String beforeText, final String afterText) {
+    private void onSurroundingTextAvailable(final String afterText) {
         if (mSearchPanelDelegate.isShowing()) {
             mSearchPanelDelegate.displaySearchContext(
-                    mSelectionController.getSelectedText(), beforeText, afterText);
+                    mSelectionController.getSelectedText(), afterText);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
new file mode 100644
index 0000000..c44fcdad
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -0,0 +1,305 @@
+// Copyright 2015 The Chromium 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.customtabs;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.support.customtabs.ICustomTabsCallback;
+import android.text.TextUtils;
+import android.util.SparseBooleanArray;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.base.annotations.SuppressFBWarnings;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.content_public.common.Referrer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/** Manages the clients' state for Custom Tabs. This class is threadsafe. */
+class ClientManager {
+    // Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only.
+    private static final int NO_PREDICTION = 0;
+    private static final int GOOD_PREDICTION = 1;
+    private static final int BAD_PREDICTION = 2;
+    private static final int PREDICTION_STATUS_COUNT = 3;
+    // Values for the "CustomTabs.CalledWarmup" UMA histogram. Append-only.
+    @VisibleForTesting static final int NO_SESSION_NO_WARMUP = 0;
+    @VisibleForTesting static final int NO_SESSION_WARMUP = 1;
+    @VisibleForTesting static final int SESSION_NO_WARMUP_ALREADY_CALLED = 2;
+    @VisibleForTesting static final int SESSION_NO_WARMUP_NOT_CALLED = 3;
+    @VisibleForTesting static final int SESSION_WARMUP = 4;
+    @VisibleForTesting static final int SESSION_WARMUP_COUNT = 5;
+
+    /** Per-session values. */
+    private static class SessionParams {
+        public final int uid;
+        public final Referrer referrer;
+        public final ICustomTabsCallback callback;
+        public final IBinder.DeathRecipient deathRecipient;
+        private ServiceConnection mKeepAliveConnection = null;
+        private String mPredictedUrl = null;
+        private long mLastMayLaunchUrlTimestamp = 0;
+
+        public SessionParams(Context context, int uid, ICustomTabsCallback callback,
+                IBinder.DeathRecipient deathRecipient) {
+            this.uid = uid;
+            referrer = constructReferrer(context, uid);
+            this.callback = callback;
+            this.deathRecipient = deathRecipient;
+        }
+
+        private static Referrer constructReferrer(Context context, int uid) {
+            PackageManager packageManager = context.getPackageManager();
+            String[] packageList = packageManager.getPackagesForUid(uid);
+            if (packageList.length != 1 || TextUtils.isEmpty(packageList[0])) return null;
+            return IntentHandler.constructValidReferrerForAuthority(packageList[0]);
+        }
+
+        public ServiceConnection getKeepAliveConnection() {
+            return mKeepAliveConnection;
+        }
+
+        public void setKeepAliveConnection(ServiceConnection serviceConnection) {
+            mKeepAliveConnection = serviceConnection;
+        }
+
+        public void setPredictionMetrics(String predictedUrl, long lastMayLaunchUrlTimestamp) {
+            mPredictedUrl = predictedUrl;
+            mLastMayLaunchUrlTimestamp = lastMayLaunchUrlTimestamp;
+        }
+
+        public String getPredictedUrl() {
+            return mPredictedUrl;
+        }
+
+        public long getLastMayLaunchUrlTimestamp() {
+            return mLastMayLaunchUrlTimestamp;
+        }
+    }
+
+    /** To be called when a client gets disconnected. */
+    public interface DisconnectCallback { public void run(IBinder session); }
+
+    private final Context mContext;
+    private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>();
+    private final SparseBooleanArray mUidHasCalledWarmup = new SparseBooleanArray();
+    private boolean mWarmupHasBeenCalled = false;
+
+    public ClientManager(Context context) {
+        mContext = context.getApplicationContext();
+        RequestThrottler.purgeOldEntries(mContext);
+    }
+
+    /** Creates a new session.
+     *
+     * @param cb Callback provided by the client.
+     * @param uid Client UID, as returned by Binder.getCallingUid(),
+     * @param onDisconnect To be called on the UI thread when a client gets disconnected.
+     * @return true for success.
+     */
+    public boolean newSession(
+            ICustomTabsCallback cb, int uid, final DisconnectCallback onDisconnect) {
+        if (cb == null) return false;
+        final IBinder session = cb.asBinder();
+        IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
+            @Override
+            public void binderDied() {
+                ThreadUtils.postOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        cleanupSession(session);
+                        onDisconnect.run(session);
+                    }
+                });
+            }
+        };
+        SessionParams params = new SessionParams(mContext, uid, cb, deathRecipient);
+        synchronized (this) {
+            if (mSessionParams.containsKey(session)) return false;
+            try {
+                session.linkToDeath(deathRecipient, 0);
+            } catch (RemoteException e) {
+                // The return code doesn't matter, because this executes when
+                // the caller has died.
+                return false;
+            }
+            mSessionParams.put(session, params);
+        }
+        return true;
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void recordUidHasCalledWarmup(int uid) {
+        mWarmupHasBeenCalled = true;
+        mUidHasCalledWarmup.put(uid, true);
+    }
+
+    /** Updates the client behavior stats and returns whether speculation is allowed.
+     *
+     * @param session Client session.
+     * @param uid As returned by Binder.getCallingUid().
+     * @param url Predicted URL.
+     * @return true if speculation is allowed.
+     */
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized boolean updateStatsAndReturnWhetherAllowed(
+            IBinder session, int uid, String url) {
+        SessionParams params = mSessionParams.get(session);
+        if (params == null || params.uid != uid) return false;
+        params.setPredictionMetrics(url, SystemClock.elapsedRealtime());
+        RequestThrottler throttler = RequestThrottler.getForUid(mContext, uid);
+        return throttler.updateStatsAndReturnWhetherAllowed();
+    }
+
+    @VisibleForTesting
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    synchronized int getWarmupState(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        boolean hasValidSession = params != null;
+        boolean hasUidCalledWarmup = hasValidSession && mUidHasCalledWarmup.get(params.uid);
+        int result = mWarmupHasBeenCalled ? NO_SESSION_WARMUP : NO_SESSION_NO_WARMUP;
+        if (hasValidSession) {
+            if (hasUidCalledWarmup) {
+                result = SESSION_WARMUP;
+            } else {
+                result = mWarmupHasBeenCalled ? SESSION_NO_WARMUP_ALREADY_CALLED
+                                              : SESSION_NO_WARMUP_NOT_CALLED;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Registers that a client has launched a URL inside a Custom Tab.
+     */
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void registerLaunch(IBinder session, String url) {
+        int outcome = NO_PREDICTION;
+        long elapsedTimeMs = -1;
+        SessionParams params = mSessionParams.get(session);
+        if (params != null) {
+            String predictedUrl = params.getPredictedUrl();
+            outcome = predictedUrl == null ? NO_PREDICTION : predictedUrl.equals(url)
+                            ? GOOD_PREDICTION
+                            : BAD_PREDICTION;
+            long now = SystemClock.elapsedRealtime();
+            elapsedTimeMs = now - params.getLastMayLaunchUrlTimestamp();
+            params.setPredictionMetrics(null, 0);
+            if (outcome == GOOD_PREDICTION) {
+                RequestThrottler.getForUid(mContext, params.uid).registerSuccess(url);
+            }
+        }
+        RecordHistogram.recordEnumeratedHistogram(
+                "CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT);
+        if (outcome == GOOD_PREDICTION) {
+            RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToLaunch",
+                    elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MILLISECONDS, 100);
+        }
+        RecordHistogram.recordEnumeratedHistogram(
+                "CustomTabs.WarmupStateOnLaunch", getWarmupState(session), SESSION_WARMUP_COUNT);
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized Referrer getReferrerForSession(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        return params != null ? params.referrer : null;
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized ICustomTabsCallback getCallbackForSession(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        return params != null ? params.callback : null;
+    }
+
+    /** Tries to bind to a client to keep it alive, and returns true for success. */
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized boolean keepAliveForSession(IBinder session, Intent intent) {
+        // When an application is bound to a service, its priority is raised to
+        // be at least equal to the application's one. This binds to a dummy
+        // service (no calls to this service are made).
+        if (intent == null || intent.getComponent() == null) return false;
+        SessionParams params = mSessionParams.get(session);
+        if (params == null) return false;
+
+        String packageName = intent.getComponent().getPackageName();
+        PackageManager pm = mContext.getApplicationContext().getPackageManager();
+        // Only binds to the application associated to this session.
+        if (!Arrays.asList(pm.getPackagesForUid(params.uid)).contains(packageName)) return false;
+        Intent serviceIntent = new Intent().setComponent(intent.getComponent());
+        // This ServiceConnection doesn't handle disconnects. This is on
+        // purpose, as it occurs when the remote process has died. Since the
+        // only use of this connection is to keep the application alive,
+        // re-connecting would just re-create the process, but the application
+        // state has been lost at that point, the callbacks invalidated, etc.
+        ServiceConnection connection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {}
+            @Override
+            public void onServiceDisconnected(ComponentName name) {}
+        };
+        boolean ok;
+        try {
+            ok = mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
+        } catch (SecurityException e) {
+            return false;
+        }
+        if (ok) params.setKeepAliveConnection(connection);
+        return ok;
+    }
+
+    /** Unbind from the KeepAlive service for a client. */
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void dontKeepAliveForSession(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        if (params == null || params.getKeepAliveConnection() == null) return;
+        ServiceConnection connection = params.getKeepAliveConnection();
+        params.setKeepAliveConnection(null);
+        mContext.unbindService(connection);
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized boolean isPrerenderingAllowed(int uid) {
+        return RequestThrottler.getForUid(mContext, uid).isPrerenderingAllowed();
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void registerPrerenderRequest(int uid, String url) {
+        RequestThrottler.getForUid(mContext, uid).registerPrerenderRequest(url);
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void resetThrottling(int uid) {
+        RequestThrottler.getForUid(mContext, uid).reset();
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    public synchronized void cleanupAll() {
+        List<IBinder> sessions = new ArrayList<>(mSessionParams.keySet());
+        for (IBinder session : sessions) cleanupSession(session);
+    }
+
+    @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
+    private synchronized void cleanupSession(IBinder session) {
+        SessionParams params = mSessionParams.get(session);
+        if (params == null) return;
+        mSessionParams.remove(session);
+        mUidHasCalledWarmup.delete(params.uid);
+        IBinder binder = params.callback.asBinder();
+        binder.unlinkToDeath(params.deathRecipient, 0);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTab.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTab.java
index 4422df5..209c00b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTab.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabChromeWebContentsDelegateAndroid;
 import org.chromium.chrome.browser.tab.TabIdManager;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -346,7 +347,7 @@
 
     @Override
     protected TabChromeWebContentsDelegateAndroid createWebContentsDelegate() {
-        return new TabChromeWebContentsDelegateAndroid() {
+        return new TabChromeWebContentsDelegateAndroid(this, mActivity) {
             private String mTargetUrl;
 
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index f3d7958..2a9c0af 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -435,6 +435,11 @@
         return super.onMenuOrKeyboardAction(id, fromMenu);
     }
 
+    @Override
+    protected void setStatusBarColor(Tab tab, int color) {
+        // Intentionally do nothing as CustomTabActivity explicitly sets status bar color.
+    }
+
     /**
      * @return The {@link AppMenuPropertiesDelegate} associated with this activity. For test
      *         purposes only.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 0115813..283b4c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -6,11 +6,8 @@
 
 import android.app.ActivityManager;
 import android.app.Application;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
@@ -22,8 +19,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.ICustomTabsCallback;
 import android.support.customtabs.ICustomTabsService;
@@ -36,7 +31,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.library_loader.ProcessInitException;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.IntentHandler;
@@ -55,14 +49,9 @@
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -78,12 +67,6 @@
     static final String NO_PRERENDERING_KEY =
             "android.support.customtabs.maylaunchurl.NO_PRERENDERING";
 
-    // Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only.
-    private static final int NO_PREDICTION = 0;
-    private static final int GOOD_PREDICTION = 1;
-    private static final int BAD_PREDICTION = 2;
-    private static final int PREDICTION_STATUS_COUNT = 3;
-
     private static AtomicReference<CustomTabsConnection> sInstance =
             new AtomicReference<CustomTabsConnection>();
 
@@ -106,63 +89,11 @@
 
     protected final Application mApplication;
     private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean();
+    private final ClientManager mClientManager;
     private ExternalPrerenderHandler mExternalPrerenderHandler;
     private PrerenderedUrlParams mPrerender;
     private WebContents mSpareWebContents;
 
-    /** Per-session values. */
-    private static class SessionParams {
-        public final int mUid;
-        public final Referrer mReferrer;
-        public final ICustomTabsCallback mCallback;
-        public final IBinder.DeathRecipient mDeathRecipient;
-        private ServiceConnection mServiceConnection;
-        private String mPredictedUrl;
-        private long mLastMayLaunchUrlTimestamp;
-
-        public SessionParams(Context context, int uid, ICustomTabsCallback callback,
-                IBinder.DeathRecipient deathRecipient) {
-            mUid = uid;
-            mCallback = callback;
-            mDeathRecipient = deathRecipient;
-            mServiceConnection = null;
-            mPredictedUrl = null;
-            mLastMayLaunchUrlTimestamp = 0;
-            mReferrer = constructReferrer(context);
-        }
-
-        private Referrer constructReferrer(Context context) {
-            PackageManager packageManager = context.getPackageManager();
-            String[] packageList = packageManager.getPackagesForUid(mUid);
-            if (packageList.length != 1 || TextUtils.isEmpty(packageList[0])) return null;
-            return IntentHandler.constructValidReferrerForAuthority(packageList[0]);
-        }
-
-        public ServiceConnection getServiceConnection() {
-            return mServiceConnection;
-        }
-
-        public void setServiceConnection(ServiceConnection serviceConnection) {
-            mServiceConnection = serviceConnection;
-        }
-
-        public void setPredictionMetrics(String predictedUrl, long lastMayLaunchUrlTimestamp) {
-            mPredictedUrl = predictedUrl;
-            mLastMayLaunchUrlTimestamp = lastMayLaunchUrlTimestamp;
-        }
-
-        public String getPredictedUrl() {
-            return mPredictedUrl;
-        }
-
-        public long getLastMayLaunchUrlTimestamp() {
-            return mLastMayLaunchUrlTimestamp;
-        }
-    }
-
-    private final Object mLock = new Object();
-    private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>();
-
     /**
      * <strong>DO NOT CALL</strong>
      * Public to be instanciable from {@link ChromeApplication}. This is however
@@ -171,9 +102,7 @@
     public CustomTabsConnection(Application application) {
         super();
         mApplication = application;
-        synchronized (mLock) {
-            RequestThrottler.purgeOldEntries(application);
-        }
+        mClientManager = new ClientManager(mApplication);
     }
 
     /**
@@ -190,43 +119,20 @@
 
     @Override
     public boolean newSession(ICustomTabsCallback callback) {
-        if (callback == null) return false;
-        final int uid = Binder.getCallingUid();
-        final IBinder session = callback.asBinder();
-        IBinder.DeathRecipient deathRecipient =
-                new IBinder.DeathRecipient() {
-                    @Override
-                    public void binderDied() {
-                        ThreadUtils.postOnUiThread(new Runnable() {
-                            @Override
-                            public void run() {
-                                synchronized (mLock) {
-                                    cleanupAlreadyLocked(session);
-                                }
-                            }
-                        });
-                    }
-                };
-        SessionParams sessionParams =
-                new SessionParams(mApplication, uid, callback, deathRecipient);
-        synchronized (mLock) {
-            if (mSessionParams.containsKey(session)) return false;
-            try {
-                callback.asBinder().linkToDeath(deathRecipient, 0);
-            } catch (RemoteException e) {
-                // The return code doesn't matter, because this executes when
-                // the caller has died.
-                return false;
+        ClientManager.DisconnectCallback onDisconnect = new ClientManager.DisconnectCallback() {
+            @Override
+            public void run(IBinder session) {
+                cancelPrerender(session);
             }
-            mSessionParams.put(session, sessionParams);
-        }
-        return true;
+        };
+        return mClientManager.newSession(callback, Binder.getCallingUid(), onDisconnect);
     }
 
     @Override
     public boolean warmup(long flags) {
         // Here and in mayLaunchUrl(), don't do expensive work for background applications.
         if (!isCallerForegroundOrSelf()) return false;
+        mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid());
         if (!mWarmupHasBeenCalled.compareAndSet(false, true)) return true;
         // The call is non-blocking and this must execute on the UI thread, post a task.
         ThreadUtils.postOnUiThread(new Runnable() {
@@ -292,12 +198,8 @@
         final boolean noPrerendering =
                 extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false;
         final int uid = Binder.getCallingUid();
-        synchronized (mLock) {
-            SessionParams sessionParams = mSessionParams.get(session);
-            if (sessionParams == null || sessionParams.mUid != uid) return false;
-            sessionParams.setPredictionMetrics(urlString, SystemClock.elapsedRealtime());
-            RequestThrottler throttler = RequestThrottler.getForUid(mApplication, uid);
-            if (!throttler.updateStatsAndReturnWhetherAllowed()) return false;
+        if (!mClientManager.updateStatsAndReturnWhetherAllowed(session, uid, urlString)) {
+            return false;
         }
         ThreadUtils.postOnUiThread(new Runnable() {
             @Override
@@ -373,31 +275,7 @@
      * This is used for accounting.
      */
     void registerLaunch(IBinder session, String url) {
-        int outcome;
-        long elapsedTimeMs = -1;
-        synchronized (mLock) {
-            SessionParams sessionParams = mSessionParams.get(session);
-            if (sessionParams == null) {
-                outcome = NO_PREDICTION;
-            } else {
-                String predictedUrl = sessionParams.getPredictedUrl();
-                outcome = predictedUrl == null ? NO_PREDICTION
-                        : predictedUrl.equals(url) ? GOOD_PREDICTION : BAD_PREDICTION;
-                elapsedTimeMs = SystemClock.elapsedRealtime()
-                        - sessionParams.getLastMayLaunchUrlTimestamp();
-                sessionParams.setPredictionMetrics(null, 0);
-                if (outcome == GOOD_PREDICTION) {
-                    RequestThrottler.getForUid(mApplication, sessionParams.mUid)
-                            .registerSuccess(url);
-                }
-            }
-        }
-        RecordHistogram.recordEnumeratedHistogram(
-                "CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT);
-        if (outcome == GOOD_PREDICTION) {
-            RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToLaunch",
-                    elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MILLISECONDS, 100);
-        }
+        mClientManager.registerLaunch(session, url);
     }
 
     /**
@@ -446,16 +324,7 @@
     }
 
     public Referrer getReferrerForSession(IBinder session) {
-        if (!mSessionParams.containsKey(session)) return null;
-        return mSessionParams.get(session).mReferrer;
-    }
-
-    private ICustomTabsCallback getCallbackForSession(IBinder session) {
-        synchronized (mLock) {
-            SessionParams sessionParams = mSessionParams.get(session);
-            if (sessionParams == null) return null;
-            return sessionParams.mCallback;
-        }
+        return mClientManager.getReferrerForSession(session);
     }
 
     /**
@@ -469,7 +338,7 @@
      * @return true for success.
      */
     boolean notifyNavigationEvent(IBinder session, int navigationEvent) {
-        ICustomTabsCallback callback = getCallbackForSession(session);
+        ICustomTabsCallback callback = mClientManager.getCallbackForSession(session);
         if (callback == null) return false;
         try {
             callback.onNavigationEvent(navigationEvent, null);
@@ -494,41 +363,7 @@
      * @return true for success.
      */
     boolean keepAliveForSession(IBinder session, Intent intent) {
-        // When an application is bound to a service, its priority is raised to
-        // be at least equal to the application's one. This binds to a dummy
-        // service (no calls to this service are made).
-        if (intent == null || intent.getComponent() == null) return false;
-        SessionParams sessionParams;
-        synchronized (mLock) {
-            sessionParams = mSessionParams.get(session);
-            if (sessionParams == null) return false;
-        }
-        String packageName = intent.getComponent().getPackageName();
-        PackageManager pm = mApplication.getApplicationContext().getPackageManager();
-        // Only binds to the application associated to this session.
-        int uid = sessionParams.mUid;
-        if (!Arrays.asList(pm.getPackagesForUid(uid)).contains(packageName)) return false;
-        Intent serviceIntent = new Intent().setComponent(intent.getComponent());
-        // This ServiceConnection doesn't handle disconnects. This is on
-        // purpose, as it occurs when the remote process has died. Since the
-        // only use of this connection is to keep the application alive,
-        // re-connecting would just re-create the process, but the application
-        // state has been lost at that point, the callbacks invalidated, etc.
-        ServiceConnection connection = new ServiceConnection() {
-            @Override
-            public void onServiceConnected(ComponentName name, IBinder service) {}
-            @Override
-            public void onServiceDisconnected(ComponentName name) {}
-        };
-        boolean ok;
-        try {
-            ok = mApplication.getApplicationContext().bindService(
-                    serviceIntent, connection, Context.BIND_AUTO_CREATE);
-        } catch (SecurityException e) {
-            return false;
-        }
-        if (ok) sessionParams.setServiceConnection(connection);
-        return ok;
+        return mClientManager.keepAliveForSession(session, intent);
     }
 
     /**
@@ -539,14 +374,7 @@
      * @param session The Binder object identifying the session.
      */
     void dontKeepAliveForSession(IBinder session) {
-        SessionParams sessionParams;
-        synchronized (mLock) {
-            sessionParams = mSessionParams.get(session);
-            if (sessionParams == null || sessionParams.getServiceConnection() == null) return;
-        }
-        ServiceConnection serviceConnection = sessionParams.getServiceConnection();
-        sessionParams.setServiceConnection(null);
-        mApplication.getApplicationContext().unbindService(serviceConnection);
+        mClientManager.dontKeepAliveForSession(session);
     }
 
     /**
@@ -613,23 +441,7 @@
     @VisibleForTesting
     void cleanupAll() {
         ThreadUtils.assertOnUiThread();
-        synchronized (mLock) {
-            List<IBinder> sessions = new ArrayList<>(mSessionParams.keySet());
-            for (IBinder session : sessions) cleanupAlreadyLocked(session);
-        }
-    }
-
-    /**
-     * Called when a remote client has died.
-     */
-    private void cleanupAlreadyLocked(IBinder session) {
-        ThreadUtils.assertOnUiThread();
-        SessionParams params = mSessionParams.get(session);
-        if (params == null) return;
-        mSessionParams.remove(session);
-        IBinder binder = params.mCallback.asBinder();
-        binder.unlinkToDeath(params.mDeathRecipient, 0);
-        cancelPrerender(session);
+        mClientManager.cleanupAll();
     }
 
     private boolean mayPrerender() {
@@ -663,9 +475,7 @@
         // Last one wins and cancels the previous prerender.
         cancelPrerender(null);
         if (TextUtils.isEmpty(url)) return;
-        synchronized (mLock) {
-            if (!RequestThrottler.getForUid(mApplication, uid).isPrerenderingAllowed()) return;
-        }
+        if (!mClientManager.isPrerenderingAllowed(uid)) return;
         Intent extrasIntent = new Intent();
         if (extras != null) extrasIntent.putExtras(extras);
         if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) return;
@@ -682,9 +492,7 @@
         WebContents webContents = mExternalPrerenderHandler.addPrerender(
                 Profile.getLastUsedProfile(), url, referrer, contentSize.x, contentSize.y);
         if (webContents != null) {
-            synchronized (mLock) {
-                RequestThrottler.getForUid(mApplication, uid).registerPrerenderRequest(url);
-            }
+            mClientManager.registerPrerenderRequest(uid, url);
             mPrerender = new PrerenderedUrlParams(session, webContents, url, referrer, extras);
         }
     }
@@ -720,8 +528,6 @@
 
     @VisibleForTesting
     void resetThrottling(Context context, int uid) {
-        synchronized (mLock) {
-            RequestThrottler.getForUid(context, uid).reset();
-        }
+        mClientManager.resetThrottling(uid);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java b/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java
index 528e52a7..96530e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/database/SQLiteCursor.java
@@ -2,7 +2,6 @@
 // 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.database;
 
 import android.database.AbstractCursor;
@@ -16,6 +15,8 @@
 /**
  * This class exposes the query result from native side.
  */
+// TODO(michaelbai): fix deprecation warnings crbug.com/528085
+@SuppressWarnings("deprecation")
 public class SQLiteCursor extends AbstractCursor {
     private static final String TAG = "SQLiteCursor";
     // Used by JNI.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java
index 70f4ecc..a9f69c35 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentActivity.java
@@ -790,11 +790,11 @@
         updateTaskDescription(label, bitmap);
     }
 
-    protected void updateTaskDescription(String label, Bitmap icon) {
+    private void updateTaskDescription(String label, Bitmap icon) {
         int color = mDefaultThemeColor;
         if (getActivityTab() != null) color = getActivityTab().getThemeColor();
         boolean useDefaultStatusBarColor = isIncognito() || color == mDefaultThemeColor;
-        DocumentUtils.updateTaskDescription(this, label, icon, color, useDefaultStatusBarColor);
+        ApiCompatibilityUtils.setTaskDescription(this, label, icon, color);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java
index b28925371..8702f90 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentTab.java
@@ -8,6 +8,7 @@
 
 import org.chromium.base.ObserverList.RewindableIterator;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.TabState;
@@ -17,6 +18,7 @@
 import org.chromium.chrome.browser.tab.ChromeTab;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabChromeWebContentsDelegateAndroid;
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabUma;
 import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
@@ -145,6 +147,10 @@
      */
     public class DocumentTabChromeWebContentsDelegateAndroid
             extends TabChromeWebContentsDelegateAndroid {
+        public DocumentTabChromeWebContentsDelegateAndroid(Tab tab, ChromeActivity activity) {
+            super(tab, activity);
+        }
+
         /**
          * TODO(dfalcantara): Remove this when DocumentActivity.getTabModelSelector()
          *                    can return a TabModelSelector that activateContents() can use.
@@ -157,7 +163,7 @@
 
     @Override
     protected TabChromeWebContentsDelegateAndroid createWebContentsDelegate() {
-        return new DocumentTabChromeWebContentsDelegateAndroid();
+        return new DocumentTabChromeWebContentsDelegateAndroid(this, mActivity);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentUtils.java
index 205856b..250a214 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/DocumentUtils.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.document;
 
 import android.annotation.TargetApi;
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManager.AppTask;
 import android.app.ActivityManager.RecentTaskInfo;
@@ -13,18 +12,14 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.graphics.Bitmap;
-import android.graphics.Color;
 import android.net.Uri;
 import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate;
-import org.chromium.chrome.browser.util.ColorUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -37,22 +32,6 @@
     public static final String TAG = "DocumentUtilities";
 
     /**
-     * Update the Recents entry for the Activity.
-     * @param activity Activity to change the entry for.
-     * @param title Title to show on the card.
-     * @param icon Icon to show on the card.
-     * @param color Color to use for the card's bar.
-     * @param useDefaultStatusBarColor Whether status bar should be set to default color.
-     */
-    public static void updateTaskDescription(Activity activity, String title, Bitmap icon,
-            int color, boolean useDefaultStatusBarColor) {
-        ApiCompatibilityUtils.setTaskDescription(activity, title, icon, color);
-        int statusBarColor = useDefaultStatusBarColor
-                ? Color.BLACK : ColorUtils.getDarkenedColorForStatusBar(color);
-        ApiCompatibilityUtils.setStatusBarColor(activity.getWindow(), statusBarColor);
-    }
-
-    /**
      * Finishes tasks other than the one with the given task ID that were started with the given
      * tabId, leaving a unique task to own a Tab with that particular ID.
      * @param tabId ID of the tab to remove duplicates for.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkBookmarkRow.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkBookmarkRow.java
index 0b67ac6..e6ddc40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkBookmarkRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkBookmarkRow.java
@@ -66,6 +66,9 @@
             case UIState.STATE_FOLDER:
                 launchLocation = LaunchLocation.FOLDER;
                 break;
+            case UIState.STATE_FILTER:
+                launchLocation = LaunchLocation.FILTER;
+                break;
             case UIState.STATE_LOADING:
                 assert false :
                         "The main content shouldn't be inflated if it's still loading";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
index f956945..a21baaee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
@@ -414,7 +414,7 @@
     public void openBookmark(BookmarkId bookmark, int launchLocation) {
         clearSelection();
         if (mEnhancedBookmarksModel.getBookmarkById(bookmark) != null) {
-            String url = mEnhancedBookmarksModel.getLaunchUrlAndMarkAccessed(bookmark);
+            String url = mEnhancedBookmarksModel.getLaunchUrlAndMarkAccessed(mActivity, bookmark);
             // TODO(jianli): Notify the user about the failure.
             if (TextUtils.isEmpty(url)) return;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkRecyclerView.java
index edadd53..90e3d06 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkRecyclerView.java
@@ -151,7 +151,8 @@
         // line to show offline page size eats up the default spacing.
         if (mVerticalSpaceItemDecoration == null) {
             mVerticalSpaceItemDecoration =
-                    new VerticalSpaceItemDecoration(R.dimen.offline_page_item_vertical_spacing);
+                    new VerticalSpaceItemDecoration(getResources().getDimensionPixelSize(
+                            R.dimen.offline_page_item_vertical_spacing));
             addItemDecoration(mVerticalSpaceItemDecoration);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
index bbe2d6f..f488ab00 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.enhancedbookmarks;
 
+import android.content.Context;
+
 import org.chromium.base.ObserverList;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.BookmarksBridge;
@@ -12,6 +14,7 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageModelObserver;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.SavePageCallback;
 import org.chromium.chrome.browser.offlinepages.OfflinePageItem;
+import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.bookmarks.BookmarkType;
@@ -229,14 +232,16 @@
      * Retrieves the url to launch a bookmark or saved page. If latter, also marks it as being
      * accessed.
      *
+     * @parma context Context for checking connection.
      * @param bookmarkId ID of the bookmark to launch.
      * @return The launch URL.
      */
-    public String getLaunchUrlAndMarkAccessed(BookmarkId bookmarkId) {
+    public String getLaunchUrlAndMarkAccessed(Context context, BookmarkId bookmarkId) {
         String url = getBookmarkById(bookmarkId).getUrl();
-        if (mOfflinePageBridge == null) return url;
+        // When there is a network connection, we visit original URL online.
+        if (mOfflinePageBridge == null || OfflinePageUtils.isConnected(context)) return url;
 
-        // Return the offline url for the offline page.
+        // Return the offline url for the offline page if one exists.
         OfflinePageItem page = mOfflinePageBridge.getPageByBookmarkId(bookmarkId);
         if (page == null) return url;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java
new file mode 100644
index 0000000..1b3024cb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyFirstRunFragment.java
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium 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.firstrun;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.Switch;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
+import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoScreen;
+
+/**
+ * The First Run Experience fragment that allows the user to opt in to Data Saver.
+ */
+public class DataReductionProxyFirstRunFragment extends FirstRunPage {
+
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.fre_data_reduction_proxy, container, false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        final Switch enableDataSaverSwitch = (Switch) view
+                .findViewById(R.id.enable_data_saver_switch);
+        Button nextButton = (Button) view.findViewById(R.id.next_button);
+
+        enableDataSaverSwitch.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                DataReductionProxySettings.getInstance().setDataReductionProxyEnabled(
+                        v.getContext(), enableDataSaverSwitch.isChecked());
+                if (enableDataSaverSwitch.isChecked()) {
+                    enableDataSaverSwitch.setText(R.string.data_reduction_enabled_switch);
+                } else {
+                    enableDataSaverSwitch.setText(R.string.data_reduction_disabled_switch);
+                }
+            }
+        });
+
+        nextButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                advanceToNextPage();
+            }
+        });
+
+        enableDataSaverSwitch.setChecked(true);
+        DataReductionProxySettings.getInstance().setDataReductionProxyEnabled(
+                view.getContext(), enableDataSaverSwitch.isChecked());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        DataReductionPromoScreen.setDisplayedDataReductionPromo(getActivity(), true);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyView.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyView.java
new file mode 100644
index 0000000..52890aaf
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DataReductionProxyView.java
@@ -0,0 +1,47 @@
+// Copyright 2015 The Chromium 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.firstrun;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.R;
+
+/**
+ * View that handles orientation changes for the Data Saver first run page.
+ */
+public class DataReductionProxyView extends FrameLayout {
+
+    public DataReductionProxyView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // This assumes that view's layout_width is set to match_parent.
+        assert MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
+        int width = MeasureSpec.getSize(widthMeasureSpec);
+        int height = MeasureSpec.getSize(heightMeasureSpec);
+        LinearLayout content = (LinearLayout) findViewById(R.id.fre_content);
+        int paddingStart = 0;
+        if (width >= 2 * getResources().getDimension(R.dimen.fre_image_carousel_width)
+                && width > height) {
+            content.setOrientation(LinearLayout.HORIZONTAL);
+            paddingStart = getResources().getDimensionPixelSize(R.dimen.fre_margin);
+        } else {
+            content.setOrientation(LinearLayout.VERTICAL);
+        }
+        ApiCompatibilityUtils.setPaddingRelative(content,
+                paddingStart,
+                content.getPaddingTop(),
+                ApiCompatibilityUtils.getPaddingEnd(content),
+                content.getPaddingBottom());
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 40d3d2d..dd93ae8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -14,6 +14,7 @@
 import android.util.Log;
 
 import org.chromium.base.ApplicationStatus;
+import org.chromium.base.FieldTrialList;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.base.metrics.RecordHistogram;
@@ -21,6 +22,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.EmbedContentViewActivity;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
+import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoScreen;
+import org.chromium.chrome.browser.preferences.datareduction.DataReductionProxyUma;
 import org.chromium.chrome.browser.profiles.Profile;
 
 import java.lang.ref.WeakReference;
@@ -100,6 +104,11 @@
         // An optional welcome page.
         if (mShowWelcomePage) mPages.add(pageOf(ToSAndUMAFirstRunFragment.class));
 
+        // An optional Data Saver page.
+        if (FieldTrialList.findFullName("DataReductionProxyFREPromo").startsWith("Enabled")) {
+            mPages.add(pageOf(DataReductionProxyFirstRunFragment.class));
+        }
+
         // An optional sign-in page.
         if (mFreProperties.getBoolean(SHOW_SIGNIN_PAGE)) {
             mPages.add(pageOf(AccountFirstRunFragment.class));
@@ -288,6 +297,17 @@
             startActivity(originalIntent);
         }
 
+        if (DataReductionPromoScreen
+                .getDisplayedDataReductionPromo(getApplicationContext())) {
+            if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) {
+                DataReductionProxyUma
+                        .dataReductionProxyUIAction(DataReductionProxyUma.ACTION_FRE_ENABLED);
+            } else {
+                DataReductionProxyUma
+                        .dataReductionProxyUIAction(DataReductionProxyUma.ACTION_FRE_DISABLED);
+            }
+        }
+
         Intent resultData = new Intent();
         resultData.putExtras(mFreProperties);
         finishAllFREActivities(Activity.RESULT_OK, resultData);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java
new file mode 100644
index 0000000..db4aa505
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java
@@ -0,0 +1,89 @@
+// Copyright 2015 The Chromium 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.media.router;
+
+import android.content.Context;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.MediaRouteDialogFactory;
+import android.support.v7.media.MediaRouter;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.chrome.browser.media.remote.ChromeMediaRouteDialogFactory;
+import org.chromium.chrome.browser.media.router.cast.MediaSource;
+
+import javax.annotation.Nullable;
+
+/**
+ * Shared code for {@link MediaRouteDialogManager} implementations.
+ */
+public abstract class BaseMediaRouteDialogManager implements MediaRouteDialogManager {
+
+    private final MediaSource mMediaSource;
+    private final MediaRouter mAndroidMediaRouter;
+    private final MediaRouteDialogDelegate mDelegate;
+
+    private DialogFragment mDialogFragment;
+
+    @Override
+    public void openDialog() {
+        if (mAndroidMediaRouter == null) return;
+
+        FragmentActivity currentActivity =
+                (FragmentActivity) ApplicationStatus.getLastTrackedFocusedActivity();
+        if (currentActivity == null) return;
+
+        FragmentManager fm = currentActivity.getSupportFragmentManager();
+        if (fm == null) return;
+
+        MediaRouteDialogFactory factory = new ChromeMediaRouteDialogFactory();
+        mDialogFragment = openDialogInternal(fm, factory);
+    }
+
+    @Override
+    public void closeDialog() {
+        if (mDialogFragment == null) return;
+
+        mDialogFragment.dismiss();
+        mDialogFragment = null;
+    }
+
+    @Override
+    public boolean isShowingDialog() {
+        return mDialogFragment != null && mDialogFragment.isVisible();
+    }
+
+    protected BaseMediaRouteDialogManager(MediaSource source, Context applicationContext,
+            MediaRouteDialogDelegate delegate) {
+        mMediaSource = source;
+        mAndroidMediaRouter = ChromeMediaRouter.getAndroidMediaRouter(applicationContext);
+        mDelegate = delegate;
+    }
+
+    /**
+     * Initializes and shows the {@link DialogFragment} instance corresponding to the dialog type
+     * needed.
+     *
+     * @param fm {@link FragmentManager} to use to show the dialog.
+     * @param factory {@link MediaRouteDialogFactory} to use to create the dialog.
+     * @return null if the initialization fails, otherwise the initialized dialog fragment.
+     */
+    @Nullable
+    protected abstract DialogFragment openDialogInternal(
+            FragmentManager fm, MediaRouteDialogFactory factory);
+
+    protected MediaRouteDialogDelegate delegate() {
+        return mDelegate;
+    }
+
+    protected MediaRouter androidMediaRouter() {
+        return mAndroidMediaRouter;
+    }
+
+    protected MediaSource mediaSource() {
+        return mMediaSource;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
index 6c71da4..8797414 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.media.router;
 
 import android.content.Context;
+import android.support.v7.media.MediaRouter;
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -18,6 +19,8 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 /**
  * Implements the JNI interface called from the C++ Media Router implementation on Android.
  * Owns a list of {@link MediaRouteProvider} implementations and dispatches native calls to them.
@@ -37,6 +40,23 @@
     private final Map<String, List<MediaSink>> mSinksPerSource =
             new HashMap<String, List<MediaSink>>();
 
+
+    /**
+     * Obtains the {@link MediaRouter} instance given the application context.
+     * @param applicationContext The context to get the Android media router service for.
+     * @return Null if the media router API is not supported, the service instance otherwise.
+     */
+    @Nullable
+    public static MediaRouter getAndroidMediaRouter(Context applicationContext) {
+        try {
+            // Pre-MR1 versions of JB do not have the complete MediaRouter APIs,
+            // so getting the MediaRouter instance will throw an exception.
+            return MediaRouter.getInstance(applicationContext);
+        } catch (NoSuchMethodError e) {
+            return null;
+        }
+    }
+
     /**
      * @param presentationId the presentation id associated with the route
      * @param sinkId the id of the {@link MediaSink} associated with the route
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
index 9cbb46d..d294354e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
@@ -4,21 +4,12 @@
 
 package org.chromium.chrome.browser.media.router;
 
-import android.app.Dialog;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnDismissListener;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
 import android.support.v7.app.MediaRouteChooserDialogFragment;
-import android.support.v7.app.MediaRouteDialogFactory;
-import android.support.v7.media.MediaRouter;
+import android.support.v7.app.MediaRouteControllerDialogFragment;
 
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
-import org.chromium.chrome.browser.media.remote.ChromeMediaRouteDialogFactory;
 import org.chromium.chrome.browser.media.router.cast.MediaSink;
 import org.chromium.chrome.browser.media.router.cast.MediaSource;
 
@@ -27,15 +18,14 @@
  * on Android.
  */
 @JNINamespace("media_router")
-public class ChromeMediaRouterDialogController extends MediaRouter.Callback
-        implements OnDismissListener, OnCancelListener {
+public class ChromeMediaRouterDialogController implements MediaRouteDialogDelegate {
 
-    private static final String MEDIA_ROUTE_CHOOSER_DIALOG_FRAGMENT =
-            "android.support.v7.mediarouter:MediaRouteChooserDialogFragment";
+    private static final String MEDIA_ROUTE_CONTROLLER_DIALOG_FRAGMENT =
+            "android.support.v7.mediarouter:MediaRouteControllerDialogFragment";
 
     private final long mNativeDialogController;
-    private final MediaRouter mAndroidMediaRouter;
-    private MediaRouteChooserDialogFragment mChooserDialogFragment;
+    private final Context mApplicationContext;
+    private MediaRouteDialogManager mDialogManager;
 
     /**
      * Returns a new initialized {@link ChromeMediaRouterDialogController}.
@@ -50,39 +40,35 @@
     }
 
     /**
-     * Shows the {@link MediaRouteChooserDialogFragment} dialog if it's not shown yet.
+     * Shows the {@link MediaRouteChooserDialogFragment} if it's not shown yet.
      * @param sourceUrn the URN identifying the media source to filter the devices with.
      */
     @CalledByNative
-    public void createDialog(String sourceUrn) {
+    public void openRouteChooserDialog(String sourceUrn) {
         if (isShowingDialog()) return;
 
-        MediaSource mediaSource = MediaSource.from(sourceUrn);
-        if (mediaSource == null) return;
+        MediaSource source = MediaSource.from(sourceUrn);
+        if (source == null) return;
 
-        FragmentActivity currentActivity =
-                (FragmentActivity) ApplicationStatus.getLastTrackedFocusedActivity();
-        if (currentActivity == null) return;
+        mDialogManager = new MediaRouteChooserDialogManager(source, mApplicationContext, this);
+        mDialogManager.openDialog();
+    }
 
-        FragmentManager fm = currentActivity.getSupportFragmentManager();
-        if (fm == null) return;
+    /**
+     * Shows the {@link MediaRouteControllerDialogFragment} if it's not shown yet.
+     * @param sourceUrn the URN identifying the media source of the current media route.
+     * @param mediaRouteId the identifier of the route to be controlled.
+     */
+    @CalledByNative
+    public void openRouteControllerDialog(String sourceUrn, String mediaRouteId) {
+        if (isShowingDialog()) return;
 
-        if (fm.findFragmentByTag(MEDIA_ROUTE_CHOOSER_DIALOG_FRAGMENT) != null) return;
+        MediaSource source = MediaSource.from(sourceUrn);
+        if (source == null) return;
 
-        MediaRouteDialogFactory factory = new ChromeMediaRouteDialogFactory();
-        mChooserDialogFragment = factory.onCreateChooserDialogFragment();
-        mChooserDialogFragment.setRouteSelector(mediaSource.buildRouteSelector());
-        mChooserDialogFragment.show(fm, MEDIA_ROUTE_CHOOSER_DIALOG_FRAGMENT);
-        fm.executePendingTransactions();
-
-        Dialog dialog = mChooserDialogFragment.getDialog();
-        if (dialog == null) {
-            closeDialog();
-            return;
-        }
-
-        dialog.setOnDismissListener(this);
-        dialog.setOnCancelListener(this);
+        mDialogManager = new MediaRouteControllerDialogManager(
+                source, mediaRouteId, mApplicationContext, this);
+        mDialogManager.openDialog();
     }
 
     /**
@@ -92,57 +78,43 @@
     public void closeDialog() {
         if (!isShowingDialog()) return;
 
-        // Will remove MediaRouter.Callback in onDismiss().
-        mChooserDialogFragment.dismiss();
-        mChooserDialogFragment = null;
+        mDialogManager.closeDialog();
+        mDialogManager = null;
     }
 
     /**
-     * @return if the media route chooser dialog is currently open.
+     * @return if any media route dialog is currently open.
      */
     @CalledByNative
     public boolean isShowingDialog() {
-        return mChooserDialogFragment != null && mChooserDialogFragment.isVisible();
+        return mDialogManager != null && mDialogManager.isShowingDialog();
     }
 
-    /**
-     * {@link OnDismissListener} implementation.
-     */
     @Override
-    public void onDismiss(DialogInterface dialog) {
-        // If the dialog was cancelled, the fragment will be null.
-        if (mChooserDialogFragment == null) return;
-
-        mChooserDialogFragment.dismiss();
-        mChooserDialogFragment = null;
-        nativeOnSinkSelected(mNativeDialogController,
-                MediaSink.fromRoute(mAndroidMediaRouter.getSelectedRoute()).getId());
+    public void onSinkSelected(MediaSink sink) {
+        mDialogManager = null;
+        nativeOnSinkSelected(mNativeDialogController, sink.getId());
     }
 
-    /**
-     * {@link OnCancelListener} implementation.
-     */
     @Override
-    public void onCancel(DialogInterface dialog) {
-        mChooserDialogFragment.dismiss();
-        mChooserDialogFragment = null;
-        nativeOnDialogDismissed(mNativeDialogController);
+    public void onRouteClosed(String mediaRouteId) {
+        mDialogManager = null;
+        nativeOnRouteClosed(mNativeDialogController, mediaRouteId);
+    }
+
+    @Override
+    public void onDialogCancelled() {
+        mDialogManager = null;
+        nativeOnDialogCancelled(mNativeDialogController);
     }
 
     private ChromeMediaRouterDialogController(long nativeDialogController, Context context) {
         mNativeDialogController = nativeDialogController;
-        MediaRouter androidMediaRouter = null;
-        try {
-            // Pre-MR1 versions of JB do not have the complete MediaRouter APIs,
-            // so getting the MediaRouter instance will throw an exception.
-            androidMediaRouter = MediaRouter.getInstance(context);
-        } catch (NoSuchMethodError e) {
-            androidMediaRouter = null;
-        }
-        mAndroidMediaRouter = androidMediaRouter;
+        mApplicationContext = context;
     }
 
-    native void nativeOnDialogDismissed(long nativeMediaRouterDialogControllerAndroid);
+    native void nativeOnDialogCancelled(long nativeMediaRouterDialogControllerAndroid);
     native void nativeOnSinkSelected(
             long nativeMediaRouterDialogControllerAndroid, String sinkId);
+    native void nativeOnRouteClosed(long nativeMediaRouterDialogControllerAndroid, String routeId);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java
new file mode 100644
index 0000000..9bc3114
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium 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.media.router;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.MediaRouteChooserDialogFragment;
+import android.support.v7.app.MediaRouteDialogFactory;
+
+import org.chromium.chrome.browser.media.router.cast.MediaSink;
+import org.chromium.chrome.browser.media.router.cast.MediaSource;
+
+/**
+ * Manages the dialog responsible for selecting a {@link MediaSink}.
+ */
+public class MediaRouteChooserDialogManager extends BaseMediaRouteDialogManager implements
+        OnCancelListener, OnDismissListener {
+
+    private static final String DIALOG_FRAGMENT_TAG =
+            "android.support.v7.mediarouter:MediaRouteChooserDialogFragment";
+
+    private boolean mCancelled;
+
+    public MediaRouteChooserDialogManager(MediaSource source, Context applicationContext,
+            MediaRouteDialogDelegate delegate) {
+        super(source, applicationContext, delegate);
+    }
+
+    @Override
+    protected DialogFragment openDialogInternal(FragmentManager fm,
+            MediaRouteDialogFactory factory) {
+        if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null;
+
+        MediaRouteChooserDialogFragment fragment = factory.onCreateChooserDialogFragment();
+        fragment.setRouteSelector(mediaSource().buildRouteSelector());
+        fragment.show(fm, DIALOG_FRAGMENT_TAG);
+        fm.executePendingTransactions();
+
+        Dialog dialog = fragment.getDialog();
+        if (dialog == null) return null;
+
+        dialog.setOnCancelListener(this);
+        dialog.setOnDismissListener(this);
+
+        return fragment;
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        mCancelled = true;
+
+        delegate().onDialogCancelled();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        closeDialog();
+
+        if (mCancelled) return;
+
+        MediaSink newSink = MediaSink.fromRoute(androidMediaRouter().getSelectedRoute());
+        delegate().onSinkSelected(newSink);
+    }
+
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java
new file mode 100644
index 0000000..c65ab4ea
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium 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.media.router;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v7.app.MediaRouteControllerDialogFragment;
+import android.support.v7.app.MediaRouteDialogFactory;
+import android.support.v7.media.MediaRouter;
+
+import org.chromium.chrome.browser.media.router.cast.MediaSource;
+
+/**
+ * Manages the dialog responsible for controlling an existing media route.
+ */
+public class MediaRouteControllerDialogManager extends BaseMediaRouteDialogManager implements
+        OnCancelListener, OnDismissListener {
+
+    private static final String DIALOG_FRAGMENT_TAG =
+            "android.support.v7.mediarouter:MediaRouteControllerDialogFragment";
+
+    private final String mMediaRouteId;
+    private final MediaRouter.Callback mCallback = new MediaRouter.Callback() {
+        @Override
+        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
+            delegate().onRouteClosed(mMediaRouteId);
+        }
+    };
+
+    public MediaRouteControllerDialogManager(MediaSource source, String mediaRouteId,
+            Context applicationContext,
+            MediaRouteDialogDelegate delegate) {
+        super(source, applicationContext, delegate);
+        mMediaRouteId = mediaRouteId;
+    }
+
+    @Override
+    protected DialogFragment openDialogInternal(FragmentManager fm,
+            MediaRouteDialogFactory factory) {
+        if (fm.findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) return null;
+
+        MediaRouteControllerDialogFragment fragment = factory.onCreateControllerDialogFragment();
+        fragment.show(fm, DIALOG_FRAGMENT_TAG);
+        fm.executePendingTransactions();
+
+        Dialog dialog = fragment.getDialog();
+        if (dialog == null) return null;
+
+        dialog.setOnCancelListener(this);
+        dialog.setOnDismissListener(this);
+        androidMediaRouter().addCallback(mediaSource().buildRouteSelector(), mCallback);
+
+        return fragment;
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        delegate().onDialogCancelled();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        androidMediaRouter().removeCallback(mCallback);
+        closeDialog();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java
new file mode 100644
index 0000000..edebb8f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium 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.media.router;
+
+import org.chromium.chrome.browser.media.router.cast.MediaSink;
+
+/**
+ * An interface providing callbacks for {@link MediaRouteDialogManager}.
+ */
+public interface MediaRouteDialogDelegate {
+    /**
+     * Notifies the delegate if the user has chosen a {@link MediaSink} to connect to.
+     * onDialogDismissed() is not called in this case.
+     * @param sink The sink selected by the user.
+     */
+    void onSinkSelected(MediaSink sink);
+
+    /**
+     * Notifies the delegate if the user has closed the existing route.
+     * @param mediaRouteId id of the media route that was closed.
+     */
+    void onRouteClosed(String mediaRouteId);
+
+    /**
+     * Notifies the delegate if the dialog was dismissed without any user action.
+     */
+    void onDialogCancelled();
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java
new file mode 100644
index 0000000..94ba0cf
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium 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.media.router;
+
+import android.support.v7.app.MediaRouteChooserDialog;
+import android.support.v7.app.MediaRouteControllerDialog;
+
+/**
+ * A common interface to be implemented by various media route dialog handlers
+ * (e.g {@link MediaRouteChooserDialog} or {@link MediaRouteControllerDialog}.
+ */
+public interface MediaRouteDialogManager {
+    /**
+     * Opens the dialog managed by the implementation of the interface.
+     */
+    void openDialog();
+
+    /**
+     * Closes the currently open dialog.
+     */
+    void closeDialog();
+
+    /**
+     * @return if a chooser or controller dialog is shown.
+     */
+    boolean isShowingDialog();
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java
index 5824dda..e87a009 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.support.v7.media.MediaRouter;
 
+import org.chromium.chrome.browser.media.router.ChromeMediaRouter;
 import org.chromium.chrome.browser.media.router.DiscoveryDelegate;
 import org.chromium.chrome.browser.media.router.MediaRouteManager;
 import org.chromium.chrome.browser.media.router.MediaRouteProvider;
@@ -24,8 +25,6 @@
  */
 public class CastMediaRouteProvider
         implements MediaRouteProvider, DiscoveryDelegate, RouteDelegate {
-    private static final String TAG = "cr.MediaRouter";
-
     private final Context mApplicationContext;
     private final MediaRouter mAndroidMediaRouter;
     private final MediaRouteManager mManager;
@@ -88,7 +87,8 @@
     public static CastMediaRouteProvider create(
             Context applicationContext, MediaRouteManager manager) {
         assert applicationContext != null;
-        MediaRouter androidMediaRouter = getAndroidMediaRouter(applicationContext);
+        MediaRouter androidMediaRouter =
+                ChromeMediaRouter.getAndroidMediaRouter(applicationContext);
         if (androidMediaRouter == null) return null;
 
         return new CastMediaRouteProvider(applicationContext, androidMediaRouter, manager);
@@ -193,15 +193,4 @@
         mManager = manager;
     }
 
-    @Nullable
-    private static MediaRouter getAndroidMediaRouter(Context applicationContext) {
-        try {
-            // Pre-MR1 versions of JB do not have the complete MediaRouter APIs,
-            // so getting the MediaRouter instance will throw an exception.
-            return MediaRouter.getInstance(applicationContext);
-        } catch (NoSuchMethodError e) {
-            return null;
-        }
-    }
-
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/SessionWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/SessionWrapper.java
index b858869..cf5018a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/SessionWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/cast/SessionWrapper.java
@@ -81,6 +81,7 @@
     private String mApplicationStatus;
     private ApplicationMetadata mApplicationMetadata;
     private int mSequenceNumber;
+    private boolean mStoppingApplication;
 
     /**
      * Initializes a new {@link SessionWrapper} instance.
@@ -115,14 +116,18 @@
 
     @Override
     public void close() {
+        if (mStoppingApplication) return;
+
         // close() have been called before from another code path.
         if (mApiClient == null) return;
 
         if (mApiClient.isConnected() || mApiClient.isConnecting()) {
+            mStoppingApplication = true;
             Cast.CastApi.stopApplication(mApiClient, mSessionId)
                     .setResultCallback(new ResultCallback<Status>() {
                         @Override
                         public void onResult(Status status) {
+                            onMessage("remove_session", "\"" + mSessionId + "\"");
                             // TODO(avayvod): handle a failure to stop the application.
                             // https://crbug.com/535577
 
@@ -134,6 +139,7 @@
                             mApiClient = null;
 
                             mRouteDelegate.onRouteClosed(SessionWrapper.this);
+                            mStoppingApplication = false;
                         }
                     });
         }
@@ -273,7 +279,8 @@
         JSONObject jsonCastMessage = jsonMessage.getJSONObject("message");
         String messageType = jsonCastMessage.getString("type");
         if ("STOP".equals(messageType)) {
-            return stopApplication();
+            close();
+            return true;
         } else if (Arrays.asList(MEDIA_MESSAGE_TYPES).contains(messageType)) {
             return sendCastMessage(jsonMessage.getString("message"), MEDIA_NAMESPACE);
         }
@@ -349,19 +356,6 @@
                 type, message, sequenceNumber, clientId);
     }
 
-    private boolean stopApplication() {
-        if (!mApiClient.isConnected() && !mApiClient.isConnecting()) return false;
-
-        try {
-            Cast.CastApi.stopApplication(mApiClient, mSessionId);
-        } catch (Exception e) {
-            Log.e(TAG, "Stopping the application failed.", e);
-            return false;
-        }
-        onMessage("remove_session", "\"" + mSessionId + "\"");
-        return true;
-    }
-
     public void updateSessionStatus() {
         if (mApiClient == null || (!mApiClient.isConnected() && !mApiClient.isConnecting())) return;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java
index cea35b8f..59694ea7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageToolbar.java
@@ -6,27 +6,22 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.Gravity;
 import android.view.View;
-import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.widget.TintedDrawable;
-import org.chromium.ui.widget.Toast;
 
 /**
  * The toolbar at the bottom of the new tab page. Contains buttons to open the bookmarks and
  * recent tabs pages.
  */
-public class NewTabPageToolbar extends LinearLayout implements OnLongClickListener {
+public class NewTabPageToolbar extends LinearLayout {
 
     private View mBookmarksButton, mRecentTabsButton;
-    private Toast mToast;
 
     /**
      * Constructor for inflating from xml.
@@ -59,28 +54,4 @@
 
         return button;
     }
-
-    @Override
-    public boolean onLongClick(View v) {
-        // Display tooltip on long click
-        if (v == mBookmarksButton) {
-            showTooltip(OfflinePageBridge.isEnabled()
-                    ? R.string.offline_pages_ntp_button_name : R.string.ntp_bookmarks);
-        } else if (v == mRecentTabsButton) {
-            showTooltip(R.string.recent_tabs);
-        }
-        return true;
-    }
-
-    /**
-     * Shows a tooltip for a button. If a tooltip is already showing, it will be hidden.
-     * @param stringId The string resource ID of the tooltip to be shown.
-     */
-    private void showTooltip(int stringId) {
-        if (mToast != null) mToast.cancel();
-        Context ctx = getContext();
-        mToast = Toast.makeText(ctx, ctx.getResources().getString(stringId), Toast.LENGTH_SHORT);
-        mToast.setGravity(Gravity.BOTTOM | Gravity.CENTER, 0, getHeight());
-        mToast.show();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index 4c50d77..ad4f27c8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -146,6 +146,7 @@
 
             @Override
             public void onDismissNoAction(Object actionData) {
+                if (actionData == null) return;
                 SnackbarButtonType buttonType = (SnackbarButtonType) actionData;
                 switch (buttonType) {
                     case NONE:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillPreferences.java
index 8fc69100..0602f73 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillPreferences.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.preferences.autofill;
 
 import android.app.Activity;
+import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -181,9 +182,17 @@
         PersonalDataManager.getInstance().unregisterDataObserver(this);
     }
 
+    // TODO: remove this than we only support Build.VERSION_CODES.M and newer.
+    @SuppressWarnings("deprecation")
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         PersonalDataManager.getInstance().registerDataObserver(this);
     }
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        PersonalDataManager.getInstance().registerDataObserver(this);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java
index 1df39700..b2e7241 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionPromoScreen.java
@@ -143,12 +143,24 @@
         super.dismiss();
     }
 
-    private static boolean getDisplayedDataReductionPromo(Context context) {
+    /**
+     * Returns whether the Data Reduction Proxy promo has been displayed before.
+     *
+     * @param context An Android context.
+     * @return Whether the Data Reduction Proxy promo has been displayed.
+     */
+    public static boolean getDisplayedDataReductionPromo(Context context) {
         return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
                 SHARED_PREF_DISPLAYED_PROMO, false);
     }
 
-    private static void setDisplayedDataReductionPromo(Context context, boolean displayed) {
+    /**
+     * Sets whether the Data Reduction Proxy promo has been displayed.
+     *
+     * @param context An Android context.
+     * @param displayed Whether the Data Reduction Proxy was displayed.
+     */
+    public static void setDisplayedDataReductionPromo(Context context, boolean displayed) {
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putBoolean(SHARED_PREF_DISPLAYED_PROMO, displayed)
                 .apply();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionProxyUma.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionProxyUma.java
index 00ccb1a8..aeafecb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionProxyUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionProxyUma.java
@@ -21,7 +21,9 @@
     public static final int ACTION_OFF_TO_ON = 6;
     public static final int ACTION_ON_TO_OFF = 7;
     public static final int ACTION_ON_TO_ON = 8;
-    public static final int ACTION_INDEX_BOUNDARY = 9;
+    public static final int ACTION_FRE_ENABLED = 9;
+    public static final int ACTION_FRE_DISABLED = 10;
+    public static final int ACTION_INDEX_BOUNDARY = 11;
 
     // Represent the possible Lo-Fi user actions. This must remain in sync with
     // DataReductionProxy.UIAction.LoFi in tools/metrics/histograms/histograms.xml.
@@ -36,7 +38,7 @@
 
     /**
      * Record the DataReductionProxy.UIAction histogram.
-     * @param action User action at the promo or settings screen
+     * @param action User action at the promo, first run experience, or settings screen
      */
     public static void dataReductionProxyUIAction(int action) {
         assert action >= 0 && action < ACTION_INDEX_BOUNDARY;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarPopupWindow.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarPopupWindow.java
index 124b79c..e8452d7a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarPopupWindow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarPopupWindow.java
@@ -45,8 +45,7 @@
                 ? parent.getResources().getDimensionPixelSize(R.dimen.snackbar_tablet_width)
                 : parent.getWidth());
 
-        setWindowLayoutMode(0, ViewGroup.LayoutParams.WRAP_CONTENT);
-
+        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
         update(snackbar, false);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java
index 9b1091bf..55aef684 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/ChromeTab.java
@@ -17,12 +17,10 @@
 import org.chromium.chrome.browser.dom_distiller.ReaderModeActivityDelegate;
 import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
-import org.chromium.chrome.browser.media.MediaCaptureNotificationService;
 import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper;
 import org.chromium.chrome.browser.ntp.NativePageAssassin;
 import org.chromium.chrome.browser.ntp.NativePageFactory;
 import org.chromium.chrome.browser.policy.PolicyAuditor;
-import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent;
 import org.chromium.chrome.browser.rlz.RevenueStats;
 import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
@@ -32,7 +30,6 @@
 import org.chromium.content.browser.crypto.CipherFactory;
 import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.WindowAndroid;
@@ -44,11 +41,6 @@
 public class ChromeTab extends Tab {
     public static final int NTP_TAB_ID = -2;
 
-    private static final String TAG = "cr.ChromeTab";
-
-    // URL didFailLoad error code. Should match the value in net_error_list.h.
-    public static final int BLOCKED_BY_ADMINISTRATOR = -22;
-
     /** The maximum amount of time to wait for a page to load before entering fullscreen.  -1 means
      *  wait until the page finishes loading. */
     private static final long MAX_FULLSCREEN_LOAD_DELAY_MS = 3000;
@@ -178,73 +170,6 @@
         return (ChromeTab) tab;
     }
 
-    private WebContentsObserver createWebContentsObserver(WebContents webContents) {
-        return new WebContentsObserver(webContents) {
-            @Override
-            public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
-                PolicyAuditor auditor =
-                        ((ChromeApplication) getApplicationContext()).getPolicyAuditor();
-                auditor.notifyAuditEvent(
-                        getApplicationContext(), AuditEvent.OPEN_URL_SUCCESS, validatedUrl, "");
-            }
-
-            @Override
-            public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
-                    String description, String failingUrl, boolean wasIgnoredByHandler) {
-                PolicyAuditor auditor =
-                        ((ChromeApplication) getApplicationContext()).getPolicyAuditor();
-                auditor.notifyAuditEvent(getApplicationContext(), AuditEvent.OPEN_URL_FAILURE,
-                        failingUrl, description);
-                if (errorCode == BLOCKED_BY_ADMINISTRATOR) {
-                    auditor.notifyAuditEvent(
-                            getApplicationContext(), AuditEvent.OPEN_URL_BLOCKED, failingUrl, "");
-                }
-            }
-
-            @Override
-            public void didCommitProvisionalLoadForFrame(
-                    long frameId, boolean isMainFrame, String url, int transitionType) {
-                if (!isMainFrame) return;
-
-                mIsNativePageCommitPending = false;
-                boolean isReload = (transitionType == PageTransition.RELOAD);
-                if (!maybeShowNativePage(url, isReload)) {
-                    showRenderedPage();
-                }
-
-                mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
-                mHandler.sendEmptyMessageDelayed(
-                        MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS);
-                updateFullscreenEnabledState();
-
-                if (getInterceptNavigationDelegate() != null) {
-                    getInterceptNavigationDelegate().maybeUpdateNavigationHistory();
-                }
-            }
-
-            @Override
-            public void didAttachInterstitialPage() {
-                PolicyAuditor auditor =
-                        ((ChromeApplication) getApplicationContext()).getPolicyAuditor();
-                auditor.notifyCertificateFailure(getWebContents(), getApplicationContext());
-            }
-
-            @Override
-            public void didDetachInterstitialPage() {
-                if (!maybeShowNativePage(getUrl(), false)) {
-                    showRenderedPage();
-                }
-            }
-
-            @Override
-            public void destroy() {
-                MediaCaptureNotificationService.updateMediaNotificationForTab(
-                        getApplicationContext(), getId(), false, false, getUrl());
-                super.destroy();
-            }
-        };
-    }
-
     @Override
     protected void didStartPageLoad(String validatedUrl, boolean showingErrorPage) {
         mIsFullscreenWaitingForLoad = !DomDistillerUrlUtils.isDistilledPage(validatedUrl);
@@ -310,7 +235,7 @@
         try {
             TraceEvent.begin("ChromeTab.setContentViewCore");
             super.setContentViewCore(cvc);
-            mWebContentsObserver = createWebContentsObserver(cvc.getWebContents());
+            mWebContentsObserver = new TabWebContentsObserver(cvc.getWebContents(), this);
 
             setInterceptNavigationDelegate(createInterceptNavigationDelegate());
 
@@ -482,7 +407,7 @@
      * @param isReload Whether the current navigation is a reload.
      * @return True, if a native page was displayed for url.
      */
-    private boolean maybeShowNativePage(String url, boolean isReload) {
+    boolean maybeShowNativePage(String url, boolean isReload) {
         NativePage candidateForReuse = isReload ? null : getNativePage();
         NativePage nativePage = NativePageFactory.createNativePageForURL(url, candidateForReuse,
                 this, mActivity.getTabModelSelector(), mActivity);
@@ -495,6 +420,24 @@
         return false;
     }
 
+    /**
+     * Update internal Tab state when provisional load gets committed.
+     * @param url The URL that was loaded.
+     * @param transitionType The transition type to the current URL.
+     */
+    void handleDidCommitProvisonalLoadForFrame(String url, int transitionType) {
+        mIsNativePageCommitPending = false;
+        boolean isReload = (transitionType == PageTransition.RELOAD);
+        if (!maybeShowNativePage(url, isReload)) {
+            showRenderedPage();
+        }
+
+        mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD);
+        mHandler.sendEmptyMessageDelayed(
+                MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, MAX_FULLSCREEN_LOAD_DELAY_MS);
+        updateFullscreenEnabledState();
+    }
+
     // TODO(dtrainor): Port more methods to the observer.
     private final TabObserver mTabObserver = new EmptyTabObserver() {
         @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 71261bd..65bb523 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -4,25 +4,18 @@
 
 package org.chromium.chrome.browser.tab;
 
-import android.annotation.TargetApi;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
-import android.graphics.Rect;
-import android.media.AudioManager;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.provider.Browser;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 import android.view.ContextMenu;
-import android.view.KeyEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
@@ -44,14 +37,12 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AccessibilityUtil;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.ChromeWebContentsDelegateAndroid;
 import org.chromium.chrome.browser.FrozenNativePage;
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
 import org.chromium.chrome.browser.NativePage;
-import org.chromium.chrome.browser.RepostFormWarningDialog;
 import org.chromium.chrome.browser.SwipeRefreshHandler;
 import org.chromium.chrome.browser.TabState;
 import org.chromium.chrome.browser.TabState.WebContentsState;
@@ -67,19 +58,14 @@
 import org.chromium.chrome.browser.crash.MinidumpUploadService;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.device.DeviceClassManager;
-import org.chromium.chrome.browser.document.DocumentUtils;
-import org.chromium.chrome.browser.document.DocumentWebContentsDelegate;
 import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
-import org.chromium.chrome.browser.media.MediaCaptureNotificationService;
 import org.chromium.chrome.browser.metrics.UmaSessionStats;
 import org.chromium.chrome.browser.metrics.UmaUtils;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader;
-import org.chromium.chrome.browser.policy.PolicyAuditor;
-import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.printing.TabPrinter;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -88,13 +74,10 @@
 import org.chromium.chrome.browser.ssl.ConnectionSecurityLevel;
 import org.chromium.chrome.browser.ssl.SecurityStateModel;
 import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
-import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator;
-import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
 import org.chromium.chrome.browser.tabmodel.TabModelImpl;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.content.browser.ActivityContentVideoViewClient;
@@ -102,7 +85,6 @@
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.ContentViewClient;
 import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content_public.browser.InvalidateTypes;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
@@ -386,34 +368,6 @@
 
     protected Handler mHandler;
 
-    private final Runnable mCloseContentsRunnable = new Runnable() {
-        @Override
-        public void run() {
-            boolean isSelected = mActivity.getTabModelSelector().getCurrentTab() == Tab.this;
-            mActivity.getTabModelSelector().closeTab(Tab.this);
-
-            // If the parent Tab belongs to another Activity, fire the Intent to bring it back.
-            if (isSelected && getParentIntent() != null
-                    && mActivity.getIntent() != getParentIntent()) {
-                boolean mayLaunch = FeatureUtilities.isDocumentMode(mActivity)
-                        ? isParentInAndroidOverview() : true;
-                if (mayLaunch) mActivity.startActivity(getParentIntent());
-            }
-        }
-
-        /** If the API allows it, returns whether a Task still exists for the parent Activity. */
-        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-        private boolean isParentInAndroidOverview() {
-            ActivityManager activityManager =
-                    (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE);
-            for (ActivityManager.AppTask task : activityManager.getAppTasks()) {
-                Intent taskIntent = DocumentUtils.getBaseIntentFromTask(task);
-                if (taskIntent != null && taskIntent.filterEquals(getParentIntent())) return true;
-            }
-            return false;
-        }
-    };
-
     /**
      * A default {@link ChromeContextMenuItemDelegate} that supports some of the context menu
      * functionality.
@@ -521,317 +475,7 @@
         }
     }
 
-    /**
-     * A basic {@link ChromeWebContentsDelegateAndroid} that forwards some calls to the registered
-     * {@link TabObserver}s.  Meant to be overridden by subclasses.
-     */
-    public class TabChromeWebContentsDelegateAndroid
-            extends ChromeWebContentsDelegateAndroid {
-        @Override
-        public void onLoadProgressChanged(int progress) {
-            if (!isLoading()) return;
-            notifyLoadProgress(getProgress());
-        }
 
-        @Override
-        public void onLoadStarted() {
-            for (TabObserver observer : mObservers) observer.onLoadStarted(Tab.this);
-        }
-
-        @Override
-        public void onLoadStopped() {
-            for (TabObserver observer : mObservers) observer.onLoadStopped(Tab.this);
-        }
-
-        @Override
-        public void onUpdateUrl(String url) {
-            for (TabObserver observer : mObservers) observer.onUpdateUrl(Tab.this, url);
-        }
-
-        @Override
-        public void showRepostFormWarningDialog() {
-            // When the dialog is visible, keeping the refresh animation active
-            // in the background is distracting and unnecessary (and likely to
-            // jank when the dialog is shown).
-            if (mSwipeRefreshHandler != null) {
-                mSwipeRefreshHandler.reset();
-            }
-            RepostFormWarningDialog warningDialog = new RepostFormWarningDialog(
-                    new Runnable() {
-                        @Override
-                        public void run() {
-                            getWebContents().getNavigationController().cancelPendingReload();
-                        }
-                    }, new Runnable() {
-                        @Override
-                        public void run() {
-                            getWebContents().getNavigationController().continuePendingReload();
-                        }
-                    });
-            warningDialog.show(mActivity.getFragmentManager(), null);
-        }
-
-        @Override
-        public void toggleFullscreenModeForTab(boolean enableFullscreen) {
-            if (mFullscreenManager != null) {
-                mFullscreenManager.setPersistentFullscreenMode(enableFullscreen);
-            }
-
-            for (TabObserver observer : mObservers) {
-                observer.onToggleFullscreenMode(Tab.this, enableFullscreen);
-            }
-        }
-
-        @Override
-        public void navigationStateChanged(int flags) {
-            if ((flags & InvalidateTypes.TAB) != 0) {
-                MediaCaptureNotificationService.updateMediaNotificationForTab(
-                        getApplicationContext(), getId(), isCapturingAudio(),
-                        isCapturingVideo(), getUrl());
-            }
-            if ((flags & InvalidateTypes.TITLE) != 0) {
-                // Update cached title then notify observers.
-                updateTitle();
-            }
-            if ((flags & InvalidateTypes.URL) != 0) {
-                for (TabObserver observer : mObservers) observer.onUrlUpdated(Tab.this);
-            }
-        }
-
-        @Override
-        public void visibleSSLStateChanged() {
-            for (TabObserver observer : mObservers) observer.onSSLStateUpdated(Tab.this);
-        }
-
-        @Override
-        public void webContentsCreated(WebContents sourceWebContents, long openerRenderFrameId,
-                String frameName, String targetUrl, WebContents newWebContents) {
-            for (TabObserver observer : mObservers) {
-                observer.webContentsCreated(Tab.this, sourceWebContents, openerRenderFrameId,
-                        frameName, targetUrl, newWebContents);
-            }
-            // The URL can't be taken from the WebContents if it's paused.  Save it for later.
-            assert mWebContentsUrlMapping == null;
-            mWebContentsUrlMapping = Pair.create(newWebContents, targetUrl);
-
-            // TODO(dfalcantara): Re-remove this once crbug.com/508366 is fixed.
-            TabCreator tabCreator = mActivity.getTabCreator(isIncognito());
-
-            if (tabCreator != null && tabCreator.createsTabsAsynchronously()) {
-                DocumentWebContentsDelegate.getInstance().attachDelegate(newWebContents);
-            }
-        }
-
-        @Override
-        public void rendererUnresponsive() {
-            super.rendererUnresponsive();
-            if (mNativeTabAndroid != 0) nativeOnRendererUnresponsive(mNativeTabAndroid);
-            if (mFullscreenManager == null) return;
-            mFullscreenHungRendererToken =
-                    mFullscreenManager.showControlsPersistentAndClearOldToken(
-                            mFullscreenHungRendererToken);
-        }
-
-        @Override
-        public void rendererResponsive() {
-            super.rendererResponsive();
-            if (mNativeTabAndroid != 0) nativeOnRendererResponsive(mNativeTabAndroid);
-            if (mFullscreenManager == null) return;
-            mFullscreenManager.hideControlsPersistent(mFullscreenHungRendererToken);
-            mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN;
-        }
-
-        @Override
-        public boolean isFullscreenForTabOrPending() {
-            return mFullscreenManager == null
-                    ? false : mFullscreenManager.getPersistentFullscreenMode();
-        }
-
-        @Override
-        public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition,
-                boolean isRendererInitiated) {
-            Tab.this.openNewTab(
-                    url, extraHeaders, postData, disposition, true, isRendererInitiated);
-        }
-
-        private Pair<WebContents, String> mWebContentsUrlMapping;
-
-        protected TabModel getTabModel() {
-            // TODO(dfalcantara): Remove this when DocumentActivity.getTabModelSelector()
-            //                    can return a TabModelSelector that activateContents() can use.
-            return mActivity.getTabModelSelector().getModel(isIncognito());
-        }
-
-        @Override
-        public boolean shouldResumeRequestsForCreatedWindow() {
-            // Pause the WebContents if an Activity has to be created for it first.
-            TabCreator tabCreator = mActivity.getTabCreator(isIncognito());
-            assert tabCreator != null;
-            return !tabCreator.createsTabsAsynchronously();
-        }
-
-        @Override
-        public boolean addNewContents(WebContents sourceWebContents, WebContents webContents,
-                int disposition, Rect initialPosition, boolean userGesture) {
-            assert mWebContentsUrlMapping.first == webContents;
-
-            TabCreator tabCreator = mActivity.getTabCreator(isIncognito());
-            assert tabCreator != null;
-
-            // Grab the URL, which might not be available via the Tab.
-            String url = mWebContentsUrlMapping.second;
-            mWebContentsUrlMapping = null;
-
-            // Skip opening a new Tab if it doesn't make sense.
-            if (isClosing()) return false;
-
-            // Creating new Tabs asynchronously requires starting a new Activity to create the Tab,
-            // so the Tab returned will always be null.  There's no way to know synchronously
-            // whether the Tab is created, so assume it's always successful.
-            boolean createdSuccessfully = tabCreator.createTabWithWebContents(
-                    webContents, getId(), TabLaunchType.FROM_LONGPRESS_FOREGROUND, url);
-            boolean success = tabCreator.createsTabsAsynchronously() || createdSuccessfully;
-            if (success && disposition == WindowOpenDisposition.NEW_POPUP) {
-                PolicyAuditor auditor =
-                        ((ChromeApplication) getApplicationContext()).getPolicyAuditor();
-                auditor.notifyAuditEvent(getApplicationContext(), AuditEvent.OPEN_POPUP_URL_SUCCESS,
-                        url, "");
-            }
-
-            return success;
-        }
-
-        @Override
-        public void activateContents() {
-            boolean activityIsDestroyed = false;
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                activityIsDestroyed = mActivity.isDestroyed();
-            }
-            if (activityIsDestroyed || !isInitialized()) {
-                Log.e(TAG, "Activity destroyed before calling activateContents().  Bailing out.");
-                return;
-            }
-
-            TabModel model = getTabModel();
-            int index = model.indexOf(Tab.this);
-            if (index == TabModel.INVALID_TAB_INDEX) return;
-            TabModelUtils.setIndex(model, index);
-            bringActivityToForeground();
-        }
-
-        /**
-         * Brings chrome's Activity to foreground, if it is not so.
-         */
-        protected void bringActivityToForeground() {
-            // This intent is sent in order to get the activity back to the foreground if it was
-            // not already. The previous call will activate the right tab in the context of the
-            // TabModel but will only show the tab to the user if Chrome was already in the
-            // foreground.
-            // The intent is getting the tabId mostly because it does not cost much to do so.
-            // When receiving the intent, the tab associated with the tabId should already be
-            // active.
-            // Note that calling only the intent in order to activate the tab is slightly slower
-            // because it will change the tab when the intent is handled, which happens after
-            // Chrome gets back to the foreground.
-            Intent newIntent = Tab.createBringTabToFrontIntent(Tab.this.getId());
-            newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-            getApplicationContext().startActivity(newIntent);
-        }
-
-        @Override
-        public void closeContents() {
-            // Execute outside of callback, otherwise we end up deleting the native
-            // objects in the middle of executing methods on them.
-            mHandler.removeCallbacks(mCloseContentsRunnable);
-            mHandler.post(mCloseContentsRunnable);
-        }
-
-        @Override
-        public boolean takeFocus(boolean reverse) {
-            if (reverse) {
-                View menuButton = mActivity.findViewById(R.id.menu_button);
-                if (menuButton == null || !menuButton.isShown()) {
-                    menuButton = mActivity.findViewById(R.id.document_menu_button);
-                }
-                if (menuButton != null && menuButton.isShown()) {
-                    return menuButton.requestFocus();
-                }
-
-                View tabSwitcherButton = mActivity.findViewById(R.id.tab_switcher_button);
-                if (tabSwitcherButton != null && tabSwitcherButton.isShown()) {
-                    return tabSwitcherButton.requestFocus();
-                }
-            } else {
-                View urlBar = mActivity.findViewById(R.id.url_bar);
-                if (urlBar != null) return urlBar.requestFocus();
-            }
-            return false;
-        }
-
-        @Override
-        public void handleKeyboardEvent(KeyEvent event) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                if (mActivity.onKeyDown(event.getKeyCode(), event)) return;
-
-                // Handle the Escape key here (instead of in KeyboardShortcuts.java), so it doesn't
-                // interfere with other parts of the activity (e.g. the URL bar).
-                if (event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE && event.hasNoModifiers()) {
-                    WebContents wc = getWebContents();
-                    if (wc != null) wc.stop();
-                    return;
-                }
-            }
-            handleMediaKey(event);
-        }
-
-        /**
-         * Redispatches unhandled media keys. This allows bluetooth headphones with play/pause or
-         * other buttons to function correctly.
-         */
-        @TargetApi(19)
-        private void handleMediaKey(KeyEvent e) {
-            if (Build.VERSION.SDK_INT < 19) return;
-            switch (e.getKeyCode()) {
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                case KeyEvent.KEYCODE_MEDIA_CLOSE:
-                case KeyEvent.KEYCODE_MEDIA_EJECT:
-                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
-                    AudioManager am = (AudioManager) mActivity.getSystemService(
-                            Context.AUDIO_SERVICE);
-                    am.dispatchMediaKeyEvent(e);
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        /**
-         * @return Whether audio is being captured.
-         */
-        private boolean isCapturingAudio() {
-            return !isClosing()
-                    && ChromeWebContentsDelegateAndroid.nativeIsCapturingAudio(getWebContents());
-        }
-
-        /**
-         * @return Whether video is being captured.
-         */
-        private boolean isCapturingVideo() {
-            return !isClosing()
-                    && ChromeWebContentsDelegateAndroid.nativeIsCapturingVideo(getWebContents());
-        }
-    }
 
     private class TabContentViewClient extends ContentViewClient {
         @Override
@@ -2223,7 +1867,7 @@
         return mTitle;
     }
 
-    private void updateTitle() {
+    void updateTitle() {
         if (isFrozen()) return;
 
         // When restoring the tabs, the title will no longer be populated, so request it from the
@@ -2560,7 +2204,7 @@
      * @return An instance of a {@link TabChromeWebContentsDelegateAndroid}.
      */
     protected TabChromeWebContentsDelegateAndroid createWebContentsDelegate() {
-        return new TabChromeWebContentsDelegateAndroid();
+        return new TabChromeWebContentsDelegateAndroid(this, mActivity);
     }
 
     /**
@@ -3215,6 +2859,13 @@
     }
 
     /**
+     * @return The default toolbar color for this tab.
+     */
+    public int getDefaultThemeColor() {
+        return mDefaultThemeColor;
+    }
+
+    /**
      * @return Intent that tells Chrome to bring an Activity for a particular Tab back to the
      *         foreground, or null if this isn't possible.
      */
@@ -3254,6 +2905,28 @@
         return mDownloadDelegate.shouldInterceptContextMenuDownload(url);
     }
 
+    void handleRendererUnresponsive() {
+        if (mFullscreenManager == null) return;
+        mFullscreenHungRendererToken =
+                mFullscreenManager.showControlsPersistentAndClearOldToken(
+                        mFullscreenHungRendererToken);
+    }
+
+    void handleRendererResponsive() {
+        if (mFullscreenManager == null) return;
+        mFullscreenManager.hideControlsPersistent(mFullscreenHungRendererToken);
+        mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN;
+    }
+
+    void resetSwipeRefreshHandler() {
+        // When the dialog is visible, keeping the refresh animation active
+        // in the background is distracting and unnecessary (and likely to
+        // jank when the dialog is shown).
+        if (mSwipeRefreshHandler != null) {
+            mSwipeRefreshHandler.reset();
+        }
+    }
+
     /**
      * Checks if spdy proxy is enabled for input url.
      * @param url Input url to check for spdy setting.
@@ -3322,8 +2995,6 @@
     private native void nativeDetachOverlayContentViewCore(long nativeTabAndroid,
             ContentViewCore content);
     private native boolean nativeHasPrerenderedUrl(long nativeTabAndroid, String url);
-    private native void nativeOnRendererUnresponsive(long nativeTabAndroid);
-    private native void nativeOnRendererResponsive(long nativeTabAndroid);
 
     private static native void nativeRecordStartupToCommitUma();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabChromeWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabChromeWebContentsDelegateAndroid.java
new file mode 100644
index 0000000..f5706fc7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabChromeWebContentsDelegateAndroid.java
@@ -0,0 +1,399 @@
+// Copyright 2015 The Chromium 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.tab;
+
+import android.annotation.TargetApi;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.media.AudioManager;
+import android.os.Build;
+import android.os.Handler;
+import android.util.Pair;
+import android.view.KeyEvent;
+import android.view.View;
+
+import org.chromium.base.Log;
+import org.chromium.base.ObserverList.RewindableIterator;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeWebContentsDelegateAndroid;
+import org.chromium.chrome.browser.RepostFormWarningDialog;
+import org.chromium.chrome.browser.document.DocumentUtils;
+import org.chromium.chrome.browser.document.DocumentWebContentsDelegate;
+import org.chromium.chrome.browser.media.MediaCaptureNotificationService;
+import org.chromium.chrome.browser.policy.PolicyAuditor;
+import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.content_public.browser.InvalidateTypes;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.WindowOpenDisposition;
+
+/**
+ * A basic {@link ChromeWebContentsDelegateAndroid} that forwards some calls to the registered
+ * {@link TabObserver}s.
+ */
+public class TabChromeWebContentsDelegateAndroid
+        extends ChromeWebContentsDelegateAndroid {
+    /** Used for logging. */
+    private static final String TAG = "WebContentsDelegate";
+
+    private final Tab mTab;
+    private final ChromeActivity mActivity;
+
+    protected Handler mHandler;
+    private final Runnable mCloseContentsRunnable = new Runnable() {
+        @Override
+        public void run() {
+            boolean isSelected = mActivity.getTabModelSelector().getCurrentTab() == mTab;
+            mActivity.getTabModelSelector().closeTab(mTab);
+
+            // If the parent Tab belongs to another Activity, fire the Intent to bring it back.
+            if (isSelected && mTab.getParentIntent() != null
+                    && mActivity.getIntent() != mTab.getParentIntent()) {
+                boolean mayLaunch = FeatureUtilities.isDocumentMode(mActivity)
+                        ? isParentInAndroidOverview() : true;
+                if (mayLaunch) mActivity.startActivity(mTab.getParentIntent());
+            }
+        }
+
+        /** If the API allows it, returns whether a Task still exists for the parent Activity. */
+        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+        private boolean isParentInAndroidOverview() {
+            ActivityManager activityManager =
+                    (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE);
+            for (ActivityManager.AppTask task : activityManager.getAppTasks()) {
+                Intent taskIntent = DocumentUtils.getBaseIntentFromTask(task);
+                if (taskIntent != null && taskIntent.filterEquals(mTab.getParentIntent())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    public TabChromeWebContentsDelegateAndroid(Tab tab, ChromeActivity activity) {
+        mTab = tab;
+        mActivity = activity;
+        mHandler = new Handler();
+    }
+
+    @Override
+    public void onLoadProgressChanged(int progress) {
+        if (!mTab.isLoading()) return;
+        mTab.notifyLoadProgress(mTab.getProgress());
+    }
+
+    @Override
+    public void onLoadStarted() {
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().onLoadStarted(mTab);
+        }
+    }
+
+    @Override
+    public void onLoadStopped() {
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().onLoadStopped(mTab);
+        }
+    }
+
+    @Override
+    public void onUpdateUrl(String url) {
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().onUpdateUrl(mTab, url);
+        }
+    }
+
+    @Override
+    public void showRepostFormWarningDialog() {
+        mTab.resetSwipeRefreshHandler();
+        RepostFormWarningDialog warningDialog = new RepostFormWarningDialog(
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        mTab.getWebContents().getNavigationController().cancelPendingReload();
+                    }
+                }, new Runnable() {
+                    @Override
+                    public void run() {
+                        mTab.getWebContents().getNavigationController().continuePendingReload();
+                    }
+                });
+        warningDialog.show(mActivity.getFragmentManager(), null);
+    }
+
+    @Override
+    public void toggleFullscreenModeForTab(boolean enableFullscreen) {
+        if (mTab.getFullscreenManager() != null) {
+            mTab.getFullscreenManager().setPersistentFullscreenMode(enableFullscreen);
+        }
+
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().onToggleFullscreenMode(mTab, enableFullscreen);
+        }
+    }
+
+    @Override
+    public void navigationStateChanged(int flags) {
+        if ((flags & InvalidateTypes.TAB) != 0) {
+            MediaCaptureNotificationService.updateMediaNotificationForTab(
+                    mTab.getApplicationContext(), mTab.getId(), isCapturingAudio(),
+                    isCapturingVideo(), mTab.getUrl());
+        }
+        if ((flags & InvalidateTypes.TITLE) != 0) {
+            // Update cached title then notify observers.
+            mTab.updateTitle();
+        }
+        if ((flags & InvalidateTypes.URL) != 0) {
+            RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+            while (observers.hasNext()) {
+                observers.next().onUrlUpdated(mTab);
+            }
+        }
+    }
+
+    @Override
+    public void visibleSSLStateChanged() {
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().onSSLStateUpdated(mTab);
+        }
+    }
+
+    @Override
+    public void webContentsCreated(WebContents sourceWebContents, long openerRenderFrameId,
+            String frameName, String targetUrl, WebContents newWebContents) {
+        RewindableIterator<TabObserver> observers = mTab.getTabObservers();
+        while (observers.hasNext()) {
+            observers.next().webContentsCreated(mTab, sourceWebContents, openerRenderFrameId,
+                    frameName, targetUrl, newWebContents);
+        }
+        // The URL can't be taken from the WebContents if it's paused.  Save it for later.
+        assert mWebContentsUrlMapping == null;
+        mWebContentsUrlMapping = Pair.create(newWebContents, targetUrl);
+
+        // TODO(dfalcantara): Re-remove this once crbug.com/508366 is fixed.
+        TabCreator tabCreator = mActivity.getTabCreator(mTab.isIncognito());
+
+        if (tabCreator != null && tabCreator.createsTabsAsynchronously()) {
+            DocumentWebContentsDelegate.getInstance().attachDelegate(newWebContents);
+        }
+    }
+
+    @Override
+    public void rendererUnresponsive() {
+        super.rendererUnresponsive();
+        if (mTab.getWebContents() != null) nativeOnRendererUnresponsive(mTab.getWebContents());
+        mTab.handleRendererUnresponsive();
+    }
+
+    @Override
+    public void rendererResponsive() {
+        super.rendererResponsive();
+        if (mTab.getWebContents() != null) nativeOnRendererResponsive(mTab.getWebContents());
+        mTab.handleRendererResponsive();
+    }
+
+    @Override
+    public boolean isFullscreenForTabOrPending() {
+        return mTab.getFullscreenManager() == null
+                ? false : mTab.getFullscreenManager().getPersistentFullscreenMode();
+    }
+
+    @Override
+    public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition,
+            boolean isRendererInitiated) {
+        mTab.openNewTab(url, extraHeaders, postData, disposition, true, isRendererInitiated);
+    }
+
+    private Pair<WebContents, String> mWebContentsUrlMapping;
+
+    protected TabModel getTabModel() {
+        // TODO(dfalcantara): Remove this when DocumentActivity.getTabModelSelector()
+        //                    can return a TabModelSelector that activateContents() can use.
+        return mActivity.getTabModelSelector().getModel(mTab.isIncognito());
+    }
+
+    @Override
+    public boolean shouldResumeRequestsForCreatedWindow() {
+        // Pause the WebContents if an Activity has to be created for it first.
+        TabCreator tabCreator = mActivity.getTabCreator(mTab.isIncognito());
+        assert tabCreator != null;
+        return !tabCreator.createsTabsAsynchronously();
+    }
+
+    @Override
+    public boolean addNewContents(WebContents sourceWebContents, WebContents webContents,
+            int disposition, Rect initialPosition, boolean userGesture) {
+        assert mWebContentsUrlMapping.first == webContents;
+
+        TabCreator tabCreator = mActivity.getTabCreator(mTab.isIncognito());
+        assert tabCreator != null;
+
+        // Grab the URL, which might not be available via the Tab.
+        String url = mWebContentsUrlMapping.second;
+        mWebContentsUrlMapping = null;
+
+        // Skip opening a new Tab if it doesn't make sense.
+        if (mTab.isClosing()) return false;
+
+        // Creating new Tabs asynchronously requires starting a new Activity to create the Tab,
+        // so the Tab returned will always be null.  There's no way to know synchronously
+        // whether the Tab is created, so assume it's always successful.
+        boolean createdSuccessfully = tabCreator.createTabWithWebContents(
+                webContents, mTab.getId(), TabLaunchType.FROM_LONGPRESS_FOREGROUND, url);
+        boolean success = tabCreator.createsTabsAsynchronously() || createdSuccessfully;
+        if (success && disposition == WindowOpenDisposition.NEW_POPUP) {
+            PolicyAuditor auditor =
+                    ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor();
+            auditor.notifyAuditEvent(mTab.getApplicationContext(),
+                    AuditEvent.OPEN_POPUP_URL_SUCCESS, url, "");
+        }
+
+        return success;
+    }
+
+    @Override
+    public void activateContents() {
+        boolean activityIsDestroyed = false;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            activityIsDestroyed = mActivity.isDestroyed();
+        }
+        if (activityIsDestroyed || !mTab.isInitialized()) {
+            Log.e(TAG, "Activity destroyed before calling activateContents().  Bailing out.");
+            return;
+        }
+
+        TabModel model = getTabModel();
+        int index = model.indexOf(mTab);
+        if (index == TabModel.INVALID_TAB_INDEX) return;
+        TabModelUtils.setIndex(model, index);
+        bringActivityToForeground();
+    }
+
+    /**
+     * Brings chrome's Activity to foreground, if it is not so.
+     */
+    protected void bringActivityToForeground() {
+        // This intent is sent in order to get the activity back to the foreground if it was
+        // not already. The previous call will activate the right tab in the context of the
+        // TabModel but will only show the tab to the user if Chrome was already in the
+        // foreground.
+        // The intent is getting the tabId mostly because it does not cost much to do so.
+        // When receiving the intent, the tab associated with the tabId should already be
+        // active.
+        // Note that calling only the intent in order to activate the tab is slightly slower
+        // because it will change the tab when the intent is handled, which happens after
+        // Chrome gets back to the foreground.
+        Intent newIntent = Tab.createBringTabToFrontIntent(mTab.getId());
+        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        mTab.getApplicationContext().startActivity(newIntent);
+    }
+
+    @Override
+    public void closeContents() {
+        // Execute outside of callback, otherwise we end up deleting the native
+        // objects in the middle of executing methods on them.
+        mHandler.removeCallbacks(mCloseContentsRunnable);
+        mHandler.post(mCloseContentsRunnable);
+    }
+
+    @Override
+    public boolean takeFocus(boolean reverse) {
+        if (reverse) {
+            View menuButton = mActivity.findViewById(R.id.menu_button);
+            if (menuButton == null || !menuButton.isShown()) {
+                menuButton = mActivity.findViewById(R.id.document_menu_button);
+            }
+            if (menuButton != null && menuButton.isShown()) {
+                return menuButton.requestFocus();
+            }
+
+            View tabSwitcherButton = mActivity.findViewById(R.id.tab_switcher_button);
+            if (tabSwitcherButton != null && tabSwitcherButton.isShown()) {
+                return tabSwitcherButton.requestFocus();
+            }
+        } else {
+            View urlBar = mActivity.findViewById(R.id.url_bar);
+            if (urlBar != null) return urlBar.requestFocus();
+        }
+        return false;
+    }
+
+    @Override
+    public void handleKeyboardEvent(KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (mActivity.onKeyDown(event.getKeyCode(), event)) return;
+
+            // Handle the Escape key here (instead of in KeyboardShortcuts.java), so it doesn't
+            // interfere with other parts of the activity (e.g. the URL bar).
+            if (event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE && event.hasNoModifiers()) {
+                WebContents wc = mTab.getWebContents();
+                if (wc != null) wc.stop();
+                return;
+            }
+        }
+        handleMediaKey(event);
+    }
+
+    /**
+     * Redispatches unhandled media keys. This allows bluetooth headphones with play/pause or
+     * other buttons to function correctly.
+     */
+    @TargetApi(19)
+    private void handleMediaKey(KeyEvent e) {
+        if (Build.VERSION.SDK_INT < 19) return;
+        switch (e.getKeyCode()) {
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+            case KeyEvent.KEYCODE_MEDIA_CLOSE:
+            case KeyEvent.KEYCODE_MEDIA_EJECT:
+            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
+                AudioManager am = (AudioManager) mActivity.getSystemService(
+                        Context.AUDIO_SERVICE);
+                am.dispatchMediaKeyEvent(e);
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * @return Whether audio is being captured.
+     */
+    private boolean isCapturingAudio() {
+        return !mTab.isClosing()
+                && ChromeWebContentsDelegateAndroid.nativeIsCapturingAudio(mTab.getWebContents());
+    }
+
+    /**
+     * @return Whether video is being captured.
+     */
+    private boolean isCapturingVideo() {
+        return !mTab.isClosing()
+                && ChromeWebContentsDelegateAndroid.nativeIsCapturingVideo(mTab.getWebContents());
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
new file mode 100644
index 0000000..97291eb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -0,0 +1,80 @@
+// Copyright 2015 The Chromium 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.tab;
+
+import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.media.MediaCaptureNotificationService;
+import org.chromium.chrome.browser.policy.PolicyAuditor;
+import org.chromium.chrome.browser.policy.PolicyAuditor.AuditEvent;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.WebContentsObserver;
+
+/**
+ * WebContentsObserver used by Tab.
+ */
+public class TabWebContentsObserver extends WebContentsObserver {
+    // URL didFailLoad error code. Should match the value in net_error_list.h.
+    public static final int BLOCKED_BY_ADMINISTRATOR = -22;
+
+    private final ChromeTab mTab;
+
+    public TabWebContentsObserver(WebContents webContents, ChromeTab tab) {
+        super(webContents);
+        mTab = tab;
+    }
+
+    @Override
+    public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
+        PolicyAuditor auditor =
+                ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor();
+        auditor.notifyAuditEvent(
+                mTab.getApplicationContext(), AuditEvent.OPEN_URL_SUCCESS, validatedUrl, "");
+    }
+
+    @Override
+    public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
+            String description, String failingUrl, boolean wasIgnoredByHandler) {
+        PolicyAuditor auditor =
+                ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor();
+        auditor.notifyAuditEvent(mTab.getApplicationContext(), AuditEvent.OPEN_URL_FAILURE,
+                failingUrl, description);
+        if (errorCode == BLOCKED_BY_ADMINISTRATOR) {
+            auditor.notifyAuditEvent(
+                    mTab.getApplicationContext(), AuditEvent.OPEN_URL_BLOCKED, failingUrl, "");
+        }
+    }
+
+    @Override
+    public void didCommitProvisionalLoadForFrame(
+            long frameId, boolean isMainFrame, String url, int transitionType) {
+        if (!isMainFrame) return;
+        mTab.handleDidCommitProvisonalLoadForFrame(url, transitionType);
+
+        if (mTab.getInterceptNavigationDelegate() != null) {
+            mTab.getInterceptNavigationDelegate().maybeUpdateNavigationHistory();
+        }
+    }
+
+    @Override
+    public void didAttachInterstitialPage() {
+        PolicyAuditor auditor =
+                ((ChromeApplication) mTab.getApplicationContext()).getPolicyAuditor();
+        auditor.notifyCertificateFailure(mTab.getWebContents(), mTab.getApplicationContext());
+    }
+
+    @Override
+    public void didDetachInterstitialPage() {
+        if (!mTab.maybeShowNativePage(mTab.getUrl(), false)) {
+            mTab.showRenderedPage();
+        }
+    }
+
+    @Override
+    public void destroy() {
+        MediaCaptureNotificationService.updateMediaNotificationForTab(
+                mTab.getApplicationContext(), mTab.getId(), false, false, mTab.getUrl());
+        super.destroy();
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
index 70f4f1a..fff33700 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -7,7 +7,6 @@
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.drawable.ColorDrawable;
@@ -303,15 +302,14 @@
     }
 
     private void updateButtonsTint() {
-        Resources resources = getResources();
-        ColorStateList colorStateList = ApiCompatibilityUtils.getColorStateList(resources,
-                mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint);
-        mMenuButton.setTint(colorStateList);
+        mMenuButton.setTint(mUseDarkColors ? mDarkModeTint : mLightModeTint);
         if (mCloseButton.getDrawable() instanceof TintedDrawable) {
-            ((TintedDrawable) mCloseButton.getDrawable()).setTint(colorStateList);
+            ((TintedDrawable) mCloseButton.getDrawable()).setTint(
+                    mUseDarkColors ? mDarkModeTint : mLightModeTint);
         }
         if (mCustomActionButton.getDrawable() instanceof TintedDrawable) {
-            ((TintedDrawable) mCustomActionButton.getDrawable()).setTint(colorStateList);
+            ((TintedDrawable) mCustomActionButton.getDrawable()).setTint(
+                    mUseDarkColors ? mDarkModeTint : mLightModeTint);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index 6f5ec3c..fd84aa5b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -6,6 +6,7 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -18,6 +19,7 @@
 import android.widget.FrameLayout;
 import android.widget.ProgressBar;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.compositor.Invalidator;
@@ -48,6 +50,9 @@
     protected TintedImageButton mMenuButton;
     private AppMenuButtonHelper mAppMenuButtonHelper;
 
+    protected final ColorStateList mDarkModeTint;
+    protected final ColorStateList mLightModeTint;
+
     private ToolbarDataProvider mToolbarDataProvider;
     private ToolbarTabController mToolbarTabController;
     private ToolbarProgressBar mProgressBar;
@@ -68,6 +73,10 @@
         super(context, attrs);
         mToolbarHeightWithoutShadow = getResources().getDimensionPixelOffset(
                 getToolbarHeightWithoutShadowResId());
+        mDarkModeTint =
+                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
+        mLightModeTint =
+                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.light_mode_tint);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index 6f30cce..85e1654 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -12,7 +12,6 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -166,6 +165,9 @@
     private TabSwitcherDrawable mTabSwitcherButtonDrawable;
     private TabSwitcherDrawable mTabSwitcherButtonDrawableLight;
 
+    private final int mLightModeDefaultColor;
+    private final int mDarkModeDefaultColor;
+
     private final Rect mUrlViewportBounds = new Rect();
     private final Rect mUrlBackgroundPadding = new Rect();
     private final Rect mBackgroundOverlayBounds = new Rect();
@@ -246,6 +248,10 @@
                 ApiCompatibilityUtils.getColor(getResources(), R.color.progress_bar_background);
         mProgressBackBackgroundColorWhite = ApiCompatibilityUtils.getColor(getResources(),
                 R.color.progress_bar_background_white);
+        mLightModeDefaultColor =
+                ApiCompatibilityUtils.getColor(getResources(), R.color.light_mode_tint);
+        mDarkModeDefaultColor =
+                ApiCompatibilityUtils.getColor(getResources(), R.color.dark_mode_tint);
     }
 
     @Override
@@ -943,8 +949,8 @@
             translateCanvasToView(mToolbarButtonsContainer, mMenuButton, canvas);
             mTabSwitcherAnimationMenuDrawable.setAlpha(rgbAlpha);
             int color = mUseLightToolbarDrawables
-                    ? ApiCompatibilityUtils.getColor(getResources(), R.color.light_mode_tint)
-                    : ApiCompatibilityUtils.getColor(getResources(), R.color.dark_mode_tint);
+                    ? mLightModeDefaultColor
+                    : mDarkModeDefaultColor;
             mTabSwitcherAnimationMenuDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
             mTabSwitcherAnimationMenuDrawable.draw(canvas);
         }
@@ -1373,8 +1379,8 @@
             Resources res = getResources();
             mTabSwitcherAnimationMenuDrawable = ApiCompatibilityUtils.getDrawable(
                     res, R.drawable.btn_menu).mutate();
-            mTabSwitcherAnimationMenuDrawable.setColorFilter(isIncognito() ? Color.WHITE
-                    : ApiCompatibilityUtils.getColor(res, R.color.light_normal_color),
+            mTabSwitcherAnimationMenuDrawable.setColorFilter(
+                    isIncognito() ? mLightModeDefaultColor : mDarkModeDefaultColor,
                     PorterDuff.Mode.SRC_IN);
             ((BitmapDrawable) mTabSwitcherAnimationMenuDrawable).setGravity(Gravity.CENTER);
         }
@@ -1874,25 +1880,21 @@
                 : R.color.progress_bar_foreground);
         getProgressBar().setForegroundColor(progressBarForegroundColor);
 
-        ColorStateList dark =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
-        ColorStateList white =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.light_mode_tint);
 
         if (mToggleTabStackButton != null) {
             mToggleTabStackButton.setImageDrawable(mUseLightToolbarDrawables
                     ? mTabSwitcherButtonDrawableLight : mTabSwitcherButtonDrawable);
             if (mTabSwitcherAnimationTabStackDrawable != null) {
                 mTabSwitcherAnimationTabStackDrawable.setTint(
-                        mUseLightToolbarDrawables ? white : dark);
+                        mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
             }
         }
 
         if (shouldShowMenuButton()) {
-            mMenuButton.setTint(mUseLightToolbarDrawables ? white : dark);
+            mMenuButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
         }
         if (mHomeButton.getVisibility() != GONE) {
-            mHomeButton.setTint(mUseLightToolbarDrawables ? white : dark);
+            mHomeButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint);
         }
 
         mPhoneLocationBar.updateVisualsForState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
index 31b0ad71..4e73d9b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
@@ -6,7 +6,6 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -292,14 +291,10 @@
             setBackgroundResource(incognito
                     ? R.color.incognito_primary_color : R.color.default_primary_color);
 
-            ColorStateList dark =
-                    ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
-            ColorStateList white = ApiCompatibilityUtils.getColorStateList(getResources(),
-                    R.color.light_mode_tint);
-            mMenuButton.setTint(incognito ? white : dark);
-            mHomeButton.setTint(incognito ? white : dark);
-            mBackButton.setTint(incognito ? white : dark);
-            mForwardButton.setTint(incognito ? white : dark);
+            mMenuButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mHomeButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mBackButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
+            mForwardButton.setTint(incognito ? mLightModeTint : mDarkModeTint);
             if (incognito) {
                 mLocationBar.getContainerView().getBackground().setAlpha(
                         ToolbarPhone.LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA);
@@ -339,26 +334,23 @@
             mReloadButton.setContentDescription(getContext().getString(
                     R.string.accessibility_btn_refresh));
         }
-        ColorStateList dark = ApiCompatibilityUtils.getColorStateList(getResources(),
-                R.color.dark_mode_tint);
-        ColorStateList white = ApiCompatibilityUtils.getColorStateList(getResources(),
-                R.color.light_mode_tint);
-        mReloadButton.setTint(isIncognito() ? white : dark);
+        mReloadButton.setTint(isIncognito() ? mLightModeTint : mDarkModeTint);
         mReloadButton.setEnabled(!mInTabSwitcherwMode);
     }
 
     @Override
     protected void updateBookmarkButton(boolean isBookmarked, boolean editingAllowed) {
-        int tintColor = isIncognito() ? R.color.light_mode_tint : R.color.dark_mode_tint;
         if (isBookmarked) {
             mBookmarkButton.setImageResource(R.drawable.btn_star_filled);
             // Non-incognito mode shows a blue filled star.
-            if (!isIncognito()) tintColor = R.color.blue_mode_tint;
+            mBookmarkButton.setTint(isIncognito()
+                    ? mLightModeTint
+                    : ApiCompatibilityUtils.getColorStateList(
+                            getResources(), R.color.blue_mode_tint));
         } else {
             mBookmarkButton.setImageResource(R.drawable.btn_star);
+            mBookmarkButton.setTint(isIncognito() ? mLightModeTint : mDarkModeTint);
         }
-        ColorStateList tint = ApiCompatibilityUtils.getColorStateList(getResources(), tintColor);
-        mBookmarkButton.setTint(tint);
         mBookmarkButton.setEnabled(editingAllowed);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivityTab.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivityTab.java
index 6011892..0167237 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivityTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivityTab.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
 import org.chromium.chrome.browser.tab.ChromeTab;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabChromeWebContentsDelegateAndroid;
 import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -308,11 +309,15 @@
 
     @Override
     protected FullScreenTabWebContentsDelegateAndroid createWebContentsDelegate() {
-        return new FullScreenTabWebContentsDelegateAndroid();
+        return new FullScreenTabWebContentsDelegateAndroid(this, mActivity);
     }
 
     private class FullScreenTabWebContentsDelegateAndroid
             extends TabChromeWebContentsDelegateAndroid {
+        public FullScreenTabWebContentsDelegateAndroid(Tab tab, ChromeActivity activity) {
+            super(tab, activity);
+        }
+
         @Override
         public void activateContents() {
             if (!(mActivity instanceof WebappActivity)) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 827a4e1e5..5711aa6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -187,7 +187,7 @@
 
     private void initializeSplashScreen() {
         final int backgroundColor = mWebappInfo.backgroundColor(
-                getResources().getColor(R.color.webapp_default_bg));
+                ApiCompatibilityUtils.getColor(getResources(), R.color.webapp_default_bg));
 
         ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
         mSplashScreen = createSplashScreen(contentView);
@@ -334,7 +334,7 @@
                 ? ApiCompatibilityUtils.getColor(getResources(), R.color.default_primary_color)
                 : mBrandColor;
 
-        DocumentUtils.updateTaskDescription(this, title, icon, color, mBrandColor == null);
+        ApiCompatibilityUtils.setTaskDescription(this, title, icon, color);
     }
 
     /** Returns a unique identifier for this WebappActivity. */
@@ -376,7 +376,7 @@
         splashIconView.setImageBitmap(displayIcon);
 
         if (ColorUtils.shoudUseLightForegroundOnBackground(backgroundColor)) {
-            appNameView.setTextColor(getResources().getColor(
+            appNameView.setTextColor(ApiCompatibilityUtils.getColor(getResources(),
                     R.color.webapp_splash_title_light));
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/FloatLabelLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/FloatLabelLayout.java
index e6a2de40..b7bca149 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/FloatLabelLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/FloatLabelLayout.java
@@ -23,6 +23,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 
 /**
@@ -100,7 +101,7 @@
         ViewCompat.setPivotX(mLabel, 0f);
         ViewCompat.setPivotY(mLabel, 0f);
 
-        mLabel.setTextAppearance(context,
+        ApiCompatibilityUtils.setTextAppearance(mLabel,
                 a.getResourceId(R.styleable.FloatLabelLayout_floatLabelTextAppearance,
                         android.R.style.TextAppearance_Small));
         a.recycle();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ReaderModeControl.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ReaderModeControl.java
index 67dcecc..3d08ee9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ReaderModeControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ReaderModeControl.java
@@ -19,7 +19,7 @@
 /**
  * Root ControlContainer for the Reader Mode panel.
  * Handles user interaction with the Reader Mode control.
- * See {@link BottomBarTextControl} for inspiration, based on ToolbarControlContainer.
+ * See {@link ContextualSearchBarControl} for inspiration, based on ToolbarControlContainer.
  */
 public class ReaderModeControl extends LinearLayout {
     private ViewResourceAdapter mResourceAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TextBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TextBubble.java
index 9ca799e..5601a04d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TextBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TextBubble.java
@@ -87,12 +87,12 @@
                                                          : android.R.style.Animation);
 
         mTooltipText = new TextView(context);
-        mTooltipText.setTextAppearance(context,
+        ApiCompatibilityUtils.setTextAppearance(mTooltipText,
                 (res.containsKey(TEXT_STYLE_ID) ? res.getInt(TEXT_STYLE_ID) : R.style.info_bubble));
 
         setContentView(mTooltipText);
-        setWindowLayoutMode(
-                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+        setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
     }
 
     /**
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index eca2944f..545adb82 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -161,6 +161,9 @@
       <message name="IDS_NO_THANKS" desc="Generic label to say no thanks for a feature. [CHAR-LIMIT=32]">
         No Thanks
       </message>
+      <message name="IDS_NEXT" desc="Generic label for a button to advance to the next item. [CHAR-LIMIT=20]">
+        Next
+      </message>
 
       <!-- Main Preferences -->
       <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
@@ -747,7 +750,7 @@
         We are testing the proxying of HTTPS pages through Google servers as part of an experiment.
       </message>
 
-      <!-- Data Saver Promo -->
+      <!-- Data Saver Promo and FRE card -->
       <message name="IDS_DATA_REDUCTION_PROMO_TITLE" desc="The title for the promo inviting users to enable Data Saver" >
         Browse more for less
       </message>
@@ -757,6 +760,12 @@
       <message name="IDS_DATA_REDUCTION_ENABLE_BUTTON" desc="Button the user presses if they want to enable Data Saver" >
         Enable Data Saver
       </message>
+      <message name="IDS_DATA_REDUCTION_ENABLED_SWITCH" desc="Message to show when the Data Saver feature is enabled via the switch on the First Run Experience card" >
+        Data Saver enabled
+      </message>
+      <message name="IDS_DATA_REDUCTION_DISABLED_SWITCH" desc="Message to show when the Data Saver feature is disabled via the switch on the First Run Experience card" >
+        Data Saver disabled
+      </message>
       <message name="IDS_DATA_REDUCTION_ENABLED_TOAST" desc="Toast message displayed after the user enables Data Saver from the promo" >
         Data Saver is on. Manage it in Settings.
       </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
new file mode 100644
index 0000000..b28cfae
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
@@ -0,0 +1,84 @@
+// Copyright 2015 The Chromium 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.customtabs;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.Process;
+import android.support.customtabs.ICustomTabsCallback;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/** Tests for ClientManager. */
+public class ClientManagerTest extends InstrumentationTestCase {
+    private static final String URL = "https://www.android.com";
+    private ClientManager mClientManager;
+    private ICustomTabsCallback mCallback = new CustomTabsTestUtils.DummyCallback();
+    private IBinder mSession = mCallback.asBinder();
+    private int mUid = Process.myUid();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Context context = getInstrumentation().getTargetContext().getApplicationContext();
+        mClientManager = new ClientManager(context);
+    }
+
+    @SmallTest
+    public void testNoSessionNoWarmup() {
+        assertEquals(ClientManager.NO_SESSION_NO_WARMUP, mClientManager.getWarmupState(null));
+    }
+
+    @SmallTest
+    public void testNoSessionWarmup() {
+        mClientManager.recordUidHasCalledWarmup(mUid);
+        assertEquals(ClientManager.NO_SESSION_WARMUP, mClientManager.getWarmupState(null));
+    }
+
+    @SmallTest
+    public void testInvalidSessionNoWarmup() {
+        assertEquals(ClientManager.NO_SESSION_NO_WARMUP, mClientManager.getWarmupState(mSession));
+    }
+
+    @SmallTest
+    public void testInvalidSessionWarmup() {
+        mClientManager.recordUidHasCalledWarmup(mUid);
+        assertEquals(ClientManager.NO_SESSION_WARMUP, mClientManager.getWarmupState(mSession));
+    }
+
+    @SmallTest
+    public void testValidSessionNoWarmup() {
+        mClientManager.newSession(mCallback, mUid, null);
+        assertEquals(ClientManager.SESSION_NO_WARMUP_NOT_CALLED,
+                mClientManager.getWarmupState(mSession));
+    }
+
+    @SmallTest
+    public void testValidSessionOtherWarmup() {
+        mClientManager.recordUidHasCalledWarmup(mUid + 1);
+        mClientManager.newSession(mCallback, mUid, null);
+        assertEquals(ClientManager.SESSION_NO_WARMUP_ALREADY_CALLED,
+                mClientManager.getWarmupState(mSession));
+    }
+
+    @SmallTest
+    public void testValidSessionWarmup() {
+        mClientManager.recordUidHasCalledWarmup(mUid);
+        mClientManager.newSession(mCallback, mUid, null);
+        assertEquals(ClientManager.SESSION_WARMUP, mClientManager.getWarmupState(mSession));
+    }
+
+    @SmallTest
+    public void testValidSessionWarmupSeveralCalls() {
+        mClientManager.recordUidHasCalledWarmup(mUid);
+        mClientManager.newSession(mCallback, mUid, null);
+        assertEquals(ClientManager.SESSION_WARMUP, mClientManager.getWarmupState(mSession));
+
+        ICustomTabsCallback callback = new CustomTabsTestUtils.DummyCallback();
+        IBinder session = callback.asBinder();
+        mClientManager.newSession(callback, mUid, null);
+        assertEquals(ClientManager.SESSION_WARMUP, mClientManager.getWarmupState(session));
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTestBase.java
index 6be2de9..3c8ce13 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTestBase.java
@@ -7,14 +7,6 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 
-import org.apache.http.HttpException;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpStatus;
-import org.apache.http.HttpVersion;
-import org.apache.http.message.BasicHttpResponse;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.CoreProtocolPNames;
-import org.apache.http.params.HttpParams;
 import org.chromium.content.browser.test.NativeLibraryTestBase;
 import org.chromium.net.test.BaseHttpTestServer;
 
@@ -27,6 +19,8 @@
  * It includes a {@link ConnectivityTestServer} which is set up and torn down automatically
  * for tests.
  */
+// TODO(nyquist): fix deprecation warnings crbug.com/537053
+@SuppressWarnings("deprecation")
 public class ConnectivityCheckerTestBase extends NativeLibraryTestBase {
     static final int TIMEOUT_MS = 5000;
     /**
@@ -116,15 +110,17 @@
         }
 
         @Override
-        protected HttpParams getConnectionParams() {
-            HttpParams httpParams = new BasicHttpParams();
-            httpParams.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
+        protected org.apache.http.params.HttpParams getConnectionParams() {
+            org.apache.http.params.HttpParams httpParams =
+                    new org.apache.http.params.BasicHttpParams();
+            httpParams.setParameter(org.apache.http.params.CoreProtocolPNames.PROTOCOL_VERSION,
+                    org.apache.http.HttpVersion.HTTP_1_1);
             return httpParams;
         }
 
         @Override
-        protected void handleGet(HttpRequest request, HttpResponseCallback callback)
-                throws HttpException {
+        protected void handleGet(org.apache.http.HttpRequest request, HttpResponseCallback callback)
+                throws org.apache.http.HttpException {
             String requestPath = request.getRequestLine().getUri();
             if (GENERATE_204_SLOW_PATH.equals(requestPath)) {
                 sendDelayedResponse(callback, requestPath);
@@ -149,22 +145,23 @@
         private void sendResponse(HttpResponseCallback callback, String requestPath) {
             int httpStatus = getStatusCodeFromRequestPath(requestPath);
             String reason = String.valueOf(httpStatus);
-            callback.onResponse(new BasicHttpResponse(HttpVersion.HTTP_1_1, httpStatus, reason));
+            callback.onResponse(new org.apache.http.message.BasicHttpResponse(
+                    org.apache.http.HttpVersion.HTTP_1_1, httpStatus, reason));
         }
 
         private int getStatusCodeFromRequestPath(String requestPath) {
             switch (requestPath) {
                 case GENERATE_200_PATH:
-                    return HttpStatus.SC_OK;
+                    return org.apache.http.HttpStatus.SC_OK;
                 case GENERATE_204_PATH: // Intentional fall through.
                 case GENERATE_204_SLOW_PATH:
-                    return HttpStatus.SC_NO_CONTENT;
+                    return org.apache.http.HttpStatus.SC_NO_CONTENT;
                 case GENERATE_302_PATH:
-                    return HttpStatus.SC_MOVED_TEMPORARILY;
+                    return org.apache.http.HttpStatus.SC_MOVED_TEMPORARILY;
                 case GENERATE_404_PATH:
-                    return HttpStatus.SC_NOT_FOUND;
+                    return org.apache.http.HttpStatus.SC_NOT_FOUND;
                 default:
-                    return HttpStatus.SC_INTERNAL_SERVER_ERROR;
+                    return org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
             }
         }
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java
index e23c096f..792375e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java
@@ -41,6 +41,8 @@
  */
 // TODO(peter): remove @SuppressLint once crbug.com/501900 is fixed.
 @SuppressLint("NewApi")
+// TODO(peter): fix deprecation warnings crbug.com/528076
+@SuppressWarnings("deprecation")
 public class NotificationUIManagerTest extends ChromeActivityTestCaseBase<ChromeActivity> {
     private static final String NOTIFICATION_TEST_PAGE =
             TestHttpServerClient.getUrl("chrome/test/data/notifications/android_test.html");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
index fb73c1bd..377cfd7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
@@ -4,17 +4,18 @@
 
 package org.chromium.chrome.browser.sync.ui;
 
+import android.app.Instrumentation.ActivityMonitor;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.test.FlakyTest;
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.sync.FakeProfileSyncService;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.test.util.ApplicationData;
+import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.content.browser.test.NativeLibraryTestBase;
 import org.chromium.sync.signin.ChromeSigninController;
 
@@ -24,10 +25,14 @@
 public class PassphraseActivityTest extends NativeLibraryTestBase {
     private static final String TEST_ACCOUNT = "test@gmail.com";
 
+    private Context mContext;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        ApplicationData.clearAppData(getInstrumentation().getTargetContext());
+        mContext = getInstrumentation().getTargetContext();
+        SigninTestUtil.setUpAuthForTest(getInstrumentation());
+        ApplicationData.clearAppData(mContext);
         loadNativeLibraryAndInitBrowserProcess();
     }
 
@@ -43,16 +48,19 @@
      * @SmallTest
      * Constantly fails on M, fine on other platforms: http://crbug.com/517590
      */
-    @FlakyTest
     @Feature({"Sync"})
     public void testCallbackAfterBackgrounded() throws Exception {
-        final Context context = getInstrumentation().getTargetContext();
+        getInstrumentation().waitForIdleSync();
+        SigninTestUtil.get().addAndSignInTestAccount();
+
         // Override before creating the activity so we know initialized is false.
         overrideProfileSyncService();
+
         // PassphraseActivity won't start if an account isn't set.
-        ChromeSigninController.get(context).setSignedInAccountName(TEST_ACCOUNT);
+        assertNotNull(ChromeSigninController.get(mContext).getSignedInAccountName());
+
         // Create the activity.
-        final PassphraseActivity activity = launchPassphraseActivity(context);
+        final PassphraseActivity activity = launchPassphraseActivity();
         assertNotNull(activity);
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
@@ -70,15 +78,18 @@
         // Nothing crashed; success!
     }
 
-    private PassphraseActivity launchPassphraseActivity(Context context) {
+    private PassphraseActivity launchPassphraseActivity() {
         Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.setComponent(new ComponentName(context, PassphraseActivity.class));
+        intent.setComponent(new ComponentName(mContext, PassphraseActivity.class));
         intent.addCategory(Intent.CATEGORY_LAUNCHER);
         // This activity will become the start of a new task on this history stack.
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         // Clears the task stack above this activity if it already exists.
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        return launchActivityWithIntent(context.getPackageName(), PassphraseActivity.class, intent);
+        ActivityMonitor monitor =
+                getInstrumentation().addMonitor(PassphraseActivity.class.getName(), null, false);
+        mContext.startActivity(intent);
+        return (PassphraseActivity) getInstrumentation().waitForMonitor(monitor);
     }
 
     private void overrideProfileSyncService() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
index 0b6cbff..3d9ece7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
@@ -4,11 +4,14 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import android.annotation.TargetApi;
 import android.graphics.Color;
+import android.os.Build;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.SysUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
@@ -17,6 +20,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
 import org.chromium.chrome.test.util.DisableInTabbedMode;
 import org.chromium.content.browser.InterstitialPageDelegateAndroid;
@@ -60,6 +64,7 @@
         // Don't launch activity automatically.
     }
 
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     private void checkForBrandColor(final int brandColor) {
         try {
             assertTrue("The toolbar background doesn't contain the right color",
@@ -78,6 +83,21 @@
                             return mToolbar.getOverlayDrawable().getColor() == brandColor;
                         }
                     }));
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
+                    && !SysUtils.isLowEndDevice()) {
+                final int expectedStatusBarColor = brandColor == mDefaultColor
+                        ? Color.BLACK
+                        : ColorUtils.getDarkenedColorForStatusBar(brandColor);
+                assertTrue("The status bar is not set to the right color",
+                        CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
+                            @Override
+                            public boolean isSatisfied() {
+                                return expectedStatusBarColor
+                                        == getActivity().getWindow().getStatusBarColor();
+                            }
+                        }));
+            }
+
         } catch (InterruptedException e) {
             fail();
         }
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
index 8abf2dea..4f38ee5c 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
@@ -57,7 +57,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         // Make sure the initial state is clean.
         assertClientAutofillProfileCount(0);
         assertServerAutofillProfileCountWithName(0, STREET);
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
index 5425869..b00a46d 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
@@ -71,7 +71,7 @@
                 mBookmarksBridge.loadEmptyPartnerBookmarkShimForTesting();
             }
         });
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         // Make sure initial state is clean.
         assertClientBookmarkCount(0);
         assertServerBookmarkCountWithName(0, TITLE);
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
index e228ddf..5e3a3e2 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
@@ -33,7 +33,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testFreSignin() throws Exception {
-        Account testAccount = setupTestAccount(CLIENT_ID);
+        Account testAccount = setUpTestAccount();
         SyncTestUtil.verifySyncIsSignedOut(mContext);
         assertFalse(AndroidSyncSettings.isChromeSyncEnabled(mContext));
         processFirstRun(testAccount.name, ShowSyncSettings.NO);
@@ -45,7 +45,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testFreNoSignin() throws Exception {
-        setupTestAccount(CLIENT_ID);
+        setUpTestAccount();
         SyncTestUtil.verifySyncIsSignedOut(mContext);
         assertFalse(AndroidSyncSettings.isChromeSyncEnabled(mContext));
         processFirstRun(null, ShowSyncSettings.NO);
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
index e164db3..b591385c 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
@@ -71,7 +71,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         mClientName = getClientName();
         mSessionTagCounter = 0;
     }
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
index c7e98d7..599e35b 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
@@ -98,7 +98,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testSyncSwitch() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         final SwitchPreference syncSwitch = getSyncSwitch(fragment);
@@ -119,7 +119,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testOpeningSettingsDoesntEnableSync() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         stopSync();
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         closeFragment(fragment);
@@ -132,7 +132,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testOpeningSettingsDoesntStartBackend() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         stopSync();
         startSyncCustomizationFragment();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -147,7 +147,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testDefaultControlStatesWithSyncOffThenOn() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         stopSync();
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         assertDefaultSyncOffState(fragment);
@@ -159,7 +159,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testDefaultControlStatesWithSyncOnThenOff() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         assertDefaultSyncOnState(fragment);
@@ -170,7 +170,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testSyncEverythingAndDataTypes() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         SwitchPreference syncEverything = getSyncEverything(fragment);
@@ -195,7 +195,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testSettingDataTypes() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         SwitchPreference syncEverything = getSyncEverything(fragment);
@@ -233,7 +233,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testDefaultEncryptionOptions() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         final SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         Preference encryption = getEncryption(fragment);
@@ -267,7 +267,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testChoosePassphraseTypeWhenSyncIsOff() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         Preference encryption = getEncryption(fragment);
@@ -291,7 +291,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testEnterPassphraseWhenSyncIsOff() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         final SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         stopSync();
@@ -312,7 +312,7 @@
     public void testPassphraseDialogDismissed() throws Exception {
         final FakeProfileSyncService pss = overrideProfileSyncService();
 
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         // Trigger PassphraseDialogFragment to be shown when taping on Encryption.
         pss.setPassphraseRequiredForDecryption(true);
@@ -343,7 +343,7 @@
     @SmallTest
     @Feature({"Sync"})
     public void testPassphraseCreation() throws Exception {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
         final SyncCustomizationFragment fragment = startSyncCustomizationFragment();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
index 707c924..2a6fdc1 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
@@ -19,7 +19,6 @@
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.JavaScriptUtils;
 import org.chromium.sync.AndroidSyncSettings;
-import org.chromium.sync.signin.AccountManagerHelper;
 
 import java.util.concurrent.TimeoutException;
 
@@ -32,7 +31,7 @@
     @LargeTest
     @Feature({"Sync"})
     public void testGetAboutSyncInfoYieldsValidData() throws Throwable {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
 
         final SyncTestUtil.AboutSyncInfoGetter syncInfoGetter =
                 new SyncTestUtil.AboutSyncInfoGetter(getActivity());
@@ -51,7 +50,7 @@
     @LargeTest
     @Feature({"Sync"})
     public void testFlushDirectoryDoesntBreakSync() throws Throwable {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         final Activity activity = getActivity();
 
         runTestOnUiThread(new Runnable() {
@@ -67,7 +66,7 @@
     @LargeTest
     @Feature({"Sync"})
     public void testAboutSyncPageDisplaysCurrentSyncStatus() throws InterruptedException {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
 
         loadUrl("chrome://sync");
         SyncTestUtil.AboutSyncInfoGetter aboutInfoGetter =
@@ -112,9 +111,7 @@
     @LargeTest
     @Feature({"Sync"})
     public void testSignInAndOut() throws InterruptedException {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
-        Account account =
-                AccountManagerHelper.createAccountFromName(SyncTestUtil.DEFAULT_TEST_ACCOUNT);
+        Account account = setUpTestAccountAndSignInToSync();
 
         // Signing out should disable sync.
         signOut();
@@ -128,9 +125,7 @@
     @LargeTest
     @Feature({"Sync"})
     public void testStopAndStartSync() throws InterruptedException {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
-        Account account =
-                AccountManagerHelper.createAccountFromName(SyncTestUtil.DEFAULT_TEST_ACCOUNT);
+        Account account = setUpTestAccountAndSignInToSync();
 
         SyncTestUtil.verifySyncIsActiveForAccount(mContext, account);
         stopSync();
@@ -142,11 +137,9 @@
     @LargeTest
     @Feature({"Sync"})
     public void testDisableAndEnableSyncThroughAndroid() throws InterruptedException {
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        Account account = setUpTestAccountAndSignInToSync();
         SyncTestUtil.waitForSyncActive(mContext);
 
-        Account account =
-                AccountManagerHelper.createAccountFromName(SyncTestUtil.DEFAULT_TEST_ACCOUNT);
         String authority = AndroidSyncSettings.getContractAuthority(mContext);
 
         // Disabling Android sync should turn Chrome sync engine off.
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java
index 062c260..097b702 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestBase.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.sync;
 
 import android.accounts.Account;
-import android.app.Activity;
 import android.content.Context;
 
 import org.chromium.base.ThreadUtils;
@@ -13,17 +12,16 @@
 import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator;
 import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory;
 import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator;
-import org.chromium.chrome.browser.signin.AccountIdProvider;
-import org.chromium.chrome.browser.signin.AccountTrackerService;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
+import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.sync.AndroidSyncSettings;
-import org.chromium.sync.signin.AccountManagerHelper;
-import org.chromium.sync.signin.ChromeSigninController;
-import org.chromium.sync.test.util.MockAccountManager;
+import org.chromium.sync.ModelType;
 import org.chromium.sync.test.util.MockSyncContentResolverDelegate;
 
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -32,15 +30,23 @@
 public class SyncTestBase extends ChromeActivityTestCaseBase<ChromeActivity> {
     private static final String TAG = "SyncTestBase";
 
-    protected static final String CLIENT_ID = "Client_ID";
+    private static final String CLIENT_ID = "Client_ID";
+
+    private static final Set<Integer> USER_SELECTABLE_TYPES =
+            new HashSet<Integer>(Arrays.asList(new Integer[] {
+                ModelType.AUTOFILL,
+                ModelType.BOOKMARKS,
+                ModelType.PASSWORDS,
+                ModelType.PREFERENCES,
+                ModelType.PROXY_TABS,
+                ModelType.TYPED_URLS,
+            }));
 
     protected SyncTestUtil.SyncTestContext mContext;
-    protected MockAccountManager mAccountManager;
     protected SyncController mSyncController;
     protected FakeServerHelper mFakeServerHelper;
     protected ProfileSyncService mProfileSyncService;
     protected MockSyncContentResolverDelegate mSyncContentResolver;
-    protected ChromeSigninController mChromeSigninController;
 
     public SyncTestBase() {
       super(ChromeActivity.class);
@@ -55,21 +61,14 @@
 
     @Override
     protected void setUp() throws Exception {
-        // This must be called before super.setUp() in order for test authentication to work
-        // properly.
-        mapAccountNamesToIds();
+        // This must be called before super.setUp() in order for test authentication to work.
+        SigninTestUtil.setUpAuthForTest(getInstrumentation());
 
         super.setUp();
         Context targetContext = getInstrumentation().getTargetContext();
         mContext = new SyncTestUtil.SyncTestContext(targetContext);
 
         setUpMockAndroidSyncSettings();
-        setUpMockAccountManager();
-
-        // Initializes ChromeSigninController to use our test context and make sure there is no
-        // account is signed in yet.
-        mChromeSigninController = ChromeSigninController.get(mContext);
-        mChromeSigninController.setSignedInAccountName(null);
 
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
@@ -87,6 +86,15 @@
                 mProfileSyncService = ProfileSyncService.get();
             }
         });
+
+        UniqueIdentificationGeneratorFactory.registerGenerator(
+                UuidBasedUniqueIdentificationGenerator.GENERATOR_ID,
+                new UniqueIdentificationGenerator() {
+                    @Override
+                    public String getUniqueId(String salt) {
+                        return CLIENT_ID;
+                    }
+                }, true);
     }
 
     @Override
@@ -99,75 +107,28 @@
             }
         });
 
-        if (mChromeSigninController.isSignedIn()) signOut();
-
         super.tearDown();
     }
 
-    private void mapAccountNamesToIds() {
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                AccountIdProvider.setInstanceForTest(new AccountIdProvider() {
-                    @Override
-                    public String getAccountId(Context ctx, String accountName) {
-                        return "gaia-id-" + accountName;
-                    }
-
-                    @Override
-                    public boolean canBeUsed(Context ctx, Activity activity) {
-                        return true;
-                    }
-                });
-            }
-        });
-    }
-
-    private void setUpMockAccountManager() {
-        mAccountManager = new MockAccountManager(mContext, getInstrumentation().getContext());
-        AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
-    }
-
     private void setUpMockAndroidSyncSettings() {
         mSyncContentResolver = new MockSyncContentResolverDelegate();
         mSyncContentResolver.setMasterSyncAutomatically(true);
         AndroidSyncSettings.overrideForTests(mContext, mSyncContentResolver);
     }
 
-    protected Account setupTestAccount(final String syncClientIdentifier)
-            throws InterruptedException {
-        Account defaultTestAccount = SyncTestUtil.setupTestAccountThatAcceptsAllAuthTokens(
-                mAccountManager, SyncTestUtil.DEFAULT_TEST_ACCOUNT, SyncTestUtil.DEFAULT_PASSWORD);
-
-        // Force refresh AccountTrackerService since accounts are changed.
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                AccountTrackerService.get(mContext).forceRefresh();
-            }
-        });
-
-        UniqueIdentificationGeneratorFactory.registerGenerator(
-                UuidBasedUniqueIdentificationGenerator.GENERATOR_ID,
-                new UniqueIdentificationGenerator() {
-                    @Override
-                    public String getUniqueId(String salt) {
-                        return syncClientIdentifier;
-                    }
-                }, true);
-
+    protected Account setUpTestAccount() throws InterruptedException {
+        Account account = SigninTestUtil.get().addAndSignInTestAccount();
         SyncTestUtil.verifySyncIsSignedOut(getActivity());
-        return defaultTestAccount;
+        return account;
     }
 
-    protected void setupTestAccountAndSignInToSync(
-            final String syncClientIdentifier)
-            throws InterruptedException {
-        Account defaultTestAccount = setupTestAccount(syncClientIdentifier);
-        signIn(defaultTestAccount);
-        SyncTestUtil.verifySyncIsActiveForAccount(mContext, defaultTestAccount);
+    protected Account setUpTestAccountAndSignInToSync() throws InterruptedException {
+        Account account = setUpTestAccount();
+        signIn(account);
+        SyncTestUtil.verifySyncIsActiveForAccount(mContext, account);
         assertTrue("Sync everything should be enabled",
                 SyncTestUtil.isSyncEverythingEnabled(mContext));
+        return account;
     }
 
     protected void startSync() throws InterruptedException {
@@ -213,6 +174,7 @@
             @Override
             public void run() {
                 Set<Integer> preferredTypes = mProfileSyncService.getPreferredDataTypes();
+                preferredTypes.retainAll(USER_SELECTABLE_TYPES);
                 preferredTypes.remove(modelType);
                 mProfileSyncService.setPreferredDataTypes(false, preferredTypes);
             }
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
index 248d7b0..6e7ad5f3 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
@@ -51,7 +51,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setupTestAccountAndSignInToSync(CLIENT_ID);
+        setUpTestAccountAndSignInToSync();
         // Make sure the initial state is clean.
         assertClientTypedUrlCount(0);
         assertServerTypedUrlCountWithName(0, URL);
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 6ca7b93..176bc62 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -87,6 +87,7 @@
 #define IDC_BASIC_PRINT                 35007
 #define IDC_TRANSLATE_PAGE              35009
 #define IDC_MANAGE_PASSWORDS_FOR_PAGE   35010
+#define IDC_ROUTE_MEDIA                 35011
 
 // When adding a new encoding to this list, be sure to append it to the
 // EncodingMenuController::kValidEncodingIds array in
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index c046f82..61193ce 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -45,6 +45,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_paths.h"
 #include "extensions/common/constants.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_switches.h"
 
 #if defined(OS_WIN)
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 119096bd..dd3062d 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1615,6 +1615,9 @@
                desc="Link label shown at the corner of the download shelf">
         Show all downloads...
       </message>
+      <message name="IDS_SHOW_ALL_DOWNLOADS_MD" desc="Button label shown at the corner of the download shelf">
+        Show all
+      </message>
       <!-- Download Error Messages-->
       <!-- *_STATUS_*: Short message in the download on the shelf.-->
       <!-- *_DESCRIPTION_*: Corresponding more descriptive message on the download page.-->
@@ -1788,42 +1791,28 @@
                desc="When starting a download, let the user know we're starting the download.">
         Starting...
       </message>
-      <message name="IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE"
-               desc=".">
-               Downloading <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph>
-      </message>
-      <message name="IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE"
-               desc=".">
-               <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph> downloaded
-      </message>
-      <message name="IDS_DOWNLOAD_STATUS_DOWNLOAD_FAILED_TITLE"
-               desc=".">
-               <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph> download unsuccessful
-      </message>
-      <message name="IDS_DOWNLOAD_STATUS_GROUP_IN_PROGRESS_TITLE"
-               desc="Title of download group notification which shows the combined progress of multiple downloads.">
-        {NUM_DOWNLOADS, plural,
-         =1 {Downloading a file}
-         other {Downloading # files}}
-      </message>
-      <message name="IDS_DOWNLOAD_STATUS_GROUP_DONE_TITLE"
-               desc="Title of download group notification which shows the combined progress of multiple downloads. [ICU Syntax]">
-        {NUM_DOWNLOADS, plural,
-         =1 {Downloaded a file}
-         other {Downloaded # files}}
-      </message>
-      <message name="IDS_DOWNLOAD_NOTIFICATION_STATUS"
-               desc="Size and units downloaded and total, the origin domain, and the current status od download.">
-        <ph name="DOWNLOAD_RECEIVED_AND_TOTAL">$1<ex>54/154 MB</ex></ph> from <ph name="DOWNLOAD_DOMAIN">$2<ex>example.com</ex></ph>, <ph name="SUB_STATUS_TEXT">$3<ex>24 secs remaining</ex></ph>
-      </message>
-      <message name="IDS_DOWNLOAD_NOTIFICATION_STATUS_COMPLETED"
-               desc="Size and units downloaded, and the origin domain.">
-        <ph name="DOWNLOAD_RECEIVED_AND_TOTAL">$1<ex>154/154 MB</ex></ph> from <ph name="DOWNLOAD_DOMAIN">$2<ex>example.com</ex></ph>
-      </message>
-      <message name="IDS_DOWNLOAD_STATUS_COMBINED_IN_PROGRESS"
-               desc="Status text of download notification which shows the combined progres of multiple downloads">
-               <ph name="PERCENT">$1<ex>30</ex></ph>% complete, <ph name="TIME_LEFT">$2<ex>20 secs left</ex></ph>,
-      </message>
+      <if expr="chromeos">
+        <message name="IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE"
+                 desc=".">
+                 Downloading <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph>
+        </message>
+        <message name="IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE"
+                 desc=".">
+                 <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph> downloaded
+        </message>
+        <message name="IDS_DOWNLOAD_STATUS_DOWNLOAD_FAILED_TITLE"
+                 desc=".">
+                 <ph name="FILE_NAME">$1<ex>somedocument.pdf</ex></ph> download unsuccessful
+        </message>
+        <message name="IDS_DOWNLOAD_NOTIFICATION_STATUS"
+                 desc="Size and units downloaded and total, the origin domain, and the current status od download.">
+          <ph name="DOWNLOAD_RECEIVED_AND_TOTAL">$1<ex>54/154 MB</ex></ph> from <ph name="DOWNLOAD_DOMAIN">$2<ex>example.com</ex></ph>, <ph name="SUB_STATUS_TEXT">$3<ex>24 secs remaining</ex></ph>
+        </message>
+        <message name="IDS_DOWNLOAD_NOTIFICATION_STATUS_COMPLETED"
+                 desc="Size and units downloaded, and the origin domain.">
+          <ph name="DOWNLOAD_RECEIVED_AND_TOTAL">$1<ex>154/154 MB</ex></ph> from <ph name="DOWNLOAD_DOMAIN">$2<ex>example.com</ex></ph>
+        </message>
+      </if>
       <message name="IDS_DOWNLOAD_STATUS_IN_PROGRESS"
                desc="Size and units downloaded, time remaining.">
         <ph name="DOWNLOAD_RECEIVED">$1<ex>54/154 MB</ex></ph>, <ph name="TIME_LEFT">$2<ex>5s</ex></ph>
@@ -1891,10 +1880,12 @@
          desc="Message shown to the user to validate the download when the download content is classified as uncommon by safebrowsing.">
         <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> is not commonly downloaded and could be dangerous.
       </message>
-      <message name="IDS_PROMPT_BLOCKED_MALICIOUS_DOWNLOAD_TITLE"
-               desc="In the download notification, a title of message shown for blocked download">
-        Malicious download blocked
-      </message>
+      <if expr="chromeos">
+        <message name="IDS_PROMPT_BLOCKED_MALICIOUS_DOWNLOAD_TITLE"
+                 desc="In the download notification, a title of message shown for blocked download">
+          Malicious download blocked
+        </message>
+      </if>
       <message name="IDS_CONFIRM_KEEP_DANGEROUS_DOWNLOAD_TITLE"
                desc="Title for the confirmation dialog asking whether the user really meant to keep a dangerous download">
         Confirm Download
@@ -2013,10 +2004,12 @@
                desc="In the download notification, 'Show all downloads' button text.">
         Show all downloads
       </message>
-      <message name="IDS_DOWNLOAD_LINK_LEARN_MORE_SCANNING"
-               desc="In the download notification, a label of the button to show information about download scanning">
-        Learn more
-      </message>
+      <if expr="chromeos">
+        <message name="IDS_DOWNLOAD_LINK_LEARN_MORE_SCANNING"
+                 desc="In the download notification, a label of the button to show information about download scanning">
+          Learn more
+        </message>
+      </if>
       <message name="IDS_DOWNLOAD_TAB_CANCELLED"
                desc="Text that appears next to the downloaded files that have been canceled">
         Canceled
@@ -6572,6 +6565,26 @@
       <message name="IDS_FLAGS_LOW_PRIORITY_IFRAMES_UI_DESCRIPTION" desc="Description of the flag to enable the low priority iframes experiment.">
         Reduces the load priority of iframe resources.
       </message>
+      <if expr="is_win">
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_NAME" desc="Name of the flag to enable PPAPI win32k lockdown experiment.">
+          Enable PPAPI Win32k Lockdown.
+        </message>
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_DESCRIPTION" desc="Description of the flag to enable PPAPI win32k lockdown experiment.">
+          Specify the PPAPI plugins which will be run within the Win32k lockdown sandbox policy.
+        </message>
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_FLASH_ONLY" desc="Enable Win32k lockdown for Flash">
+          Flash only
+        </message>
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_PDF_ONLY" desc="Enable Win32k lockdown for PDF">
+          PDF only
+        </message>
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_FLASH_AND_PDF" desc="Enable Win32k lockdown for Flash and PDF">
+          Flash and PDF
+        </message>
+        <message name="IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_ALL" desc="Enable Win32k lockdown for all plugins">
+          All plugins
+        </message>
+      </if>
 
       <!-- Crashes -->
       <message name="IDS_CRASHES_TITLE" desc="Title for the chrome://crashes page.">
@@ -7115,6 +7128,9 @@
           Search or type URL
         </message>
       </if>
+      <message name="IDS_OMNIBOX_ACCESSIBLE_ANSWER" desc="Readable text represening a query typed by the user in the omnibox, followed by an indication that an answer to that query will follow, followed by the answer. The commas are significant as they will introduce a pause in the spoken text.">
+        <ph name="QUERY">$1<ex>weather in los angeles</ex></ph>, answer, <ph name="ANSWER">$2<ex>sunny and 84 degrees</ex></ph>
+      </message>
 
       <!--Tooltip strings-->
       <message name="IDS_TOOLTIP_BACK" desc="The tooltip for back button">
@@ -15255,13 +15271,31 @@
 
       <!-- WebUsb Notification -->
       <message name="IDS_WEBUSB_DEVICE_DETECTED_NOTIFICATION" desc="Content for notification shown to the user when a USB device gets plugged in.">
-        Go to <ph name="LANDING_PAGE">$1</ph> to connect.
+        Go to <ph name="LANDING_PAGE">$1<ex>www.google.com</ex></ph> to connect.
       </message>
       <message name="IDS_WEBUSB_DEVICE_DETECTED_NOTIFICATION_TITLE" desc="Title for notification shown to the user when a USB device gets plugged in.">
-        <ph name="USB_DEVICE_NAME">$1</ph> detected
+        <ph name="USB_DEVICE_NAME">$1<ex>Nexus 5</ex></ph> detected
       </message>
     </if>
 
+      <!-- Audio device strings. -->
+      <message name="IDS_DEFAULT_AUDIO_DEVICE_NAME" desc="System default audio device (microphone or loudspeaker). This is typically presented to users in a drop-down list of device choices.">
+          Default
+      </message>
+      <if expr="is_win">
+        <message name="IDS_COMMUNICATIONS_AUDIO_DEVICE_NAME" desc="System default communications audio device (microphone or loudspeaker). This is typically presented to users in a drop-down list of device choices.">
+          Communications
+        </message>
+      </if>
+      <if expr="chromeos">
+        <message name="IDS_BEAMFORMING_ON_DEFAULT_AUDIO_INPUT_DEVICE_NAME" desc="Default audio input device (microphone) with a narrow angle coverage. Only the user in front of the device (i.e. you) will be listened to. This is typically presented to users in a drop-down list of device choices.">
+          Default (pick up just you)
+        </message>
+        <message name="IDS_BEAMFORMING_OFF_DEFAULT_AUDIO_INPUT_DEVICE_NAME" desc="Default audio input device (microphone) with a wide angle coverage. All the sounds in the vicinity will be listend to. This is typically presented to users in a drop-down list of device choices.">
+          Default (pick up everything)
+        </message>
+      </if>
+
     </messages>
   </release>
 </grit>
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp
index 7f62bad..254c353 100644
--- a/chrome/app/media_router_strings.grdp
+++ b/chrome/app/media_router_strings.grdp
@@ -8,6 +8,9 @@
   <message name="IDS_MEDIA_ROUTER_SHARE_YOUR_SCREEN_TEXT" desc="Tooltip for the Media Router Action icon, which appears in the toolbar. The tooltip appears on mouseover of the icon.">
    Share your screen
   </message>
+  <message name="IDS_MEDIA_ROUTER_MENU_ITEM_TITLE" desc="Title of menu item for Media Router, which appears in the overflow menu and page contextual menus.">
+    Cast...
+  </message>
 
   <!-- Cast Modes -->
   <message name="IDS_MEDIA_ROUTER_DEFAULT_CAST_MODE" desc="Title for the default cast mode, which is used when the host is cast enabled. This is shown as a dropdown option, and if selected, also appears as the header of a list of devices.">
diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp
index ae278a90..beb31be 100644
--- a/chrome/app/settings_chromium_strings.grdp
+++ b/chrome/app/settings_chromium_strings.grdp
@@ -10,4 +10,28 @@
   <message name="IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT" desc="Text alerting the user that synced data is encrypted.">
     For added security, Chromium will encrypt your data.
   </message>
+
+  <!-- Languages Page -->
+  <if expr="chromeos">
+    <message name="IDS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that cannot be used as the UI display language.">
+      Chromium OS cannot be displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that is currently used as the UI display language.">
+      Chromium OS is displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE" desc="The label used for a button that changes the UI language.">
+      Display Chromium OS in this language
+    </message>
+  </if>
+  <if expr="not chromeos">
+    <message name="IDS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that cannot be used as the UI display language.">
+      Chromium cannot be displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that is currently used as the UI display language.">
+      Chromium is displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE" desc="The label used for a button that changes the UI language.">
+      Display Chromium in this language
+    </message>
+  </if>
 </grit-part>
diff --git a/chrome/app/settings_google_chrome_strings.grdp b/chrome/app/settings_google_chrome_strings.grdp
index d1e15ad..772f056f 100644
--- a/chrome/app/settings_google_chrome_strings.grdp
+++ b/chrome/app/settings_google_chrome_strings.grdp
@@ -10,4 +10,28 @@
   <message name="IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT" desc="Text alerting the user that synced data is encrypted.">
     For added security, Google Chrome will encrypt your data.
   </message>
+
+  <!-- Languages Page -->
+  <if expr="chromeos">
+    <message name="IDS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that cannot be used as the UI display language.">
+      Chrome OS cannot be displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that is currently used as the UI display language.">
+      Chrome OS is displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE" desc="The label used for a button that changes the UI language.">
+      Display Chrome OS in this language
+    </message>
+  </if>
+  <if expr="not chromeos">
+    <message name="IDS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that cannot be used as the UI display language.">
+      Google Chrome cannot be displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE" desc="The label for a language that is currently used as the UI display language.">
+      Google Chrome is displayed in this language.
+    </message>
+    <message name="IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE" desc="The label used for a button that changes the UI language.">
+      Display Google Chrome in this language
+    </message>
+  </if>
 </grit-part>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index ef7fa393..864b609 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -6,64 +6,69 @@
     This setting is controlled by extension <ph name="NAME">$1<ex>Settings Extension</ex></ph> 
   </message>
 
-  <!-- Accessibility Page -->
-  <message name="IDS_SETTINGS_ACCESSIBILITY" desc="Name of the settings page which displays accessibility preferences.">
-    Accessibility
-  </message>
-  <message name="IDS_SETTINGS_MORE_FEATURES_LINK" desc="Link which opens page where users can install extensions which provide additional accessibility features.">
-    Add additional accessibility features
-  </message>
-  <message name="IDS_SETTINGS_OPTIONS_IN_MENU_LABEL" desc="Label for checkbox which enables showing accessibilitly options in the system menu.">
-    Show accessibility options in the system menu
-  </message>
-  <message name="IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL" desc="Label for checkbox which enables showing a larger mouse cursor than normal.">
-    Show large mouse cursor
-  </message>
-  <message name="IDS_SETTINGS_HIGH_CONTRAST_LABEL" desc="Label for checkbox which enables high-contrast UI.">
-    Use high contrast mode
-  </message>
-  <message name="IDS_SETTINGS_STICKY_KEYS_LABEL" desc="Label for checkbox which enables sticky keys.">
-    Enable sticky keys
-  </message>
-  <message name="IDS_SETTINGS_STICKY_KEYS_SUBLABEL" desc="Sub-label describing what the term 'sticky keys' means.">
-    (to perform keyboard shortcuts by typing them sequentially)
-  </message>
-  <message name="IDS_SETTINGS_CHROMEVOX_LABEL" desc="Label for checkbox which enables ChromeVox">
-    Enable ChromeVox
-  </message>
-  <message name="IDS_SETTINGS_CHROMEVOX_SUBLABEL" desc="Sub-label describingn what ChromeVox is.">
-    (spoken feedback)
-  </message>
-  <message name="IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL" desc="Label for checkbox which enables the screen magnifier">
-    Enable screen magnifier
-  </message>
-  <message name="IDS_SETTINGS_TAP_DRAGGING_LABEL" desc="Label for checkbox which enables tap dragging.">
-    Enable tap dragging
-  </message>
-  <message name="IDS_SETTINGS_CLICK_ON_STOP_LABEL" desc="Label for checkbox which enables automatically clicking when the mouse pointer stops.">
-    Automatically click when the mouse pointer stops
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL" desc="Label for dropdown menu which contains various time delays for clicks.">
-    Delay before click:
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT" desc="Description of an extremely short delay before clicks.">
-    extremely short
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT" desc="Description of a very short delay before clicks.">
-    very short
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT" desc="Description of a short delay before clicks.">
-    short
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG" desc="Description of a long delay before clicks.">
-    long
-  </message>
-  <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG" desc="Description of a very long delay before clicks.">
-    very long
-  </message>
-  <message name="IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL" desc="Label for checkbox which enables an on-screen keyboard.">
-    Enable on-screen keyboard
-  </message>
+  <if expr="chromeos">
+    <!-- Accessibility Page -->
+    <message name="IDS_SETTINGS_ACCESSIBILITY" desc="Name of the settings page which displays accessibility preferences.">
+      Accessibility
+    </message>
+    <message name="IDS_SETTINGS_MORE_FEATURES_LINK" desc="Link which opens page where users can install extensions which provide additional accessibility features.">
+      Add additional accessibility features
+    </message>
+    <message name="IDS_SETTINGS_OPTIONS_IN_MENU_LABEL" desc="Label for checkbox which enables showing accessibilitly options in the system menu.">
+      Show accessibility options in the system menu
+    </message>
+    <message name="IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL" desc="Label for checkbox which enables showing a larger mouse cursor than normal.">
+      Show large mouse cursor
+    </message>
+    <message name="IDS_SETTINGS_HIGH_CONTRAST_LABEL" desc="Label for checkbox which enables high-contrast UI.">
+      Use high contrast mode
+    </message>
+    <message name="IDS_SETTINGS_STICKY_KEYS_LABEL" desc="Label for checkbox which enables sticky keys.">
+      Enable sticky keys
+    </message>
+    <message name="IDS_SETTINGS_STICKY_KEYS_SUBLABEL" desc="Sub-label describing what the term 'sticky keys' means.">
+      (to perform keyboard shortcuts by typing them sequentially)
+    </message>
+    <message name="IDS_SETTINGS_CHROMEVOX_LABEL" desc="Label for checkbox which enables ChromeVox">
+      Enable ChromeVox
+    </message>
+    <message name="IDS_SETTINGS_CHROMEVOX_SUBLABEL" desc="Sub-label describingn what ChromeVox is.">
+      (spoken feedback)
+    </message>
+    <message name="IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL" desc="Label for checkbox which enables the screen magnifier">
+      Enable screen magnifier
+    </message>
+    <message name="IDS_SETTINGS_TAP_DRAGGING_LABEL" desc="Label for checkbox which enables tap dragging.">
+      Enable tap dragging
+    </message>
+    <message name="IDS_SETTINGS_CLICK_ON_STOP_LABEL" desc="Label for checkbox which enables automatically clicking when the mouse pointer stops.">
+      Automatically click when the mouse pointer stops
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL" desc="Label for dropdown menu which contains various time delays for clicks.">
+      Delay before click:
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT" desc="Description of an extremely short delay before clicks.">
+      extremely short
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT" desc="Description of a very short delay before clicks.">
+      very short
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT" desc="Description of a short delay before clicks.">
+      short
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG" desc="Description of a long delay before clicks.">
+      long
+    </message>
+    <message name="IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG" desc="Description of a very long delay before clicks.">
+      very long
+    </message>
+    <message name="IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL" desc="Label for checkbox which enables an on-screen keyboard.">
+      Enable on-screen keyboard
+    </message>
+    <message name="IDS_SETTINGS_ACCESSIBILITY_EXPLANATION" desc="Informational message at the top of the accessibility section of the settings page about enabling additional accessibility-related features.">
+      Enable accessibility features to make your device easier to use.
+    </message>
+  </if>
 
   <!-- Advanced Page -->
   <message name="IDS_SETTINGS_ADVANCED" desc="Name of the settings page which displays advanced preferences.">
@@ -226,16 +231,18 @@
     Date and time are set automatically.
   </message>
 
-  <!-- Internet Page -->
-  <message name="IDS_SETTINGS_INTERNET" desc="Name of the settings page which displays internet preferences.">
-    Internet Connection
-  </message>
-  <message name="IDS_SETTINGS_INTERNET_DETAIL" desc="Name of the settings page which displays network details.">
-    Network Details
-  </message>
-  <message name="IDS_SETTINGS_INTERNET_KNOWN_NETWORKS" desc="Name of the settings page which displays the list of known networks.">
-    Known Networks
-  </message>
+  <if expr="chromeos">
+    <!-- Internet Page -->
+    <message name="IDS_SETTINGS_INTERNET" desc="Name of the settings page which displays internet preferences.">
+      Internet Connection
+    </message>
+    <message name="IDS_SETTINGS_INTERNET_DETAIL" desc="Name of the settings page which displays network details.">
+      Network Details
+    </message>
+    <message name="IDS_SETTINGS_INTERNET_KNOWN_NETWORKS" desc="Name of the settings page which displays the list of known networks.">
+      Known Networks
+    </message>
+  </if>
 
   <!-- On Startup Page -->
   <message name="IDS_SETTINGS_ON_STARTUP" desc="Name of the on startup page.">
diff --git a/chrome/app/theme/README b/chrome/app/theme/README
index 6a0438c..ff029c7 100644
--- a/chrome/app/theme/README
+++ b/chrome/app/theme/README
@@ -24,11 +24,6 @@
 If you are creating an ICO from a set of PNGs of different sizes, the following
 process (using ImageMagick and GIMP) satisfies the above conditions:
 
-**IMPORTANT**: There is an issue with GIMP generating sub-optimal ICO files
-(see http://crbug.com/526622#c35); therefore if you are creating or updating
-icons using the below process, please add mgiuca@chromium.org as a reviewer.
-TODO(mgiuca): Update the tools/process to work around the problem.
-
 1. Convert each of the smaller images to 8-bit. With ImageMagick:
 
     for f in FILENAME-??.png; \
@@ -46,4 +41,5 @@
 4. Run src/tools/resources/optimize-ico-files.py on the resulting .ico file.
 
 You can also run src/tools/resources/optimize-ico-files.py on existing .ico
-files. This will run a basic PNG optimization pass.
+files. This will run a basic PNG optimization pass and fix up any broken image
+masks (http://crbug.com/534679).
diff --git a/chrome/app/theme/default_100_percent/legacy/download_error.png b/chrome/app/theme/default_100_percent/legacy/download_error.png
deleted file mode 100644
index 3f02b21..0000000
--- a/chrome/app/theme/default_100_percent/legacy/download_error.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/download_icon.png b/chrome/app/theme/default_100_percent/legacy/download_icon.png
deleted file mode 100644
index 027b5ec7..0000000
--- a/chrome/app/theme/default_100_percent/legacy/download_icon.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/download_icon_incognito.png b/chrome/app/theme/default_100_percent/legacy/download_icon_incognito.png
deleted file mode 100644
index f62a57bb..0000000
--- a/chrome/app/theme/default_100_percent/legacy/download_icon_incognito.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/download_warning_bad.png b/chrome/app/theme/default_100_percent/legacy/download_warning_bad.png
deleted file mode 100644
index 0c3f166..0000000
--- a/chrome/app/theme/default_100_percent/legacy/download_warning_bad.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/download_warning_unwanted.png b/chrome/app/theme/default_100_percent/legacy/download_warning_unwanted.png
deleted file mode 100644
index 7c1161e..0000000
--- a/chrome/app/theme/default_100_percent/legacy/download_warning_unwanted.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/download_error.png b/chrome/app/theme/default_200_percent/legacy/download_error.png
deleted file mode 100644
index ec1bed9..0000000
--- a/chrome/app/theme/default_200_percent/legacy/download_error.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/download_icon.png b/chrome/app/theme/default_200_percent/legacy/download_icon.png
deleted file mode 100644
index 3652962..0000000
--- a/chrome/app/theme/default_200_percent/legacy/download_icon.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/download_icon_incognito.png b/chrome/app/theme/default_200_percent/legacy/download_icon_incognito.png
deleted file mode 100644
index af1416b..0000000
--- a/chrome/app/theme/default_200_percent/legacy/download_icon_incognito.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/download_warning_bad.png b/chrome/app/theme/default_200_percent/legacy/download_warning_bad.png
deleted file mode 100644
index bcfd8c5..0000000
--- a/chrome/app/theme/default_200_percent/legacy/download_warning_bad.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/download_warning_unwanted.png b/chrome/app/theme/default_200_percent/legacy/download_warning_unwanted.png
deleted file mode 100644
index 02a5706..0000000
--- a/chrome/app/theme/default_200_percent/legacy/download_warning_unwanted.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 33a8ff1..d3c8b85 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -242,21 +242,14 @@
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_BUTTON_RIGHT_TOP_H" file="common/download_button_right_top_hover.png" />
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_BUTTON_RIGHT_TOP_NO_DD" file="common/download_button_right_top_no_dd.png" />
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_BUTTON_RIGHT_TOP_P" file="common/download_button_right_top_pressed.png" />
-      <if expr="is_macosx">
-        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING" file="legacy/download_icon.png" />
-        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_ERROR" file="legacy/download_error.png" />
-        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_INCOGNITO" file="legacy/download_icon_incognito.png" />
-        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_WARNING_BAD" file="legacy/download_warning_bad.png" />
-        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_WARNING_UNWANTED" file="legacy/download_warning_unwanted.png" />
-      </if>
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_CANCEL" file="common/downloads/cancel.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_DELETE" file="common/downloads/delete.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_DOWNLOAD" file="common/downloads/download.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_FOLDER" file="common/downloads/folder.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_PAUSE" file="common/downloads/pause.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="common/download_progress_background32.png" />
-      <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="common/download_progress_foreground32.png" />
       <if expr="chromeos">
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_CANCEL" file="common/downloads/cancel.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_DELETE" file="common/downloads/delete.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_DOWNLOAD" file="common/downloads/download.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_FOLDER" file="common/downloads/folder.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_NOTIFICATION_MENU_PAUSE" file="common/downloads/pause.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="common/download_progress_background32.png" />
+        <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="common/download_progress_foreground32.png" />
         <structure type="chrome_scaled_image" name="IDR_ENABLE_DEBUGGING_FAILURE" file="cros/enable_debugging_failure.png" />
         <structure type="chrome_scaled_image" name="IDR_ENABLE_DEBUGGING_SUCCESS" file="cros/enable_debugging_success.png" />
       </if>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index f66bb8b..8e06e93 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1104,6 +1104,17 @@
     ]
   }
 
+  if (is_android) {
+    sources -= [
+      "password_manager/password_manager_test_base.cc",
+      "password_manager/password_manager_test_base.h",
+      "sessions/session_service_test_helper.cc",
+      "sessions/session_service_test_helper.h",
+      "ui/webui/signin/login_ui_test_utils.cc",
+      "ui/webui/signin/login_ui_test_utils.h",
+    ]
+  }
+
   if (enable_extensions) {
     sources += [
       "extensions/extension_action_test_util.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f5907e7..1730008 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -420,7 +420,6 @@
 #endif
 
 #if defined(OS_CHROMEOS)
-
 const Experiment::Choice kAshMaterialDesignInkDropAnimationSpeed[] = {
     {IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", ""},
     {IDS_FLAGS_MATERIAL_DESIGN_INK_DROP_ANIMATION_FAST,
@@ -480,7 +479,6 @@
     keyboard::switches::kGestureEditing,
     keyboard::switches::kGestureEditingEnabled},
 };
-#endif
 
 const Experiment::Choice kDownloadNotificationChoices[] = {
   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
@@ -491,6 +489,7 @@
     switches::kEnableDownloadNotification,
     "disabled" }
 };
+#endif
 
 const Experiment::Choice kSupervisedUserSafeSitesChoices[] = {
   { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
@@ -539,6 +538,26 @@
 };
 #endif  // defined(OS_CHROMEOS)
 
+#if defined(OS_WIN)
+const Experiment::Choice kPpapiWin32kLockdown[] = {
+    {IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", ""},
+    {IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
+     switches::kEnableWin32kLockDownMimeTypes, ""},
+    {IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_FLASH_ONLY,
+     switches::kEnableWin32kLockDownMimeTypes,
+     "application/x-shockwave-flash,application/futuresplash"},
+    {IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_PDF_ONLY,
+     switches::kEnableWin32kLockDownMimeTypes,
+     "application/x-google-chrome-pdf,application/pdf"},
+    {IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_FLASH_AND_PDF,
+     switches::kEnableWin32kLockDownMimeTypes,
+     "application/x-shockwave-flash,application/futuresplash,"
+     "application/x-google-chrome-pdf,application/pdf"},
+    {IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_ALL,
+     switches::kEnableWin32kLockDownMimeTypes, "*"},
+};
+#endif  // defined(OS_WIN)
+
 // RECORDING USER METRICS FOR FLAGS:
 // -----------------------------------------------------------------------------
 // The first line of the experiment is the internal name. If you'd like to
@@ -874,11 +893,13 @@
      IDS_FLAGS_ENABLE_DOWNLOAD_RESUMPTION_DESCRIPTION,
      kOsDesktop,
      SINGLE_VALUE_TYPE(switches::kEnableDownloadResumption)},
+#if defined(OS_CHROMEOS)
     {"enable-download-notification",
      IDS_FLAGS_ENABLE_DOWNLOAD_NOTIFICATION_NAME,
      IDS_FLAGS_ENABLE_DOWNLOAD_NOTIFICATION_DESCRIPTION,
-     kOsDesktop,
+     kOsCrOS,
      MULTI_VALUE_TYPE(kDownloadNotificationChoices)},
+#endif
 #if defined(ENABLE_PLUGINS)
     {"allow-nacl-socket-api",
      IDS_FLAGS_ALLOW_NACL_SOCKET_API_NAME,
@@ -1737,13 +1758,8 @@
     {"disable-delay-agnostic-aec",
      IDS_FLAGS_DISABLE_DELAY_AGNOSTIC_AEC_NAME,
      IDS_FLAGS_DISABLE_DELAY_AGNOSTIC_AEC_DESCRIPTION,
-     kOsWin | kOsLinux | kOsCrOS,
+     kOsWin | kOsLinux | kOsCrOS | kOsMac,
      SINGLE_VALUE_TYPE(switches::kDisableDelayAgnosticAec)},
-    {"enable-delay-agnostic-aec",
-     IDS_FLAGS_ENABLE_DELAY_AGNOSTIC_AEC_NAME,
-     IDS_FLAGS_ENABLE_DELAY_AGNOSTIC_AEC_DESCRIPTION,
-     kOsMac,
-     SINGLE_VALUE_TYPE(switches::kEnableDelayAgnosticAec)},
     {"mark-non-secure-as",  // FLAGS:RECORD_UMA
      IDS_MARK_NON_SECURE_AS_NAME,
      IDS_MARK_NON_SECURE_AS_DESCRIPTION,
@@ -2077,6 +2093,12 @@
      kOsCrOS,
      MULTI_VALUE_TYPE(kCrosRegionsModeChoices)},
 #endif  // OS_CHROMEOS
+#if defined(OS_WIN)
+    {"enable-ppapi-win32k-lockdown",
+     IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_NAME,
+     IDS_FLAGS_PPAPI_WIN32K_LOCKDOWN_DESCRIPTION, kOsWin,
+     MULTI_VALUE_TYPE(kPpapiWin32kLockdown)},
+#endif  // defined(OS_WIN)
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms.xml. See note in
     // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index 1fb8fcf3..b13e78b 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -8,8 +8,10 @@
 #include "base/android/jni_string.h"
 #include "base/command_line.h"
 #include "chrome/browser/android/feature_utilities.h"
+#include "chrome/browser/android/hung_renderer_infobar_delegate.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/file_select_helper.h"
+#include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/media_stream_capture_indicator.h"
 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
@@ -19,12 +21,12 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/android/bluetooth_chooser_android.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "chrome/browser/ui/tab_helpers.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/app_modal/javascript_dialog_manager.h"
+#include "components/infobars/core/infobar.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
@@ -72,6 +74,16 @@
           static_cast<int>(rect.bottom())));
 }
 
+infobars::InfoBar* FindHungRendererInfoBar(InfoBarService* infobar_service) {
+  DCHECK(infobar_service);
+  for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
+    infobars::InfoBar* infobar = infobar_service->infobar_at(i);
+    if (infobar->delegate()->AsHungRendererInfoBarDelegate())
+      return infobar;
+  }
+  return nullptr;
+}
+
 }  // anonymous namespace
 
 namespace chrome {
@@ -154,8 +166,7 @@
 
   return static_cast<blink::WebDisplayMode>(
       Java_ChromeWebContentsDelegateAndroid_getDisplayMode(
-          env, obj.obj())
-    );
+          env, obj.obj()));
 }
 
 void ChromeWebContentsDelegateAndroid::FindReply(
@@ -386,6 +397,36 @@
 }  // namespace android
 }  // namespace chrome
 
+void OnRendererUnresponsive(JNIEnv* env,
+                            const JavaParamRef<jclass>& clazz,
+                            const JavaParamRef<jobject>& java_web_contents) {
+  content::WebContents* web_contents =
+        content::WebContents::FromJavaWebContents(java_web_contents);
+  InfoBarService* infobar_service =
+      InfoBarService::FromWebContents(web_contents);
+  DCHECK(!FindHungRendererInfoBar(infobar_service));
+  HungRendererInfoBarDelegate::Create(infobar_service,
+                                      web_contents->GetRenderProcessHost());
+}
+
+void OnRendererResponsive(JNIEnv* env,
+                          const JavaParamRef<jclass>& clazz,
+                          const JavaParamRef<jobject>& java_web_contents) {
+  content::WebContents* web_contents =
+          content::WebContents::FromJavaWebContents(java_web_contents);
+  InfoBarService* infobar_service =
+      InfoBarService::FromWebContents(web_contents);
+  infobars::InfoBar* hung_renderer_infobar =
+      FindHungRendererInfoBar(infobar_service);
+  if (!hung_renderer_infobar)
+    return;
+
+  hung_renderer_infobar->delegate()
+      ->AsHungRendererInfoBarDelegate()
+      ->OnRendererResponsive();
+  infobar_service->RemoveInfoBar(hung_renderer_infobar);
+}
+
 jboolean IsCapturingAudio(JNIEnv* env,
                           const JavaParamRef<jclass>& clazz,
                           const JavaParamRef<jobject>& java_web_contents) {
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index 84f7b2b7..e690b02 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -57,9 +57,8 @@
 const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: ";
 const char kDoPreventPreloadValue[] = "1";
 
-// The number of characters that should be shown on each side of the selected
-// expression.
-const int kSurroundingSizeForUI = 30;
+// The number of characters that should be shown after the selected expression.
+const int kSurroundingSizeForUI = 60;
 
 } // namespace
 
@@ -337,13 +336,6 @@
 void ContextualSearchDelegate::SendSurroundingText(int max_surrounding_chars) {
   const base::string16& surrounding = context_->surrounding_text;
 
-  // Determine the text before the selection.
-  int num_before_characters =
-      std::min(context_->start_offset, max_surrounding_chars);
-  int start_position = context_->start_offset - num_before_characters;
-  base::string16 before_text =
-      surrounding.substr(start_position, num_before_characters);
-
   // Determine the text after the selection.
   int surrounding_length = surrounding.length();  // Cast to int.
   int num_after_characters = std::min(
@@ -351,9 +343,8 @@
   base::string16 after_text = surrounding.substr(
       context_->end_offset, num_after_characters);
 
-  base::TrimWhitespace(before_text, base::TRIM_ALL, &before_text);
   base::TrimWhitespace(after_text, base::TRIM_ALL, &after_text);
-  surrounding_callback_.Run(UTF16ToUTF8(before_text), UTF16ToUTF8(after_text));
+  surrounding_callback_.Run(UTF16ToUTF8(after_text));
 }
 
 void ContextualSearchDelegate::SetDiscourseContextAndAddToHeader(
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.h b/chrome/browser/android/contextualsearch/contextual_search_delegate.h
index 8714afe..13b26ee 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.h
@@ -35,8 +35,7 @@
                               bool,
                               int,
                               int)> SearchTermResolutionCallback;
-  typedef base::Callback<
-      void(const std::string&, const std::string&)> SurroundingTextCallback;
+  typedef base::Callback<void(const std::string&)> SurroundingTextCallback;
   typedef base::Callback<
       void(const base::string16&, int, int)>
       HandleSurroundingsCallback;
@@ -90,6 +89,8 @@
   FRIEND_TEST_ALL_PREFIXES(ContextualSearchDelegateTest,
                            SurroundingTextNoBeforeText);
   FRIEND_TEST_ALL_PREFIXES(ContextualSearchDelegateTest,
+                           SurroundingTextNoAfterText);
+  FRIEND_TEST_ALL_PREFIXES(ContextualSearchDelegateTest,
                            ExtractMentionsStartEnd);
   FRIEND_TEST_ALL_PREFIXES(ContextualSearchDelegateTest,
                            SurroundingTextForIcing);
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate_unittest.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate_unittest.cc
index f2ff8c4..92f63e37 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate_unittest.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate_unittest.cc
@@ -133,7 +133,6 @@
   std::string display_text() { return display_text_; }
   std::string alternate_term() { return alternate_term_; }
   bool do_prevent_preload() { return prevent_preload_; }
-  std::string before_text() { return before_text_; }
   std::string after_text() { return after_text_; }
   int start_adjust() { return start_adjust_; }
   int end_adjust() { return end_adjust_; }
@@ -160,9 +159,7 @@
     end_adjust_ = end_adjust;
   }
 
-  void recordSurroundingText(const std::string& before_text,
-                             const std::string& after_text) {
-    before_text_ = before_text;
+  void recordSurroundingText(const std::string& after_text) {
     after_text_ = after_text;
   }
 
@@ -181,7 +178,6 @@
   bool prevent_preload_;
   int start_adjust_;
   int end_adjust_;
-  std::string before_text_;
   std::string after_text_;
 
   base::MessageLoopForIO io_message_loop_;
@@ -395,7 +391,6 @@
   base::string16 surrounding = base::ASCIIToUTF16("aa bb Bogus dd ee");
   SetSurroundingContext(surrounding, 6, 11);
   delegate_->SendSurroundingText(30);  // High maximum # of surrounding chars.
-  EXPECT_EQ("aa bb", before_text());
   EXPECT_EQ("dd ee", after_text());
 }
 
@@ -404,7 +399,6 @@
   SetSurroundingContext(surrounding, 6, 11);
   delegate_->SendSurroundingText(3);  // Low maximum # of surrounding chars.
   // Whitespaces are trimmed.
-  EXPECT_EQ("bb", before_text());
   EXPECT_EQ("dd", after_text());
 }
 
@@ -412,10 +406,16 @@
   base::string16 surrounding = base::ASCIIToUTF16("Bogus ee ff gg");
   SetSurroundingContext(surrounding, 0, 5);
   delegate_->SendSurroundingText(5);
-  EXPECT_EQ("", before_text());
   EXPECT_EQ("ee f", after_text());
 }
 
+TEST_F(ContextualSearchDelegateTest, SurroundingTextNoAfterText) {
+  base::string16 surrounding = base::ASCIIToUTF16("aa bb Bogus");
+  SetSurroundingContext(surrounding, 6, 11);
+  delegate_->SendSurroundingText(5);
+  EXPECT_EQ("", after_text());
+}
+
 TEST_F(ContextualSearchDelegateTest, ExtractMentionsStartEnd) {
   ListValue mentions_list;
   mentions_list.AppendInteger(1);
diff --git a/chrome/browser/android/contextualsearch/contextual_search_manager.cc b/chrome/browser/android/contextualsearch/contextual_search_manager.cc
index be8f127..c8b41ab 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_manager.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_manager.cc
@@ -113,17 +113,13 @@
 }
 
 void ContextualSearchManager::OnSurroundingTextAvailable(
-    const std::string& before_text,
     const std::string& after_text) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  base::android::ScopedJavaLocalRef<jstring> j_before_text =
-      base::android::ConvertUTF8ToJavaString(env, before_text.c_str());
   base::android::ScopedJavaLocalRef<jstring> j_after_text =
       base::android::ConvertUTF8ToJavaString(env, after_text.c_str());
   Java_ContextualSearchManager_onSurroundingTextAvailable(
       env,
       java_manager_.obj(),
-      j_before_text.obj(),
       j_after_text.obj());
 }
 
diff --git a/chrome/browser/android/contextualsearch/contextual_search_manager.h b/chrome/browser/android/contextualsearch/contextual_search_manager.h
index f9e7603..08a2e3d 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_manager.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_manager.h
@@ -58,8 +58,7 @@
                                       int selection_end_adjust);
 
   // Calls back to Java with the surrounding text to be displayed.
-  void OnSurroundingTextAvailable(const std::string& before_text,
-                                  const std::string& after_text);
+  void OnSurroundingTextAvailable(const std::string& after_text);
 
   // Calls back to Java with notification for Icing selection.
   void OnIcingSelectionAvailable(const std::string& encoding,
diff --git a/chrome/browser/android/popular_sites.cc b/chrome/browser/android/popular_sites.cc
index aeda57d7..f2fcc2d 100644
--- a/chrome/browser/android/popular_sites.cc
+++ b/chrome/browser/android/popular_sites.cc
@@ -13,6 +13,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/file_downloader.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -21,6 +22,7 @@
 #include "components/search_engines/search_engine_type.h"
 #include "components/search_engines/template_url_prepopulate_data.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/variations/service/variations_service.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
@@ -35,9 +37,11 @@
 
 
 // Find out the country code of the user by using the Google country code if
-// Google is the default search engine set. Fallback to a default if we can't
+// Google is the default search engine set. If Google is not the default search,
+// use the country provided Fallback to a default if we can't
 // make an educated guess.
-std::string GetCountryCode(Profile* profile) {
+std::string GetCountryCode(Profile* profile,
+                           const std::string& fallback_country) {
   DCHECK(profile);
 
   const TemplateURLService* template_url_service =
@@ -55,28 +59,29 @@
       *default_provider, template_url_service->search_terms_data()) ==
           SearchEngineType::SEARCH_ENGINE_GOOGLE;
 
-  if (!is_google_search_engine)
-    return kPopularSitesDefaultCountryCode;
+  if (is_google_search_engine) {
+    GURL search_url = default_provider->GenerateSearchURL(
+        template_url_service->search_terms_data());
+    return base::ToUpperASCII(google_util::GetGoogleCountryCode(search_url));
+  }
 
-  GURL search_url = default_provider->GenerateSearchURL(
-      template_url_service->search_terms_data());
+  if (!fallback_country.empty())
+    return base::ToUpperASCII(fallback_country);
 
-  std::string country_code =
-      base::ToUpperASCII(google_util::GetGoogleCountryCode(search_url));
-
-  return country_code;
+  return kPopularSitesDefaultCountryCode;
 }
 
-std::string GetPopularSitesServerFilename(
-    Profile* profile,
-    const std::string& override_country,
-    const std::string& override_version,
-    const std::string& override_filename) {
+std::string GetPopularSitesServerFilename(Profile* profile,
+                                          const std::string& override_country,
+                                          const std::string& override_version,
+                                          const std::string& override_filename,
+                                          const std::string& fallback_country) {
   if (!override_filename.empty())
     return override_filename;
 
-  std::string country = !override_country.empty() ? override_country
-                                                  : GetCountryCode(profile);
+  std::string country = !override_country.empty()
+                            ? override_country
+                            : GetCountryCode(profile, fallback_country);
   std::string version = !override_version.empty() ? override_version
                                                   : kPopularSitesDefaultVersion;
   return base::StringPrintf(kPopularSitesServerFilenameFormat,
@@ -86,12 +91,13 @@
 GURL GetPopularSitesURL(Profile* profile,
                         const std::string& override_country,
                         const std::string& override_version,
-                        const std::string& override_filename) {
-  return GURL(base::StringPrintf(kPopularSitesURLFormat,
-      GetPopularSitesServerFilename(profile,
-                                    override_country,
-                                    override_version,
-                                    override_filename).c_str()));
+                        const std::string& override_filename,
+                        const std::string& fallback_country) {
+  return GURL(base::StringPrintf(
+      kPopularSitesURLFormat,
+      GetPopularSitesServerFilename(profile, override_country, override_version,
+                                    override_filename, fallback_country)
+          .c_str()));
 }
 
 base::FilePath GetPopularSitesPath() {
@@ -100,6 +106,16 @@
   return dir.AppendASCII(kPopularSitesLocalFilename);
 }
 
+// Get the country that the experiment is running under
+std::string GetVariationsServiceCountry() {
+  DCHECK(g_browser_process);
+  variations::VariationsService* variations_service =
+      g_browser_process->variations_service();
+  if (variations_service)
+    return variations_service->GetStoredPermanentCountry();
+  return std::string();
+}
+
 scoped_ptr<std::vector<PopularSites::Site>> ReadAndParseJsonFile(
     const base::FilePath& path) {
   std::string json;
@@ -161,9 +177,10 @@
   // Re-download the file once on every Chrome startup, but use the cached
   // local file afterwards.
   static bool first_time = true;
-  FetchPopularSites(GetPopularSitesURL(profile, override_country,
-                                       override_version, override_filename),
-                    profile->GetRequestContext(), first_time || force_download);
+  FetchPopularSites(
+      GetPopularSitesURL(profile, override_country, override_version,
+                         override_filename, GetVariationsServiceCountry()),
+      profile->GetRequestContext(), first_time || force_download);
   first_time = false;
 }
 
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc
index b1a54f11..963a006 100644
--- a/chrome/browser/android/preferences/pref_service_bridge.cc
+++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -462,20 +462,20 @@
 static jboolean GetMetricsReportingEnabled(JNIEnv* env,
                                            const JavaParamRef<jobject>& obj) {
   PrefService* local_state = g_browser_process->local_state();
-  return local_state->GetBoolean(prefs::kMetricsReportingEnabled);
+  return local_state->GetBoolean(metrics::prefs::kMetricsReportingEnabled);
 }
 
 static void SetMetricsReportingEnabled(JNIEnv* env,
                                        const JavaParamRef<jobject>& obj,
                                        jboolean enabled) {
   PrefService* local_state = g_browser_process->local_state();
-  local_state->SetBoolean(prefs::kMetricsReportingEnabled, enabled);
+  local_state->SetBoolean(metrics::prefs::kMetricsReportingEnabled, enabled);
 }
 
 static jboolean HasSetMetricsReporting(JNIEnv* env,
                                        const JavaParamRef<jobject>& obj) {
   PrefService* local_state = g_browser_process->local_state();
-  return local_state->HasPrefPath(prefs::kMetricsReportingEnabled);
+  return local_state->HasPrefPath(metrics::prefs::kMetricsReportingEnabled);
 }
 
 namespace {
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index 7c5b0b7..bd724ac5 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -12,7 +12,6 @@
 #include "cc/layers/layer.h"
 #include "chrome/browser/android/chrome_web_contents_delegate_android.h"
 #include "chrome/browser/android/compositor/tab_content_manager.h"
-#include "chrome/browser/android/hung_renderer_infobar_delegate.h"
 #include "chrome/browser/android/metrics/uma_utils.h"
 #include "chrome/browser/android/offline_pages/offline_page_bridge.h"
 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
@@ -55,8 +54,6 @@
 #include "components/bookmarks/managed/managed_bookmark_service.h"
 #include "components/dom_distiller/core/url_utils.h"
 #include "components/favicon/content/content_favicon_driver.h"
-#include "components/infobars/core/infobar.h"
-#include "components/infobars/core/infobar_container.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/navigation_interception/navigation_params.h"
 #include "components/offline_pages/offline_page_feature.h"
@@ -104,16 +101,6 @@
 const int kImageSearchThumbnailMaxWidth = 600;
 const int kImageSearchThumbnailMaxHeight = 600;
 
-infobars::InfoBar* FindHungRendererInfoBar(InfoBarService* infobar_service) {
-  DCHECK(infobar_service);
-  for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
-    infobars::InfoBar* infobar = infobar_service->infobar_at(i);
-    if (infobar->delegate()->AsHungRendererInfoBarDelegate())
-      return infobar;
-  }
-  return nullptr;
-}
-
 }  // namespace
 
 TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
@@ -400,7 +387,7 @@
   if (favicon.empty())
     return;
 
-  JNIEnv *env = base::android::AttachCurrentThread();
+  JNIEnv* env = base::android::AttachCurrentThread();
   Java_Tab_onFaviconAvailable(env, weak_java_tab_.get(env).obj(),
                               gfx::ConvertToJavaBitmap(&favicon).obj());
 }
@@ -568,7 +555,7 @@
   if (prerender_manager) {
     bool prefetched_page_loaded = HasPrerenderedUrl(gurl);
     // Getting the load status before MaybeUsePrerenderedPage() b/c it resets.
-    chrome::NavigateParams params(NULL, web_contents());
+    chrome::NavigateParams params(web_contents());
     InstantSearchPrerenderer* prerenderer =
         InstantSearchPrerenderer::GetForProfile(GetProfile());
     if (prerenderer) {
@@ -683,7 +670,6 @@
 
 ScopedJavaLocalRef<jobject> TabAndroid::GetFavicon(JNIEnv* env,
                                                    jobject obj) {
-
   ScopedJavaLocalRef<jobject> bitmap;
   favicon::FaviconDriver* favicon_driver =
       favicon::ContentFaviconDriver::FromWebContents(web_contents_.get());
@@ -872,28 +858,6 @@
   return HasPrerenderedUrl(gurl);
 }
 
-void TabAndroid::OnRendererUnresponsive(JNIEnv* env, jobject obj) {
-  InfoBarService* infobar_service =
-      InfoBarService::FromWebContents(web_contents());
-  DCHECK(!FindHungRendererInfoBar(infobar_service));
-  HungRendererInfoBarDelegate::Create(infobar_service,
-                                      web_contents()->GetRenderProcessHost());
-}
-
-void TabAndroid::OnRendererResponsive(JNIEnv* env, jobject obj) {
-  InfoBarService* infobar_service =
-      InfoBarService::FromWebContents(web_contents());
-  infobars::InfoBar* hung_renderer_infobar =
-      FindHungRendererInfoBar(infobar_service);
-  if (!hung_renderer_infobar)
-    return;
-
-  hung_renderer_infobar->delegate()
-      ->AsHungRendererInfoBarDelegate()
-      ->OnRendererResponsive();
-  infobar_service->RemoveInfoBar(hung_renderer_infobar);
-}
-
 namespace {
 
 class ChromeInterceptNavigationDelegate : public InterceptNavigationDelegate {
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 8c992233..0642fee9 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -122,9 +122,6 @@
 
   bool HasPrerenderedUrl(GURL gurl);
 
-  void OnRendererUnresponsive(JNIEnv* env, jobject obj);
-  void OnRendererResponsive(JNIEnv* env, jobject obj);
-
   void MakeLoadURLParams(
       chrome::NavigateParams* params,
       content::NavigationController::LoadURLParams* load_url_params);
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index b93aea0..c304151 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -25,6 +25,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
diff --git a/chrome/browser/apps/app_url_redirector.cc b/chrome/browser/apps/app_url_redirector.cc
index cf15169..63962933 100644
--- a/chrome/browser/apps/app_url_redirector.cc
+++ b/chrome/browser/apps/app_url_redirector.cc
@@ -9,22 +9,18 @@
 #include "base/logging.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
-#include "components/navigation_interception/intercept_navigation_resource_throttle.h"
+#include "components/navigation_interception/intercept_navigation_throttle.h"
 #include "components/navigation_interception/navigation_params.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/browser/resource_throttle.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
-#include "extensions/browser/info_map.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "net/url_request/url_request.h"
 
 using content::BrowserThread;
-using content::ResourceRequestInfo;
 using content::WebContents;
 using extensions::Extension;
 using extensions::UrlHandlers;
@@ -55,8 +51,8 @@
   }
 
   // These are guaranteed by CreateThrottleFor below.
-  DCHECK(!params.is_post());
   DCHECK(UrlHandlers::CanExtensionHandleUrl(app.get(), params.url()));
+  DCHECK(!params.is_post());
 
   Profile* profile =
       Profile::FromBrowserContext(source->GetBrowserContext());
@@ -73,57 +69,54 @@
 }  // namespace
 
 // static
-content::ResourceThrottle*
-AppUrlRedirector::MaybeCreateThrottleFor(net::URLRequest* request,
-                                         ProfileIOData* profile_io_data) {
-  DVLOG(1) << "Considering URL for redirection: "
-           << request->method() << " " << request->url().spec();
+scoped_ptr<content::NavigationThrottle>
+AppUrlRedirector::MaybeCreateThrottleFor(content::NavigationHandle* handle) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DVLOG(1) << "Considering URL for redirection: " << handle->GetURL().spec();
+
+  content::BrowserContext* browser_context =
+      handle->GetWebContents()->GetBrowserContext();
+  DCHECK(browser_context);
 
   // Support only GET for now.
-  if (request->method() != "GET") {
+  if (handle->IsPost()) {
     DVLOG(1) << "Skip redirection: method is not GET";
-    return NULL;
+    return nullptr;
   }
 
-  if (!request->url().SchemeIsHTTPOrHTTPS()) {
+  if (!handle->GetURL().SchemeIsHTTPOrHTTPS()) {
     DVLOG(1) << "Skip redirection: scheme is not HTTP or HTTPS";
-    return NULL;
-  }
-
-  // The user has indicated that a URL should be force downloaded. Turn off
-  // URL redirection in this case.
-  if (ResourceRequestInfo::ForRequest(request)->IsDownload()) {
-    DVLOG(1) << "Skip redirection: request is a forced download";
-    return NULL;
+    return nullptr;
   }
 
   // Never redirect URLs to apps in incognito. Technically, apps are not
   // supported in incognito, but that may change in future.
   // See crbug.com/240879, which tracks incognito support for v2 apps.
-  if (profile_io_data->IsOffTheRecord()) {
+  Profile* profile = Profile::FromBrowserContext(browser_context);
+  if (profile->GetProfileType() == Profile::INCOGNITO_PROFILE) {
     DVLOG(1) << "Skip redirection: unsupported in incognito";
-    return NULL;
+    return nullptr;
   }
 
-  const extensions::ExtensionSet& extensions =
-      profile_io_data->GetExtensionInfoMap()->extensions();
-  for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
-       iter != extensions.end();
-       ++iter) {
+  const extensions::ExtensionSet& enabled_extensions =
+      extensions::ExtensionRegistry::Get(browser_context)->enabled_extensions();
+  for (extensions::ExtensionSet::const_iterator iter =
+           enabled_extensions.begin();
+       iter != enabled_extensions.end(); ++iter) {
     const UrlHandlerInfo* handler =
-        UrlHandlers::FindMatchingUrlHandler(iter->get(), request->url());
+        UrlHandlers::FindMatchingUrlHandler(iter->get(), handle->GetURL());
     if (handler) {
       DVLOG(1) << "Found matching app handler for redirection: "
                << (*iter)->name() << "(" << (*iter)->id() << "):"
                << handler->id;
-      return new navigation_interception::InterceptNavigationResourceThrottle(
-          request,
-          base::Bind(&LaunchAppWithUrl,
-                     scoped_refptr<const Extension>(*iter),
-                     handler->id));
+      return scoped_ptr<content::NavigationThrottle>(
+          new navigation_interception::InterceptNavigationThrottle(
+              handle,
+              base::Bind(&LaunchAppWithUrl,
+                         scoped_refptr<const Extension>(*iter), handler->id)));
     }
   }
 
   DVLOG(1) << "Skipping redirection: no matching app handler found";
-  return NULL;
+  return nullptr;
 }
diff --git a/chrome/browser/apps/app_url_redirector.h b/chrome/browser/apps/app_url_redirector.h
index 331d7b42..629af37 100644
--- a/chrome/browser/apps/app_url_redirector.h
+++ b/chrome/browser/apps/app_url_redirector.h
@@ -6,24 +6,22 @@
 #define CHROME_BROWSER_APPS_APP_URL_REDIRECTOR_H_
 
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/navigation_throttle.h"
 
 namespace content {
-class ResourceThrottle;
+class NavigationHandle;
+class NavigationThrottle;
+class WebContents;
 }
 
-namespace net {
-class URLRequest;
-}
-
-class ProfileIOData;
-
-// This class creates resource throttles that redirect URLs to apps that
-// have a matching URL handler in the 'url_handlers' manifest key.
+// This class creates navigation throttles that redirect URLs to apps that have
+// a matching URL handler in the 'url_handlers' manifest key. Note that this is
+// a UI thread class.
 class AppUrlRedirector {
  public:
-  static content::ResourceThrottle* MaybeCreateThrottleFor(
-      net::URLRequest* request,
-      ProfileIOData* profile_io_data);
+  static scoped_ptr<content::NavigationThrottle> MaybeCreateThrottleFor(
+      content::NavigationHandle* handle);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AppUrlRedirector);
diff --git a/chrome/browser/apps/app_url_redirector_browsertest.cc b/chrome/browser/apps/app_url_redirector_browsertest.cc
index 43721da..1d18ba9 100644
--- a/chrome/browser/apps/app_url_redirector_browsertest.cc
+++ b/chrome/browser/apps/app_url_redirector_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/win/windows_version.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
diff --git a/chrome/browser/apps/drive/drive_app_converter_browsertest.cc b/chrome/browser/apps/drive/drive_app_converter_browsertest.cc
index 867b82a..890dec9f 100644
--- a/chrome/browser/apps/drive/drive_app_converter_browsertest.cc
+++ b/chrome/browser/apps/drive/drive_app_converter_browsertest.cc
@@ -116,7 +116,7 @@
   EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(app));
   EXPECT_EQ(extensions::LAUNCH_CONTAINER_TAB,
             AppLaunchInfo::GetLaunchContainer(app));
-  EXPECT_EQ(0u, app->permissions_data()->active_permissions()->apis().size());
+  EXPECT_EQ(0u, app->permissions_data()->active_permissions().apis().size());
   EXPECT_EQ(1u, extensions::IconsInfo::GetIcons(app).map().size());
 
   const Extension* installed = extensions::ExtensionSystem::Get(profile())
diff --git a/chrome/browser/apps/ephemeral_app_launcher.cc b/chrome/browser/apps/ephemeral_app_launcher.cc
index b9192fb..c9d4fa06 100644
--- a/chrome/browser/apps/ephemeral_app_launcher.cc
+++ b/chrome/browser/apps/ephemeral_app_launcher.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
@@ -167,8 +168,8 @@
       parent_window_(parent_window),
       dummy_web_contents_(
           WebContents::Create(WebContents::CreateParams(profile))) {
-   if (parent_window_)
-     parent_window_tracker_ = NativeWindowTracker::Create(parent_window);
+  if (parent_window_)
+    parent_window_tracker_ = NativeWindowTracker::Create(parent_window);
 }
 
 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id,
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 478b3d1..8c3491f 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1625,6 +1625,27 @@
             GetGuestWebContents()->GetLastCommittedURL());
 }
 
+// A navigation to a web-safe URL should succeed, even if it is not renderer-
+// initiated, such as a navigation from the PDF viewer.
+IN_PROC_BROWSER_TEST_F(WebViewTest, OpenURLFromTab_CurrentTab_Succeed) {
+  LoadAppWithGuest("web_view/simple");
+
+  // Verify that OpenURLFromTab with a window disposition of CURRENT_TAB will
+  // navigate the current <webview>.
+  ExtensionTestMessageListener load_listener("WebViewTest.LOADSTOP", false);
+
+  GURL test_url("http://www.google.com");
+  content::OpenURLParams params(test_url, content::Referrer(), CURRENT_TAB,
+                                ui::PAGE_TRANSITION_AUTO_TOPLEVEL,
+                                false /* is_renderer_initiated */);
+  GetGuestWebContents()->GetDelegate()->OpenURLFromTab(GetGuestWebContents(),
+                                                       params);
+
+  ASSERT_TRUE(load_listener.WaitUntilSatisfied());
+
+  EXPECT_EQ(test_url, GetGuestWebContents()->GetLastCommittedURL());
+}
+
 IN_PROC_BROWSER_TEST_F(WebViewNewWindowTest, OpenURLFromTab_NewWindow_Abort) {
   LoadAppWithGuest("web_view/simple");
 
diff --git a/chrome/browser/autocomplete/autocomplete_browsertest.cc b/chrome/browser/autocomplete/autocomplete_browsertest.cc
index 3063925..5046dff 100644
--- a/chrome/browser/autocomplete/autocomplete_browsertest.cc
+++ b/chrome/browser/autocomplete/autocomplete_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/history/core/browser/history_service.h"
@@ -53,7 +54,7 @@
 class AutocompleteBrowserTest : public ExtensionBrowserTest {
  protected:
   void WaitForTemplateURLServiceToLoad() {
-    ui_test_utils::WaitForTemplateURLServiceToLoad(
+    search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(browser()->profile()));
   }
 
diff --git a/chrome/browser/autocomplete/history_quick_provider_unittest.cc b/chrome/browser/autocomplete/history_quick_provider_unittest.cc
index b88f076..acdf836 100644
--- a/chrome/browser/autocomplete/history_quick_provider_unittest.cc
+++ b/chrome/browser/autocomplete/history_quick_provider_unittest.cc
@@ -233,6 +233,9 @@
   bookmarks::test::WaitForBookmarkModelToLoad(
       BookmarkModelFactory::GetForProfile(profile_.get()));
   profile_->BlockUntilHistoryIndexIsRefreshed();
+  // History index refresh creates rebuilt tasks to run on history thread.
+  // Block here to make sure that all of them are complete.
+  profile_->BlockUntilHistoryProcessesPendingRequests();
   history_service_ = HistoryServiceFactory::GetForProfile(
       profile_.get(), ServiceAccessType::EXPLICIT_ACCESS);
   EXPECT_TRUE(history_service_);
@@ -248,6 +251,10 @@
 
 void HistoryQuickProviderTest::TearDown() {
   provider_ = NULL;
+  // History index rebuild task is created from main thread during SetUp,
+  // performed on DB thread and must be deleted on main thread.
+  // Run main loop to process delete task, to prevent leaks.
+  base::MessageLoop::current()->RunUntilIdle();
 }
 
 void HistoryQuickProviderTest::GetTestData(size_t* data_count,
diff --git a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
index d01df8f..4ac93bc5 100644
--- a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
@@ -11,8 +11,8 @@
 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chrome/test/base/ui_test_utils.h"
 #include "components/omnibox/browser/shortcuts_database.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/test/test_browser_thread.h"
@@ -126,7 +126,7 @@
       &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
   TemplateURLService* template_url_service =
       TemplateURLServiceFactory::GetForProfile(&profile_);
-  ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
 }
 
 void ShortcutsBackendTest::TearDown() {
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index 20e6d14..ecd5e80 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc
index 1c41c0a4..9b87387 100644
--- a/chrome/browser/background/background_application_list_model_unittest.cc
+++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -117,10 +117,9 @@
 
   scoped_refptr<Extension> temporary =
       CreateExtension(GenerateUniqueExtensionName(), true);
-  const extensions::PermissionSet* permissions =
-      temporary->permissions_data()->active_permissions();
   extensions::PermissionsUpdater(service->profile())
-      .AddPermissions(extension, permissions);
+      .AddPermissions(extension,
+                      temporary->permissions_data()->active_permissions());
 }
 
 void RemoveBackgroundPermission(ExtensionService* service,
diff --git a/chrome/browser/background/background_mode_manager_unittest.cc b/chrome/browser/background/background_mode_manager_unittest.cc
index 1b31cfd..2344a25b 100644
--- a/chrome/browser/background/background_mode_manager_unittest.cc
+++ b/chrome/browser/background/background_mode_manager_unittest.cc
@@ -30,7 +30,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_unittest_util.h"
 #include "ui/message_center/message_center.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 02896d6..5a6d7fd6 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -822,9 +822,8 @@
                                std::string());
 #endif  // defined(OS_CHROMEOS)
 #if !defined(OS_CHROMEOS)
-  registry->RegisterBooleanPref(
-      prefs::kMetricsReportingEnabled,
-      GoogleUpdateSettings::GetCollectStatsConsent());
+  registry->RegisterBooleanPref(metrics::prefs::kMetricsReportingEnabled,
+                                GoogleUpdateSettings::GetCollectStatsConsent());
 #endif  // !defined(OS_CHROMEOS)
 
 #if defined(OS_ANDROID)
@@ -1006,7 +1005,7 @@
   // whenever the preference or its controlling policy changes.
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
   pref_change_registrar_.Add(
-      prefs::kMetricsReportingEnabled,
+      metrics::prefs::kMetricsReportingEnabled,
       base::Bind(&BrowserProcessImpl::ApplyMetricsReportingPolicy,
                  base::Unretained(this)));
 #endif
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index d99d8f13..825fa8e4 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -32,7 +32,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
diff --git a/chrome/browser/captive_portal/captive_portal_tab_helper_unittest.cc b/chrome/browser/captive_portal/captive_portal_tab_helper_unittest.cc
index 1580224..96cd8b2 100644
--- a/chrome/browser/captive_portal/captive_portal_tab_helper_unittest.cc
+++ b/chrome/browser/captive_portal/captive_portal_tab_helper_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/captive_portal/captive_portal_tab_helper.h"
 
 #include "base/callback.h"
+#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/captive_portal/captive_portal_service.h"
 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
@@ -17,6 +18,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/web_contents_tester.h"
 #include "net/base/net_errors.h"
@@ -133,7 +135,13 @@
     content::RenderFrameHostTester* rfh_tester =
         content::RenderFrameHostTester::For(rfh);
     rfh_tester->SimulateNavigationError(url, net::ERR_ABORTED);
-    rfh_tester->SimulateNavigationStop();
+    // PlzNavigate: on abort, no renderer will have been associated with the
+    // navigation. Therefore do not simulate a DidStopLoading IPC coming from a
+    // renderer.
+    if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kEnableBrowserSideNavigation)) {
+      rfh_tester->SimulateNavigationStop();
+    }
 
     // Make sure that above call resulted in abort, for tests that continue
     // after the abort.
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 29c6093..76375f1 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -205,6 +205,8 @@
 
 #if !defined(OS_IOS)
 #include "chrome/browser/ui/app_modal/chrome_javascript_native_dialog_factory.h"
+#include "chrome/common/media/media_resource_provider.h"
+#include "media/base/media_resources.h"
 #endif  // !defined(OS_IOS)
 
 #if !defined(DISABLE_NACL)
@@ -678,9 +680,8 @@
   variations::VariationsService* variations_service =
       browser_process_->variations_service();
   if (variations_service)
-    variations_service->CreateTrialsFromSeed();
+    variations_service->CreateTrialsFromSeed(feature_list.get());
 
-  // TODO(asvitkine): Pass |feature_list| to CreateTrialsFromSeed() above.
   base::FeatureList::SetInstance(feature_list.Pass());
 
   // This must be called after |local_state_| is initialized.
@@ -1524,6 +1525,10 @@
 
   // Configure modules that need access to resources.
   net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
+#if !defined(OS_IOS)
+  media::SetLocalizedStringProvider(
+      chrome_common_media::LocalizedStringProvider);
+#endif
 
   // In unittest mode, this will do nothing.  In normal mode, this will create
   // the global IntranetRedirectDetector instance, which will promptly go to
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index dd26039..e0a26c80 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -24,6 +24,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/after_startup_task_utils.h"
+#include "chrome/browser/apps/app_url_redirector.h"
 #include "chrome/browser/browser_about_handler.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_shutdown.h"
@@ -77,6 +78,8 @@
 #include "chrome/browser/tracing/chrome_tracing_delegate.h"
 #include "chrome/browser/ui/blocked_content/blocked_window_params.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/browser/ui/sync/sync_promo_ui.h"
 #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
@@ -121,6 +124,8 @@
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -174,6 +179,7 @@
 #include "chrome/browser/chrome_browser_main_android.h"
 #include "chrome/common/descriptors_android.h"
 #include "components/crash/content/browser/crash_dump_manager_android.h"
+#include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/service_tab_launcher/browser/android/service_tab_launcher.h"
 #include "ui/base/resource/resource_bundle_android.h"
 #elif defined(OS_POSIX)
@@ -2604,6 +2610,34 @@
   }
 }
 
+ScopedVector<content::NavigationThrottle>
+ChromeContentBrowserClient::CreateThrottlesForNavigation(
+    content::NavigationHandle* handle) {
+  ScopedVector<content::NavigationThrottle> throttles;
+#if defined(OS_ANDROID)
+  // TODO(davidben): This is insufficient to integrate with prerender properly.
+  // https://crbug.com/370595
+  prerender::PrerenderContents* prerender_contents =
+      prerender::PrerenderContents::FromWebContents(handle->GetWebContents());
+  if (!prerender_contents && handle->IsInMainFrame()) {
+    throttles.push_back(
+        navigation_interception::InterceptNavigationDelegate::CreateThrottleFor(
+            handle)
+            .Pass());
+  }
+#else
+  if (handle->IsInMainFrame()) {
+    // Redirect some navigations to apps that have registered matching URL
+    // handlers ('url_handlers' in the manifest).
+    scoped_ptr<content::NavigationThrottle> url_to_app_throttle =
+        AppUrlRedirector::MaybeCreateThrottleFor(handle);
+    if (url_to_app_throttle)
+      throttles.push_back(url_to_app_throttle.Pass());
+  }
+#endif
+  return throttles.Pass();
+}
+
 content::DevToolsManagerDelegate*
 ChromeContentBrowserClient::GetDevToolsManagerDelegate() {
   return new ChromeDevToolsManagerDelegate();
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index fa4bc9ae5..e53cd22 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -285,6 +285,8 @@
       content::WebContents* web_contents) override;
 
   void RecordURLMetric(const std::string& metric, const GURL& url) override;
+  ScopedVector<content::NavigationThrottle> CreateThrottlesForNavigation(
+      content::NavigationHandle* handle) override;
 
  private:
   friend class DisableWebRtcEncryptionFlagTest;
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index 7cd0ed6..1d5455d 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -10,10 +10,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/test/base/browser_with_test_window_test.h"
-#include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/variations/entropy_provider.h"
@@ -27,6 +23,13 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/search_test_utils.h"
+#endif
+
 using ChromeContentBrowserClientTest = testing::Test;
 
 TEST_F(ChromeContentBrowserClientTest, ShouldAssignSiteForURL) {
@@ -85,7 +88,7 @@
   EXPECT_EQ(previous_count + 2, browser()->tab_strip_model()->count());
 }
 
-#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
 
 #if defined(ENABLE_WEBRTC)
 
@@ -112,6 +115,7 @@
   base::CommandLine from_command_line_;
   base::CommandLine to_command_line_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(DisableWebRtcEncryptionFlagTest);
 };
 
@@ -335,7 +339,7 @@
         profile(), &TemplateURLServiceFactory::BuildInstanceFor);
     TemplateURLService* template_url_service =
         TemplateURLServiceFactory::GetForProfile(browser()->profile());
-    ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
+    search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
 
     TemplateURLData data;
     data.SetShortName(base::ASCIIToUTF16("foo.com"));
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
index ef0081b23..ae843d1 100644
--- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
+++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
@@ -108,7 +108,7 @@
 
   // net::SSLPrivateKey:
   Type GetType() override;
-  bool SupportsHash(Hash hash) override;
+  std::vector<net::SSLPrivateKey::Hash> GetDigestPreferences() override;
   size_t GetMaxSignatureLengthInBytes() override;
   void SignDigest(Hash hash,
                   const base::StringPiece& input,
@@ -228,9 +228,10 @@
   return cert_info_.type;
 }
 
-bool CertificateProviderService::SSLPrivateKey::SupportsHash(Hash hash) {
+std::vector<net::SSLPrivateKey::Hash>
+CertificateProviderService::SSLPrivateKey::GetDigestPreferences() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return ContainsValue(cert_info_.supported_hashes, hash);
+  return cert_info_.supported_hashes;
 }
 
 size_t
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service_unittest.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_unittest.cc
index 096e647..9d34096 100644
--- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service_unittest.cc
+++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_unittest.cc
@@ -60,16 +60,8 @@
 
 bool IsKeyEqualToCertInfo(const certificate_provider::CertificateInfo& info,
                           net::SSLPrivateKey* key) {
-  const net::SSLPrivateKey::Hash hashes[] = {
-      net::SSLPrivateKey::Hash::MD5_SHA1, net::SSLPrivateKey::Hash::SHA1,
-      net::SSLPrivateKey::Hash::SHA256, net::SSLPrivateKey::Hash::SHA384,
-      net::SSLPrivateKey::Hash::SHA512};
-
-  for (const net::SSLPrivateKey::Hash hash : hashes) {
-    if (ContainsValue(info.supported_hashes, hash) != key->SupportsHash(hash)) {
-      return false;
-    }
-  }
+  if (info.supported_hashes != key->GetDigestPreferences())
+    return false;
 
   return key->GetType() == info.type &&
          key->GetMaxSignatureLengthInBytes() ==
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index c36221e..91005c4 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -105,6 +105,7 @@
 #include "chromeos/network/network_change_notifier_chromeos.h"
 #include "chromeos/network/network_change_notifier_factory_chromeos.h"
 #include "chromeos/network/network_handler.h"
+#include "chromeos/network/portal_detector/network_portal_detector_stub.h"
 #include "chromeos/system/statistics_provider.h"
 #include "chromeos/tpm/tpm_token_loader.h"
 #include "components/device_event_log/device_event_log.h"
@@ -118,6 +119,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/main_function_params.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "media/audio/sounds/sounds_manager.h"
 #include "net/base/network_change_notifier.h"
 #include "net/socket/ssl_server_socket.h"
@@ -155,6 +157,21 @@
       KioskAppLaunchError::Get() == KioskAppLaunchError::NONE;
 }
 
+// Creates an instance of the NetworkPortalDetector implementation or a stub.
+void InitializeNetworkPortalDetector() {
+  if (network_portal_detector::SetForTesting())
+    return;
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          ::switches::kTestType)) {
+    network_portal_detector::SetNetworkPortalDetector(
+        new NetworkPortalDetectorStub());
+  } else {
+    network_portal_detector::SetNetworkPortalDetector(
+        new NetworkPortalDetectorImpl(
+            g_browser_process->system_request_context(), true));
+  }
+}
+
 }  // namespace
 
 namespace internal {
@@ -168,6 +185,12 @@
     // Initialize DBusThreadManager for the browser. This must be done after
     // the main message loop is started, as it uses the message loop.
     DBusThreadManager::Initialize();
+
+    bluez::BluezDBusManager::Initialize(
+        DBusThreadManager::Get()->GetSystemBus(),
+        chromeos::DBusThreadManager::Get()->IsUsingStub(
+            chromeos::DBusClientBundle::BLUETOOTH));
+
     PowerPolicyController::Initialize(
         DBusThreadManager::Get()->GetPowerManagerClient());
 
@@ -234,6 +257,7 @@
     PowerDataCollector::Shutdown();
     PowerPolicyController::Shutdown();
     device::BluetoothAdapterFactory::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
 
     // NOTE: This must only be called if Initialize() was called.
     DBusThreadManager::Shutdown();
@@ -550,8 +574,7 @@
   // NetworkStateHandler and initiates captive portal detection for
   // active networks. Should be called before call to CreateSessionManager,
   // because it depends on NetworkPortalDetector.
-  NetworkPortalDetectorImpl::Initialize(
-      g_browser_process->system_request_context());
+  InitializeNetworkPortalDetector();
   {
 #if defined(GOOGLE_CHROME_BUILD)
     bool is_official_build = true;
@@ -561,7 +584,7 @@
     // Enable portal detector if EULA was previously accepted or if
     // this is an unofficial build.
     if (!is_official_build || StartupUtils::IsEulaAccepted())
-      NetworkPortalDetector::Get()->Enable(true);
+      network_portal_detector::GetInstance()->Enable(true);
   }
 
   // Initialize input methods.
@@ -761,7 +784,7 @@
   // ChromeBrowserMainPartsLinux::PostMainMessageLoopRun() to be
   // executed after execution of chrome::CloseAsh(), because some
   // parts of WebUI depends on NetworkPortalDetector.
-  NetworkPortalDetector::Shutdown();
+  network_portal_detector::Shutdown();
 
   g_browser_process->platform_part()->DestroyChromeUserManager();
 
diff --git a/chrome/browser/chromeos/customization/customization_document_unittest.cc b/chrome/browser/chromeos/customization/customization_document_unittest.cc
index 9bc7d886..4de5800 100644
--- a/chrome/browser/chromeos/customization/customization_document_unittest.cc
+++ b/chrome/browser/chromeos/customization/customization_document_unittest.cc
@@ -204,10 +204,9 @@
 class ServicesCustomizationDocumentTest : public testing::Test {
  protected:
   ServicesCustomizationDocumentTest()
-    : factory_(NULL,
-               base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
-               base::Unretained(&url_callback_))) {
-  }
+      : factory_(nullptr,
+                 base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
+                            base::Unretained(&url_callback_))) {}
 
   // testing::Test:
   void SetUp() override {
@@ -221,7 +220,7 @@
     std::string default_network_path =
         default_network ? default_network->path() : "";
 
-    NetworkPortalDetector::InitializeForTesting(&network_portal_detector_);
+    network_portal_detector::InitializeForTesting(&network_portal_detector_);
     NetworkPortalDetector::CaptivePortalState online_state;
     online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
     online_state.response_code = 204;
@@ -238,10 +237,10 @@
   }
 
   void TearDown() override {
-    TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
+    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
     NetworkHandler::Shutdown();
     DBusThreadManager::Shutdown();
-    NetworkPortalDetector::InitializeForTesting(NULL);
+    network_portal_detector::InitializeForTesting(nullptr);
 
     ServicesCustomizationDocument::ShutdownForTesting();
   }
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc
index 3c44cb4..65e5abe 100644
--- a/chrome/browser/chromeos/enrollment_dialog_view.cc
+++ b/chrome/browser/chromeos/enrollment_dialog_view.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/network/client_cert_util.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
index 3800322..3b9637b4 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
@@ -26,6 +26,7 @@
     "haiffjcadagjlijoggckpgfnoeiflnem",  // Citrix Receiver
     "mfaihdlpglflfgpfjcifdjdjcckigekc",  // ARC Runtime
     "ngjnkanfphagcaokhjecbgkboelgfcnf",  // Print button
+    "gbchcmhmhahfdphkhkmpfmihenigjmpp",  // Chrome Remote Desktop
 
     // Libraries:
     "aclofikceldphonlfmghmimkodjdmhck",  // Ancoris login component
@@ -100,6 +101,7 @@
     "ongnjlefhnoajpbodoldndkbkdgfomlp",  // Show Managed Storage
     "ilnpadgckeacioehlommkaafedibdeob",  // Enterprise DeviceAttributes
     "oflckobdemeldmjddmlbaiaookhhcngo",  // Citrix Receiver QA version
+    "ljacajndfccfgnfohlgkdphmbnpkjflk",  // Chrome Remote Desktop (Dev Build)
 };
 
 }  // namespace
@@ -145,10 +147,13 @@
         return true;
     }
   } else if (account_type_ == policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
-    // For single-app kiosk sessions, allow platform apps and shared modules.
+    // For single-app kiosk sessions, allow platform apps, extesions and
+    // shared modules.
     if (extension->GetType() == extensions::Manifest::TYPE_PLATFORM_APP ||
-        extension->GetType() == extensions::Manifest::TYPE_SHARED_MODULE)
+        extension->GetType() == extensions::Manifest::TYPE_SHARED_MODULE ||
+        extension->GetType() == extensions::Manifest::TYPE_EXTENSION) {
       return true;
+    }
   }
 
   // Disallow all other extensions.
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
index c6f974d..41c708e 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
@@ -128,8 +128,8 @@
   // kiosk session.
   extension = CreateExternalComponentExtension();
   ASSERT_TRUE(extension.get());
-  EXPECT_FALSE(provider.UserMayLoad(extension.get(), &error));
-  EXPECT_NE(base::string16(), error);
+  EXPECT_TRUE(provider.UserMayLoad(extension.get(), &error));
+  EXPECT_EQ(base::string16(), error);
   error.clear();
 
   // Verify that an extension whose type has been whitelisted for use in other
@@ -146,8 +146,8 @@
   // session.
   extension = CreateRegularExtension(kWhitelistedId);
   ASSERT_TRUE(extension.get());
-  EXPECT_FALSE(provider.UserMayLoad(extension.get(), &error));
-  EXPECT_NE(base::string16(), error);
+  EXPECT_TRUE(provider.UserMayLoad(extension.get(), &error));
+  EXPECT_EQ(base::string16(), error);
   error.clear();
 }
 
diff --git a/chrome/browser/chromeos/extensions/echo_private_api.cc b/chrome/browser/chromeos/extensions/echo_private_api.cc
index 7b74050..cec7110a 100644
--- a/chrome/browser/chromeos/extensions/echo_private_api.cc
+++ b/chrome/browser/chromeos/extensions/echo_private_api.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/ui/echo_dialog_view.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/extensions/api/echo_private.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/system/statistics_provider.h"
@@ -48,9 +49,9 @@
   registry->RegisterDictionaryPref(prefs::kEchoCheckedOffers);
 }
 
-} // namespace echo_offer
+}  // namespace echo_offer
 
-} // namespace chromeos
+}  // namespace chromeos
 
 EchoPrivateGetRegistrationCodeFunction::
     EchoPrivateGetRegistrationCodeFunction() {}
@@ -189,8 +190,8 @@
 EchoPrivateGetUserConsentFunction::~EchoPrivateGetUserConsentFunction() {}
 
 bool EchoPrivateGetUserConsentFunction::RunAsync() {
-   CheckRedeemOffersAllowed();
-   return true;
+  CheckRedeemOffersAllowed();
+  return true;
 }
 
 void EchoPrivateGetUserConsentFunction::OnAccept() {
diff --git a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
index ae66cfaf..d427d162 100644
--- a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
+++ b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/browser/ui/singleton_tabs.h"
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
index 0d79aee..e4fb0ed 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -26,7 +26,7 @@
   const NetworkState* default_network =
       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
   return default_network
-             ? NetworkPortalDetector::Get()
+             ? network_portal_detector::GetInstance()
                    ->GetCaptivePortalState(default_network->guid())
                    .status
              : NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN;
@@ -57,7 +57,7 @@
 }
 
 AutoEnrollmentCheckScreen::~AutoEnrollmentCheckScreen() {
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
   if (actor_)
     actor_->SetDelegate(NULL);
 }
@@ -65,7 +65,7 @@
 void AutoEnrollmentCheckScreen::ClearState() {
   auto_enrollment_progress_subscription_.reset();
   connect_request_subscription_.reset();
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
 
   auto_enrollment_state_ = policy::AUTO_ENROLLMENT_STATE_IDLE;
   captive_portal_status_ = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN;
@@ -98,8 +98,7 @@
           base::Bind(
               &AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed,
               base::Unretained(this)));
-  NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
-  portal_detector->AddObserver(this);
+  network_portal_detector::GetInstance()->AddObserver(this);
 
   // Perform an initial UI update.
   NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status =
@@ -115,7 +114,7 @@
 
   // Make sure gears are in motion in the background.
   auto_enrollment_controller_->Start();
-  portal_detector->StartDetectionIfIdle();
+  network_portal_detector::GetInstance()->StartDetectionIfIdle();
 }
 
 void AutoEnrollmentCheckScreen::Hide() {
@@ -244,7 +243,7 @@
 }
 
 void AutoEnrollmentCheckScreen::SignalCompletion() {
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
   auto_enrollment_progress_subscription_.reset();
   connect_request_subscription_.reset();
 
diff --git a/chrome/browser/chromeos/login/error_screens_histogram_helper.cc b/chrome/browser/chromeos/login/error_screens_histogram_helper.cc
index 94a7ff67..be4ee92 100644
--- a/chrome/browser/chromeos/login/error_screens_histogram_helper.cc
+++ b/chrome/browser/chromeos/login/error_screens_histogram_helper.cc
@@ -10,13 +10,12 @@
 
 namespace {
 
-static const char kOobeErrorScreensCounterPrefix[] = "OOBE.NetworkErrorShown.";
-static const char kOobeTimeSpentOnErrorScreensPrefix[] =
-    "OOBE.ErrorScreensTime.";
+const char kOobeErrorScreensCounterPrefix[] = "OOBE.NetworkErrorShown.";
+const char kOobeTimeSpentOnErrorScreensPrefix[] = "OOBE.ErrorScreensTime.";
 
-const base::TimeDelta time_min = base::TimeDelta::FromMilliseconds(10);
-const base::TimeDelta time_max = base::TimeDelta::FromMinutes(3);
-const int time_bucket_count = 50;
+const int kTimeMinInMS = 10;
+const int kTimeMaxInMinutes = 3;
+const int kTimeBucketCount = 50;
 
 std::string ErrorToString(NetworkError::ErrorState error) {
   switch (error) {
@@ -64,10 +63,8 @@
   // This comes from UMA_HISTOGRAM_MEDIUM_TIMES macros. Can't use it because of
   // non const histogram name.
   base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
-      histogram_name,
-      time_min,
-      time_max,
-      time_bucket_count,
+      histogram_name, base::TimeDelta::FromMilliseconds(kTimeMinInMS),
+      base::TimeDelta::FromMinutes(kTimeMaxInMinutes), kTimeBucketCount,
       base::HistogramBase::kUmaTargetedHistogramFlag);
 
   histogram->AddTime(time_delta);
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 40ae90c..9f4df21 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -126,6 +126,7 @@
 const char kTestSecondaryApp1[] = "ihplaomghjbeafnpnjkhppmfpnmdihgd";
 const char kTestSecondaryApp2[] = "fiehokkcgaojmbhfhlpiheggjhaedjoc";
 const char kTestSecondaryApp3[] = "aabnpdpieclcikafhdkkpldcaodmfoai";
+const char kTestSecondaryExtension[] = "imlgadjgphbjkaceoiapiephhgeofhic";
 
 // Fake usb stick mount path.
 const char kFakeUsbMountPathUpdatePass[] =
@@ -208,6 +209,17 @@
   return app != nullptr;
 }
 
+extensions::Manifest::Type GetAppType(const std::string& app_id) {
+  Profile* app_profile = ProfileManager::GetPrimaryUserProfile();
+  DCHECK(app_profile);
+  const extensions::Extension* app =
+      extensions::ExtensionSystem::Get(app_profile)
+          ->extension_service()
+          ->GetInstalledExtension(app_id);
+  DCHECK(app);
+  return app->GetType();
+}
+
 // Helper functions for CanConfigureNetwork mock.
 class ScopedCanConfigureNetwork {
  public:
@@ -1278,11 +1290,13 @@
     std::string id;
     std::string version;
     std::string crx_filename;
+    extensions::Manifest::Type type;
     TestAppInfo() {}
     TestAppInfo(const std::string& id,
                 const std::string& version,
-                const std::string& crx_filename)
-        : id(id), version(version), crx_filename(crx_filename) {}
+                const std::string& crx_filename,
+                extensions::Manifest::Type type)
+        : id(id), version(version), crx_filename(crx_filename), type(type) {}
     ~TestAppInfo() {}
   };
 
@@ -1393,10 +1407,8 @@
 
     set_test_app_id(primary_app.id);
     fake_cws()->SetNoUpdate(primary_app.id);
-    for (size_t i = 0; i < secondary_apps.size(); ++i) {
-      fake_cws()->SetUpdateCrx(secondary_apps[i].id,
-                               secondary_apps[i].crx_filename,
-                               secondary_apps[i].version);
+    for (const auto& app : secondary_apps) {
+      fake_cws()->SetUpdateCrx(app.id, app.crx_filename, app.version);
     }
 
     // Launch the primary app.
@@ -1407,25 +1419,45 @@
 
     // Verify the primary app and the secondary apps are all installed.
     EXPECT_EQ(primary_app.version, GetInstalledAppVersion().GetString());
-    for (size_t i = 0; i < secondary_apps.size(); ++i)
-      EXPECT_TRUE(IsAppInstalled(secondary_apps[i].id));
+    for (const auto& app : secondary_apps) {
+      EXPECT_TRUE(IsAppInstalled(app.id));
+      EXPECT_EQ(GetAppType(app.id), app.type);
+    }
   }
 
   void LaunchTestKioskAppWithTwoSecondaryApps() {
     TestAppInfo primary_app(kTestPrimaryKioskApp, "1.0.0",
-                            std::string(kTestPrimaryKioskApp) + "-1.0.0.crx");
+                            std::string(kTestPrimaryKioskApp) + "-1.0.0.crx",
+                            extensions::Manifest::TYPE_PLATFORM_APP);
 
     std::vector<TestAppInfo> secondary_apps;
     TestAppInfo secondary_app_1(kTestSecondaryApp1, "1.0.0",
-                                std::string(kTestSecondaryApp1) + "-1.0.0.crx");
+                                std::string(kTestSecondaryApp1) + "-1.0.0.crx",
+                                extensions::Manifest::TYPE_PLATFORM_APP);
     secondary_apps.push_back(secondary_app_1);
     TestAppInfo secondary_app_2(kTestSecondaryApp2, "1.0.0",
-                                std::string(kTestSecondaryApp2) + "-1.0.0.crx");
+                                std::string(kTestSecondaryApp2) + "-1.0.0.crx",
+                                extensions::Manifest::TYPE_PLATFORM_APP);
     secondary_apps.push_back(secondary_app_2);
 
     LaunchKioskWithSecondaryApps(primary_app, secondary_apps);
   }
 
+  void LaunchTestKioskAppWithSeconadayExtension() {
+    TestAppInfo primary_app(kTestPrimaryKioskApp, "24.0.0",
+                            std::string(kTestPrimaryKioskApp) + "-24.0.0.crx",
+                            extensions::Manifest::TYPE_PLATFORM_APP);
+
+    std::vector<TestAppInfo> secondary_apps;
+    TestAppInfo secondary_extension(
+        kTestSecondaryExtension, "1.0.0",
+        std::string(kTestSecondaryExtension) + "-1.0.0.crx",
+        extensions::Manifest::TYPE_EXTENSION);
+    secondary_apps.push_back(secondary_extension);
+
+    LaunchKioskWithSecondaryApps(primary_app, secondary_apps);
+  }
+
  private:
   class KioskAppExternalUpdateWaiter : public KioskAppManagerObserver {
    public:
@@ -1871,6 +1903,10 @@
   EXPECT_TRUE(IsAppInstalled(kTestSecondaryApp3));
 }
 
+IN_PROC_BROWSER_TEST_F(KioskUpdateTest, LaunchKioskAppWithSecondaryExtension) {
+  LaunchTestKioskAppWithSeconadayExtension();
+}
+
 class KioskEnterpriseTest : public KioskTest {
  protected:
   KioskEnterpriseTest() {
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 2bf45b9e..eea1b56b 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -368,7 +368,7 @@
     DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
   }
   // Close captive portal window and clear signin profile.
-  NetworkPortalDetector::Get()->OnLockScreenRequest();
+  network_portal_detector::GetInstance()->OnLockScreenRequest();
 }
 
 // static
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
index d4c218cc0..fb398bbf 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
+#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -173,6 +174,14 @@
   EXPECT_TRUE(VerifyLockScreenDismissed());
 }
 
+// Makes sure Chrome doesn't crash if we lock the screen during an add-user
+// flow. Regression test for crbug.com/467111.
+IN_PROC_BROWSER_TEST_F(ScreenLockerTest, LockScreenWhileAddingUser) {
+  UserAddingScreen::Get()->Start();
+  content::RunAllPendingInMessageLoop();
+  ScreenLocker::HandleLockScreenRequest();
+}
+
 // Test how locking the screen affects an active fullscreen window.
 IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) {
   // 1) If the active browser window is in fullscreen and the fullscreen window
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc
index dd4cdb5..8ce8c30f 100644
--- a/chrome/browser/chromeos/login/screens/error_screen.cc
+++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -99,7 +99,7 @@
       chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
       content::NotificationService::AllSources(),
       content::NotificationService::NoDetails());
-  NetworkPortalDetector::Get()->SetStrategy(
+  network_portal_detector::GetInstance()->SetStrategy(
       PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
 }
 
@@ -109,7 +109,7 @@
     on_hide_callback_->Run();
     on_hide_callback_.reset();
   }
-  NetworkPortalDetector::Get()->SetStrategy(
+  network_portal_detector::GetInstance()->SetStrategy(
       PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
 }
 
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc
index f7d0c99e..b63754d 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -51,13 +51,13 @@
 
 const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline";
 
-// Minimum timestep between two consecutive measurements for the
-// download rate.
-const base::TimeDelta kMinTimeStep = base::TimeDelta::FromSeconds(1);
+// Minimum timestep between two consecutive measurements for the download rates.
+const int kMinTimeStepInSeconds = 1;
 
 // Smooth factor that is used for the average downloading speed
 // estimation.
-// avg_speed = smooth_factor * cur_speed + (1.0 - smooth_factor) * avg_speed.
+// avg_speed = smooth_factor * cur_speed + (1.0 - smooth_factor) *
+// avg_speed.
 const double kDownloadSpeedSmoothFactor = 0.1;
 
 // Minumum allowed value for the average downloading speed.
@@ -133,7 +133,7 @@
     view_->Unbind();
 
   DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
   GetInstanceSet().erase(this);
 }
 
@@ -276,7 +276,7 @@
         FROM_HERE,
         base::Bind(
             base::IgnoreResult(&NetworkPortalDetector::StartDetectionIfIdle),
-            base::Unretained(NetworkPortalDetector::Get())));
+            base::Unretained(network_portal_detector::GetInstance())));
     return;
   }
   is_first_detection_notification_ = false;
@@ -309,14 +309,14 @@
   // If portal detector is enabled and portal detection before AU is
   // allowed, initiate network state check. Otherwise, directly
   // proceed to update.
-  if (!NetworkPortalDetector::Get()->IsEnabled()) {
+  if (!network_portal_detector::GetInstance()->IsEnabled()) {
     StartUpdateCheck();
     return;
   }
   state_ = STATE_FIRST_PORTAL_CHECK;
   is_first_detection_notification_ = true;
   is_first_portal_notification_ = true;
-  NetworkPortalDetector::Get()->AddAndFireObserver(this);
+  network_portal_detector::GetInstance()->AddAndFireObserver(this);
 }
 
 void UpdateScreen::PrepareToShow() {
@@ -371,7 +371,7 @@
 
 void UpdateScreen::ExitUpdate(UpdateScreen::ExitReason reason) {
   DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
   SetHostPairingControllerStatus(HostPairingController::UPDATE_STATUS_UPDATED);
 
 
@@ -441,7 +441,9 @@
 void UpdateScreen::UpdateDownloadingStats(
     const UpdateEngineClient::Status& status) {
   base::Time download_current_time = base::Time::Now();
-  if (download_current_time >= download_last_time_ + kMinTimeStep) {
+  if (download_current_time >=
+      download_last_time_ +
+          base::TimeDelta::FromSeconds(kMinTimeStepInSeconds)) {
     // Estimate downloading rate.
     double progress_delta =
         std::max(status.download_progress - download_last_progress_, 0.0);
@@ -514,7 +516,7 @@
   error_message_timer_.Stop();
   GetErrorScreen()->HideCaptivePortal();
 
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
   connect_request_subscription_.reset();
   if (state_ == STATE_ERROR)
     HideErrorMessage();
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
index aade1c40..70e03a34 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -57,7 +57,7 @@
     // ethernet and wifi networks. Ethernet is an active network by
     // default.
     network_portal_detector_ = new NetworkPortalDetectorTestImpl();
-    NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+    network_portal_detector::InitializeForTesting(network_portal_detector_);
     NetworkPortalDetector::CaptivePortalState online_state;
     online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
     online_state.response_code = 204;
@@ -94,7 +94,7 @@
   }
 
   void TearDownInProcessBrowserTestFixture() override {
-    NetworkPortalDetector::Shutdown();
+    network_portal_detector::Shutdown();
     WizardInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
   }
 
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index de52496a..538ce241 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -477,8 +477,8 @@
 void UserSessionManager::PerformPostUserLoggedInActions() {
   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
   if (user_manager->GetLoggedInUsers().size() == 1) {
-    if (NetworkPortalDetector::IsInitialized()) {
-      NetworkPortalDetector::Get()->SetStrategy(
+    if (network_portal_detector::IsInitialized()) {
+      network_portal_detector::GetInstance()->SetStrategy(
           PortalDetectorStrategy::STRATEGY_ID_SESSION);
     }
   }
diff --git a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
index 62f5f89..e210e9a 100644
--- a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
+++ b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
@@ -31,6 +31,7 @@
 
 char kSecondUserEmail[] = "second_user@gmail.com";
 char kSecondUserPassword[] = "password";
+char kSecondUserGaiaId[] = "4321";
 char kSecondUserRefreshToken1[] = "refresh_token_second_user_1";
 char kSecondUserRefreshToken2[] = "refresh_token_second_user_2";
 
@@ -98,13 +99,15 @@
 
   void SignInOnline(const std::string& user_id,
                     const std::string& password,
-                    const std::string& refresh_token) {
+                    const std::string& refresh_token,
+                    const std::string& gaia_id) {
     WaitForGaiaPageLoad();
 
     FakeGaia::MergeSessionParams params;
     params.email = user_id;
     params.refresh_token = refresh_token;
     fake_gaia_->UpdateMergeSessionParams(params);
+    fake_gaia_->MapEmailToGaiaId(user_id, gaia_id);
 
     GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password);
     WaitForSessionStart();
@@ -171,7 +174,8 @@
 
 // Add the first user and check that device ID is consistent.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_PRE_PRE_NewUsers) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1);
+  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
+               kFakeUserGaiaId);
   CheckDeviceIDIsConsistent(kFakeUserEmail, kRefreshToken1);
 }
 
@@ -182,7 +186,8 @@
   EXPECT_FALSE(device_id.empty());
   EXPECT_EQ(device_id, GetDeviceIdFromGAIA(kRefreshToken1));
 
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken2);
+  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken2,
+               kFakeUserGaiaId);
   CheckDeviceIDIsConsistent(kFakeUserEmail, kRefreshToken2);
 
   CHECK_EQ(device_id, GetDeviceId(kFakeUserEmail));
@@ -205,7 +210,8 @@
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_NewUsers) {
   WaitForSigninScreen();
   JS().ExecuteAsync("chrome.send('showAddUser')");
-  SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken1);
+  SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken1,
+               kSecondUserGaiaId);
   CheckDeviceIDIsConsistent(kSecondUserEmail, kSecondUserRefreshToken1);
 }
 
@@ -218,7 +224,8 @@
 // Add the second user back. Verify that device ID has been changed.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, NewUsers) {
   EXPECT_TRUE(GetDeviceId(kSecondUserEmail).empty());
-  SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken2);
+  SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken2,
+               kSecondUserGaiaId);
   CheckDeviceIDIsConsistent(kSecondUserEmail, kSecondUserRefreshToken2);
   EXPECT_NE(GetDeviceIdFromGAIA(kSecondUserRefreshToken1),
             GetDeviceId(kSecondUserEmail));
@@ -226,7 +233,8 @@
 
 // Set up a user that has a device ID stored in preference only.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_Migration) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1);
+  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
+               kFakeUserGaiaId);
 
   // Simulate user that has device ID saved only in preferences (pre-M44).
   PrefService* prefs =
@@ -252,7 +260,8 @@
 
 // Set up a user that doesn't have a device ID.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_LegacyUsers) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1);
+  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
+               kFakeUserGaiaId);
 
   PrefService* prefs =
       ProfileHelper::Get()
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
index 1cfd624..2648f7f 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -120,7 +120,7 @@
     sync_service_->RemoveObserver(this);
   if (actor_)
     actor_->SetDelegate(NULL);
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
 }
 
 void SupervisedUserCreationScreen::PrepareToShow() {
@@ -141,7 +141,7 @@
   }
 
   if (!on_error_screen_)
-    NetworkPortalDetector::Get()->AddAndFireObserver(this);
+    network_portal_detector::GetInstance()->AddAndFireObserver(this);
   on_error_screen_ = false;
   histogram_helper_->OnScreenShow();
 }
@@ -190,7 +190,7 @@
   if (actor_)
     actor_->Hide();
   if (!on_error_screen_)
-    NetworkPortalDetector::Get()->RemoveObserver(this);
+    network_portal_detector::GetInstance()->RemoveObserver(this);
 }
 
 std::string SupervisedUserCreationScreen::GetName() const {
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_test_base.cc b/chrome/browser/chromeos/login/supervised/supervised_user_test_base.cc
index f8e1a675..39fca9f 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_test_base.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_test_base.cc
@@ -196,7 +196,7 @@
   // ethernet and wifi networks. Ethernet is an active network by
   // default.
   network_portal_detector_ = new NetworkPortalDetectorTestImpl();
-  NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+  network_portal_detector::InitializeForTesting(network_portal_detector_);
   NetworkPortalDetector::CaptivePortalState online_state;
   online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
   online_state.response_code = 204;
@@ -214,7 +214,7 @@
 }
 
 void SupervisedUserTestBase::TearDownInProcessBrowserTestFixture() {
-  NetworkPortalDetector::Shutdown();
+  network_portal_detector::Shutdown();
 }
 
 void SupervisedUserTestBase::JSEval(const std::string& script) {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index a0b04be..fc3c084 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -40,6 +40,7 @@
 // static
 const char OobeBaseTest::kFakeUserEmail[] = "fake-email@gmail.com";
 const char OobeBaseTest::kFakeUserPassword[] = "fake-password";
+const char OobeBaseTest::kFakeUserGaiaId[] = "fake-gaiaId";
 const char OobeBaseTest::kFakeSIDCookie[] = "fake-SID-cookie";
 const char OobeBaseTest::kFakeLSIDCookie[] = "fake-LSID-cookie";
 
@@ -82,7 +83,7 @@
 void OobeBaseTest::SetUpInProcessBrowserTestFixture() {
   host_resolver()->AddRule("*", "127.0.0.1");
   network_portal_detector_ = new NetworkPortalDetectorTestImpl();
-  NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+  network_portal_detector::InitializeForTesting(network_portal_detector_);
   network_portal_detector_->SetDefaultNetworkForTesting(
       FakeShillManagerClient::kFakeEthernetNetworkGuid);
 
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h
index dc51123..0acadf7 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.h
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -39,6 +39,7 @@
 
   static const char kFakeUserEmail[];
   static const char kFakeUserPassword[];
+  static const char kFakeUserGaiaId[];
 
   // FakeGaia is configured to return these cookies for kFakeUserEmail.
   static const char kFakeSIDCookie[];
diff --git a/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc b/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
index 50f9670..18ea84e 100644
--- a/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
+++ b/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
@@ -182,7 +182,7 @@
     LoginManagerTest::SetUpInProcessBrowserTestFixture();
 
     network_portal_detector_ = new NetworkPortalDetectorTestImpl();
-    NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+    network_portal_detector::InitializeForTesting(network_portal_detector_);
     NetworkPortalDetector::CaptivePortalState portal_state;
     portal_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
     portal_state.response_code = 200;
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
index ae9d5658..f3d283e9 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -916,7 +916,7 @@
     base::MessageLoop::current()->Quit();
 
   if (!completion_callback_.is_null())
-    completion_callback_.Run();
+    base::MessageLoop::current()->PostTask(FROM_HERE, completion_callback_);
 }
 
 void LoginDisplayHostImpl::ScheduleWorkspaceAnimation() {
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index 015b55f..172a495f 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
-#include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/media/media_stream_devices_controller.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
@@ -440,7 +440,8 @@
     WebContents* web_contents,
     const content::MediaStreamRequest& request,
     const content::MediaResponseCallback& callback) {
-  if (MediaStreamInfoBarDelegate::Create(web_contents, request, callback))
+  MediaStreamDevicesController controller(web_contents, request, callback);
+  if (controller.IsAskingForVideo() || controller.IsAskingForAudio())
     NOTREACHED() << "Media stream not allowed for WebUI";
 }
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index c39b345..2e7d4b0 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -795,7 +795,7 @@
       NetworkStateHandler::kDefaultCheckPortalList);
   host_->GetAutoEnrollmentController()->Start();
   host_->PrewarmAuthentication();
-  NetworkPortalDetector::Get()->Enable(true);
+  network_portal_detector::GetInstance()->Enable(true);
 }
 
 void WizardController::PerformOOBECompletedActions() {
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index db26cd0c..702489e 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -486,7 +486,7 @@
         new net::FakeURLFetcherFactory(fallback_fetcher_factory_.get()));
 
     network_portal_detector_ = new NetworkPortalDetectorTestImpl();
-    NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+    network_portal_detector::InitializeForTesting(network_portal_detector_);
 
     NetworkPortalDetector::CaptivePortalState online_state;
     online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
diff --git a/chrome/browser/chromeos/net/delay_network_call.cc b/chrome/browser/chromeos/net/delay_network_call.cc
index 76768ebf..e04d371 100644
--- a/chrome/browser/chromeos/net/delay_network_call.cc
+++ b/chrome/browser/chromeos/net/delay_network_call.cc
@@ -32,10 +32,11 @@
                << " State: " << default_connection_state;
     }
   }
-  if (!delay_network_call && NetworkPortalDetector::IsInitialized()) {
-    NetworkPortalDetector* detector = NetworkPortalDetector::Get();
+  if (!delay_network_call && network_portal_detector::IsInitialized()) {
     NetworkPortalDetector::CaptivePortalStatus status =
-        detector->GetCaptivePortalState(default_network->guid()).status;
+        network_portal_detector::GetInstance()
+            ->GetCaptivePortalState(default_network->guid())
+            .status;
     if (status != NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
       delay_network_call = true;
       DVLOG(1) << "DelayNetworkCall: Captive portal status for "
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index 7f717b2a..fa99dc0 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -19,7 +19,6 @@
 #include "chromeos/login/login_state.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/portal_detector/network_portal_detector_stub.h"
 #include "components/device_event_log/device_event_log.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/content_switches.h"
@@ -208,27 +207,10 @@
 const char NetworkPortalDetectorImpl::kSessionPortalToOnlineHistogram[] =
     "CaptivePortal.Session.PortalToOnlineTransition";
 
-// static
-void NetworkPortalDetectorImpl::Initialize(
-    net::URLRequestContextGetter* url_context) {
-  if (set_for_testing())
-    return;
-  CHECK(!network_portal_detector())
-      << "NetworkPortalDetector was initialized twice.";
-  NET_LOG(EVENT) << "NetworkPortalDetectorImpl::Initialize";
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          ::switches::kTestType)) {
-    set_network_portal_detector(new NetworkPortalDetectorStub());
-  } else {
-    set_network_portal_detector(
-        new NetworkPortalDetectorImpl(url_context, true));
-  }
-}
-
 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl(
     const scoped_refptr<net::URLRequestContextGetter>& request_context,
     bool create_notification_controller)
-    : test_url_(CaptivePortalDetector::kDefaultURL),
+    : portal_test_url_(CaptivePortalDetector::kDefaultURL),
       strategy_(PortalDetectorStrategy::CreateById(
           PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN,
           this)),
@@ -454,12 +436,13 @@
 
 void NetworkPortalDetectorImpl::StartAttempt() {
   DCHECK(is_portal_check_pending());
+  DCHECK(portal_test_url_.is_valid());
 
   state_ = STATE_CHECKING_FOR_PORTAL;
   attempt_start_time_ = NowTicks();
 
   captive_portal_detector_->DetectCaptivePortal(
-      test_url_,
+      portal_test_url_,
       base::Bind(&NetworkPortalDetectorImpl::OnAttemptCompleted,
                  weak_factory_.GetWeakPtr()));
   attempt_timeout_.Reset(
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h
index 7dcf93d..161ae25 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h
@@ -41,12 +41,11 @@
 // This class handles all notifications about network changes from
 // NetworkStateHandler and delegates portal detection for the default
 // network to CaptivePortalService.
-class NetworkPortalDetectorImpl
-    : public NetworkPortalDetector,
-      public base::NonThreadSafe,
-      public chromeos::NetworkStateHandlerObserver,
-      public content::NotificationObserver,
-      public PortalDetectorStrategy::Delegate {
+class NetworkPortalDetectorImpl : public NetworkPortalDetector,
+                                  public base::NonThreadSafe,
+                                  public chromeos::NetworkStateHandlerObserver,
+                                  public content::NotificationObserver,
+                                  public PortalDetectorStrategy::Delegate {
  public:
   static const char kOobeDetectionResultHistogram[];
   static const char kOobeDetectionDurationHistogram[];
@@ -62,14 +61,16 @@
   static const char kSessionShillOfflineHistogram[];
   static const char kSessionPortalToOnlineHistogram[];
 
-  // Creates an instance of the implementation or a stub.
-  static void Initialize(net::URLRequestContextGetter* url_context);
-
   NetworkPortalDetectorImpl(
       const scoped_refptr<net::URLRequestContextGetter>& request_context,
       bool create_notification_controller);
   ~NetworkPortalDetectorImpl() override;
 
+  // Set the URL to be tested for portal state.
+  void set_portal_test_url(const GURL& portal_test_url) {
+    portal_test_url_ = portal_test_url;
+  }
+
  private:
   friend class ::NetworkingConfigTest;
   friend class NetworkPortalDetectorImplTest;
@@ -228,7 +229,7 @@
   base::CancelableClosure attempt_timeout_;
 
   // URL that returns a 204 response code when connected to the Internet.
-  GURL test_url_;
+  GURL portal_test_url_;
 
   // Detector for checking default network for a portal state.
   scoped_ptr<captive_portal::CaptivePortalDetector> captive_portal_detector_;
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
index 7a45b5e6..59077df 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
@@ -130,7 +130,7 @@
     network_portal_detector_ = new NetworkPortalDetectorImpl(
         g_browser_process->system_request_context(),
         true /* create_notification_controller */);
-    NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+    network_portal_detector::InitializeForTesting(network_portal_detector_);
     network_portal_detector_->Enable(false /* start_detection */);
     set_detector(network_portal_detector_->captive_portal_detector_.get());
     PortalDetectorStrategy::set_delay_till_next_attempt_for_testing(
@@ -200,9 +200,10 @@
   // Check that wifi is marked as behind the portal and that notification
   // is displayed.
   ASSERT_TRUE(message_center()->FindVisibleNotificationById(kNotificationId));
-  ASSERT_EQ(
-      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
-      NetworkPortalDetector::Get()->GetCaptivePortalState(kWifiGuid).status);
+  ASSERT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
+            network_portal_detector::GetInstance()
+                ->GetCaptivePortalState(kWifiGuid)
+                .status);
 
   // Wait until notification is displayed.
   observer.WaitAndReset();
@@ -267,9 +268,10 @@
   // Check that WiFi is marked as behind a portal and that a notification
   // is displayed.
   EXPECT_TRUE(message_center()->FindVisibleNotificationById(kNotificationId));
-  EXPECT_EQ(
-      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
-      NetworkPortalDetector::Get()->GetCaptivePortalState(kWifiGuid).status);
+  EXPECT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
+            network_portal_detector::GetInstance()
+                ->GetCaptivePortalState(kWifiGuid)
+                .status);
 
   // Wait until notification is displayed.
   observer.WaitAndReset();
diff --git a/chrome/browser/chromeos/net/onc_utils.cc b/chrome/browser/chromeos/net/onc_utils.cc
index 7a661d7..1f6b510 100644
--- a/chrome/browser/chromeos/net/onc_utils.cc
+++ b/chrome/browser/chromeos/net/onc_utils.cc
@@ -269,29 +269,35 @@
     const char* pref_name,
     const NetworkState& network) {
   if (!pref_service) {
-    DLOG(ERROR) << "No pref service";
-    return nullptr;
+    VLOG(2) << "No pref service";
+    return NULL;
   }
 
-  const PrefService::Preference* const preference =
+  const PrefService::Preference* preference =
       pref_service->FindPreference(pref_name);
   if (!preference) {
-    DVLOG(2) << "No preference " << pref_name;
+    VLOG(2) << "No preference " << pref_name;
     // The preference may not exist in tests.
-    return nullptr;
+    return NULL;
   }
 
   // User prefs are not stored in this Preference yet but only the policy.
-  if (!preference->IsManaged()) {
-    DVLOG(2) << "Preference has no mandatory value.";
+  //
+  // The policy server incorrectly configures the OpenNetworkConfiguration user
+  // policy as Recommended. To work around that, we handle the Recommended and
+  // the Mandatory value in the same way.
+  // TODO(pneubeck): Remove this workaround, once the server is fixed. See
+  // http://crbug.com/280553 .
+  if (preference->IsDefaultValue()) {
+    VLOG(2) << "Preference has no recommended or mandatory value.";
     // No policy set.
-    return nullptr;
+    return NULL;
   }
-  DVLOG(2) << "Preference with policy found.";
-  const base::Value* const onc_policy_value = preference->GetValue();
+  VLOG(2) << "Preference with policy found.";
+  const base::Value* onc_policy_value = preference->GetValue();
   DCHECK(onc_policy_value);
 
-  const base::ListValue* onc_policy = nullptr;
+  const base::ListValue* onc_policy = NULL;
   onc_policy_value->GetAsList(&onc_policy);
   DCHECK(onc_policy);
 
diff --git a/chrome/browser/chromeos/policy/consumer_management_notifier.cc b/chrome/browser/chromeos/policy/consumer_management_notifier.cc
index 830b8ab..72eb6dc 100644
--- a/chrome/browser/chromeos/policy/consumer_management_notifier.cc
+++ b/chrome/browser/chromeos/policy/consumer_management_notifier.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/notifications/notification_delegate.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/url_constants.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index df60ba5..acb574a8 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -42,6 +42,9 @@
 const int kMainIndexMask = 0x1000;
 const int kMoreIndexMask = 0x4000;
 
+const ui::ResourceBundle::FontStyle kAssociatedNetworkFontStyle =
+    ui::ResourceBundle::BoldFont;
+
 // Replace '&' in a string with "&&" to allow it to be a menu item label.
 std::string EscapeAmpersands(const std::string& input) {
   std::string str = input;
@@ -249,7 +252,7 @@
   const gfx::FontList* font_list = NULL;
   if (menu_items_[index].flags & FLAG_ASSOCIATED) {
     ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-    font_list = &rb->GetFontList(browser_defaults::kAssociatedNetworkFontStyle);
+    font_list = &rb->GetFontList(kAssociatedNetworkFontStyle);
   }
 
   return font_list;
diff --git a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
index 9e4e23b..75db6c6 100644
--- a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
+++ b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
@@ -8,8 +8,12 @@
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/user_metrics.h"
-#include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/vector_icons_public.h"
+
+#if defined(OS_MACOSX)
+#include "grit/theme_resources.h"
+#endif
 
 namespace {
 
@@ -38,8 +42,21 @@
 RegisterProtocolHandlerPermissionRequest::
 ~RegisterProtocolHandlerPermissionRequest() {}
 
+gfx::VectorIconId RegisterProtocolHandlerPermissionRequest::GetVectorIconId()
+    const {
+#if defined(OS_MACOSX)
+  return gfx::VectorIconId::VECTOR_ICON_NONE;
+#else
+  return gfx::VectorIconId::PROTOCOL_HANDLER;
+#endif
+}
+
 int RegisterProtocolHandlerPermissionRequest::GetIconId() const {
+#if defined(OS_MACOSX)
   return IDR_REGISTER_PROTOCOL_HANDLER;
+#else
+  return 0;
+#endif
 }
 
 base::string16
diff --git a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
index 1acf5dc..1ccbf102 100644
--- a/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
+++ b/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
@@ -24,6 +24,7 @@
   ~RegisterProtocolHandlerPermissionRequest() override;
 
   // PermissionBubbleRequest:
+  gfx::VectorIconId GetVectorIconId() const override;
   int GetIconId() const override;
   base::string16 GetMessageText() const override;
   base::string16 GetMessageTextFragment() const override;
diff --git a/chrome/browser/defaults.cc b/chrome/browser/defaults.cc
index b742060..35cd53f 100644
--- a/chrome/browser/defaults.cc
+++ b/chrome/browser/defaults.cc
@@ -51,9 +51,6 @@
 const bool kScrollEventChangesTab = false;
 #endif
 
-const ui::ResourceBundle::FontStyle kAssociatedNetworkFontStyle =
-    ui::ResourceBundle::BoldFont;
-
 #if !defined(OS_ANDROID)
 const bool kPasswordEchoEnabled = false;
 #endif
diff --git a/chrome/browser/defaults.h b/chrome/browser/defaults.h
index 482f7c6..6d93b7c 100644
--- a/chrome/browser/defaults.h
+++ b/chrome/browser/defaults.h
@@ -8,8 +8,6 @@
 #define CHROME_BROWSER_DEFAULTS_H_
 
 #include "build/build_config.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "ui/base/resource/resource_bundle.h"
 
 namespace browser_defaults {
 
@@ -53,9 +51,6 @@
 // Should scroll events on the tabstrip change tabs?
 extern const bool kScrollEventChangesTab;
 
-// ChromiumOS network menu font
-extern const ui::ResourceBundle::FontStyle kAssociatedNetworkFontStyle;
-
 // Last character display for passwords.
 extern const bool kPasswordEchoEnabled;
 
diff --git a/chrome/browser/devtools/chrome_devtools_discovery_provider.cc b/chrome/browser/devtools/chrome_devtools_discovery_provider.cc
index 530405d..5d45ee5a 100644
--- a/chrome/browser/devtools/chrome_devtools_discovery_provider.cc
+++ b/chrome/browser/devtools/chrome_devtools_discovery_provider.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/devtools/devtools_target_impl.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 
 namespace {
 
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index bd98e9a..64a8c33 100644
--- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -223,6 +223,12 @@
     }
   }
 
+  bool FindInterfaceByEndpoint(uint8_t endpoint_address,
+                               uint8_t* interface_number) {
+    NOTIMPLEMENTED();
+    return false;
+  }
+
   template <class D>
   void append(D data) {
     std::copy(reinterpret_cast<char*>(&data),
diff --git a/chrome/browser/devtools/devtools_network_transaction.cc b/chrome/browser/devtools/devtools_network_transaction.cc
index af48f1c..48213c1 100644
--- a/chrome/browser/devtools/devtools_network_transaction.cc
+++ b/chrome/browser/devtools/devtools_network_transaction.cc
@@ -246,6 +246,11 @@
   return network_transaction_->GetLoadTimingInfo(load_timing_info);
 }
 
+bool DevToolsNetworkTransaction::GetRemoteEndpoint(
+    net::IPEndPoint* endpoint) const {
+  return network_transaction_->GetRemoteEndpoint(endpoint);
+}
+
 void DevToolsNetworkTransaction::SetPriority(net::RequestPriority priority) {
   network_transaction_->SetPriority(priority);
 }
diff --git a/chrome/browser/devtools/devtools_network_transaction.h b/chrome/browser/devtools/devtools_network_transaction.h
index 167727a..17f899d 100644
--- a/chrome/browser/devtools/devtools_network_transaction.h
+++ b/chrome/browser/devtools/devtools_network_transaction.h
@@ -101,6 +101,7 @@
   net::UploadProgress GetUploadProgress() const override;
   void SetQuicServerInfo(net::QuicServerInfo* quic_server_info) override;
   bool GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override;
+  bool GetRemoteEndpoint(net::IPEndPoint* endpoint) const override;
   void SetPriority(net::RequestPriority priority) override;
   void SetWebSocketHandshakeStreamCreateHelper(
       net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index db825a3..e8fc89c 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/location.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/prefs/pref_service.h"
@@ -49,6 +50,7 @@
 #include "content/public/browser/worker_service_observer.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/notification_types.h"
@@ -91,11 +93,14 @@
 const char kReloadSharedWorkerTestWorker[] =
     "files/workers/debug_shared_worker_initialization.js";
 
-void RunTestFunction(DevToolsWindow* window, const char* test_name) {
+template <typename... T>
+void DispatchOnTestSuite(DevToolsWindow* window,
+                         const char* method,
+                         T... args) {
   std::string result;
-
-  RenderViewHost* rvh = DevToolsWindowTesting::Get(window)->
-      main_web_contents()->GetRenderViewHost();
+  RenderViewHost* rvh = DevToolsWindowTesting::Get(window)
+                            ->main_web_contents()
+                            ->GetRenderViewHost();
   // At first check that JavaScript part of the front-end is loaded by
   // checking that global variable uiTests exists(it's created after all js
   // files have been loaded) and has runTest method.
@@ -103,17 +108,29 @@
       content::ExecuteScriptAndExtractString(
           rvh,
           "window.domAutomationController.send("
-          "    '' + (window.uiTests && (typeof uiTests.runTest)));",
+          "    '' + (window.uiTests && (typeof uiTests.dispatchOnTestSuite)));",
           &result));
-
   ASSERT_EQ("function", result) << "DevTools front-end is broken.";
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      rvh,
-      base::StringPrintf("uiTests.runTest('%s')", test_name),
-      &result));
+
+  const char* args_array[] = {method, args...};
+  std::ostringstream script;
+  script << "uiTests.dispatchOnTestSuite([";
+  for (size_t i = 0; i < arraysize(args_array); ++i)
+    script << (i ? "," : "") << '\"' << args_array[i] << '\"';
+  script << "])";
+  ASSERT_TRUE(
+      content::ExecuteScriptAndExtractString(rvh, script.str(), &result));
   EXPECT_EQ("[OK]", result);
 }
 
+void RunTestFunction(DevToolsWindow* window, const char* test_name) {
+  DispatchOnTestSuite(window, test_name);
+}
+
+void SwitchToPanel(DevToolsWindow* window, const char* panel) {
+  DispatchOnTestSuite(window, "switchToPanel", panel);
+}
+
 }  // namespace
 
 class DevToolsSanityTest : public InProcessBrowserTest {
@@ -878,12 +895,40 @@
       content::ExecuteScriptAndExtractString(
           main_web_contents()->GetRenderViewHost(),
           "window.domAutomationController.send("
-          "    '' + (window.uiTests && (typeof uiTests.runTest)));",
+          "    '' + (window.uiTests && (typeof uiTests.dispatchOnTestSuite)));",
           &result));
   ASSERT_EQ("function", result) << "DevTools front-end is broken.";
   CloseDevToolsWindow();
 }
 
+class DevToolsReattachAfterCrashTest : public DevToolsSanityTest {
+ protected:
+  void RunTestWithPanel(const char* panel_name) {
+    OpenDevToolsWindow("about:blank", false);
+    SwitchToPanel(window_, panel_name);
+    ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+    content::RenderProcessHostWatcher crash_observer(
+        GetInspectedTab(),
+        content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+    ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
+    crash_observer.Wait();
+    content::TestNavigationObserver navigation_observer(GetInspectedTab(), 1);
+    chrome::Reload(browser(), CURRENT_TAB);
+    navigation_observer.Wait();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(DevToolsReattachAfterCrashTest,
+                       TestReattachAfterCrashOnTimeline) {
+  RunTestWithPanel("timeline");
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsReattachAfterCrashTest,
+                       TestReattachAfterCrashOnNetwork) {
+  RunTestWithPanel("network");
+}
+
 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, InspectSharedWorker) {
 #if defined(OS_WIN) && defined(USE_ASH)
   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 43348883..8ebae8c 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -300,11 +300,11 @@
  private:
   // contents::WebContentsObserver:
   void RenderProcessGone(base::TerminationStatus status) override;
-  void DidStartProvisionalLoadForFrame(
-      content::RenderFrameHost* render_frame_host,
-      const GURL& validated_url,
-      bool is_error_page,
-      bool is_iframe_srcdoc) override;
+  // TODO(creis): Replace with RenderFrameCreated when http://crbug.com/425397
+  // is fixed.  See also http://crbug.com/424641.
+  void AboutToNavigateRenderFrame(
+      content::RenderFrameHost* old_host,
+      content::RenderFrameHost* new_host) override;
   void DocumentOnLoadCompletedInMainFrame() override;
   void DidNavigateMainFrame(
       const content::LoadCommittedDetails& details,
@@ -346,14 +346,12 @@
 }
 
 void DevToolsUIBindings::FrontendWebContentsObserver::
-    DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host,
-                                    const GURL& validated_url,
-                                    bool is_error_page,
-                                    bool is_iframe_srcdoc) {
-  if (render_frame_host->GetParent())
+    AboutToNavigateRenderFrame(content::RenderFrameHost* old_host,
+                               content::RenderFrameHost* new_host) {
+  if (new_host->GetParent())
     return;
   devtools_bindings_->frontend_host_.reset(
-      content::DevToolsFrontendHost::Create(render_frame_host,
+      content::DevToolsFrontendHost::Create(new_host,
                                             devtools_bindings_));
 }
 
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index 8e617d73..1e6a533b 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -1263,8 +1263,13 @@
   return event_forwarder_->ForwardEvent(event);
 }
 
-void DevToolsWindow::ReloadInspectedWebContents(bool ignore_cache) {
+bool DevToolsWindow::ReloadInspectedWebContents(bool ignore_cache) {
+  // Only route reload via front-end if the agent is attached.
+  WebContents* wc = GetInspectedWebContents();
+  if (!wc || wc->GetCrashedStatus() != base::TERMINATION_STATUS_STILL_RUNNING)
+    return false;
   base::FundamentalValue ignore_cache_value(ignore_cache);
   bindings_->CallClientFunction("DevToolsAPI.reloadInspectedPage",
                                 &ignore_cache_value, nullptr, nullptr);
+  return true;
 }
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h
index c9d9aaf6..e73817e 100644
--- a/chrome/browser/devtools/devtools_window.h
+++ b/chrome/browser/devtools/devtools_window.h
@@ -125,7 +125,9 @@
   bool ForwardKeyboardEvent(const content::NativeWebKeyboardEvent& event);
 
   // Reloads inspected web contents as if it was triggered from DevTools.
-  void ReloadInspectedWebContents(bool ignore_cache);
+  // Returns true if it has successfully handled reload, false if the caller
+  // is to proceed reload without DevTools interception.
+  bool ReloadInspectedWebContents(bool ignore_cache);
 
   content::WebContents* OpenURLFromTab(
       content::WebContents* source,
diff --git a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
index 0d84bbf1..9c69f4d6 100644
--- a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
+++ b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 7dbaa89..f04c13f 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/download/download_shelf.h"
 #include "chrome/browser/download/download_target_determiner.h"
 #include "chrome/browser/download/download_test_file_activity_observer.h"
-#include "chrome/browser/download/notification/download_notification_manager.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #include "chrome/browser/extensions/extension_install_prompt_show_params.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -3392,8 +3391,10 @@
 
 class DownloadTestWithShelf : public DownloadTest {
   void SetUpCommandLine(base::CommandLine* command_line) override {
+#if defined(OS_CHROMEOS)
     command_line->AppendSwitchASCII(switches::kEnableDownloadNotification,
                                     "disabled");
+#endif
     DownloadTest::SetUpCommandLine(command_line);
   }
 };
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc
index 5f3f3cd..0ec6610 100644
--- a/chrome/browser/download/download_shelf.cc
+++ b/chrome/browser/download/download_shelf.cc
@@ -84,9 +84,8 @@
   bg_paint.setColor(SkColorSetA(indicator_color, 0x33));
   bg_paint.setAntiAlias(true);
   const SkScalar kCenterPoint = kProgressIndicatorSize / 2.f;
-  const SkScalar kRadius = 12.5f;
   SkPath bg;
-  bg.addCircle(kCenterPoint, kCenterPoint, kRadius);
+  bg.addCircle(kCenterPoint, kCenterPoint, kCenterPoint);
   canvas->DrawPath(bg, bg_paint);
 
   // Calculate progress.
@@ -104,11 +103,9 @@
 
   // Draw progress.
   SkPath progress;
-  progress.addArc(SkRect::MakeLTRB(kCenterPoint - kRadius,
-                                   kCenterPoint - kRadius,
-                                   kCenterPoint + kRadius,
-                                   kCenterPoint + kRadius),
-                  start_pos, sweep_angle);
+  progress.addArc(
+      SkRect::MakeLTRB(0, 0, kProgressIndicatorSize, kProgressIndicatorSize),
+      start_pos, sweep_angle);
   SkPaint progress_paint;
   progress_paint.setColor(indicator_color);
   progress_paint.setStyle(SkPaint::kStroke_Style);
diff --git a/chrome/browser/download/download_shelf.h b/chrome/browser/download/download_shelf.h
index 7ae5021..bf3de940 100644
--- a/chrome/browser/download/download_shelf.h
+++ b/chrome/browser/download/download_shelf.h
@@ -53,8 +53,8 @@
     // Progress animation timer period, in milliseconds.
     kProgressRateMs = 30,
 
-    // Size of the space used for the progress indicator, including padding.
-    kProgressIndicatorSize = 39,
+    // Size of the space used for the progress indicator.
+    kProgressIndicatorSize = 25,
 
     // x/y offset for the file type icon.
     kFiletypeIconOffset = (kProgressIndicatorSize - 16) / 2
diff --git a/chrome/browser/download/download_ui_controller.cc b/chrome/browser/download/download_ui_controller.cc
index ae197a84..c21aa81 100644
--- a/chrome/browser/download/download_ui_controller.cc
+++ b/chrome/browser/download/download_ui_controller.cc
@@ -19,12 +19,15 @@
 #if defined(OS_ANDROID)
 #include "content/public/browser/android/download_controller_android.h"
 #else
-#include "chrome/browser/download/notification/download_notification_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/host_desktop.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/download/notification/download_notification_manager.h"
+#endif
+
 namespace {
 
 // DownloadShelfUIControllerDelegate{Android,} is used when a
@@ -104,22 +107,23 @@
                                            scoped_ptr<Delegate> delegate)
     : download_notifier_(manager, this),
       delegate_(delegate.Pass()) {
-  if (!delegate_) {
 #if defined(OS_ANDROID)
+  if (!delegate_)
     delegate_.reset(new AndroidUIControllerDelegate());
 #else
-    // The delegate should not be invoked after the profile has gone away. This
-    // should be the case since DownloadUIController is owned by
-    // DownloadService, which in turn is a profile keyed service.
-    if (DownloadNotificationManager::IsEnabled()) {
-      delegate_.reset(new DownloadNotificationManager(
-          Profile::FromBrowserContext(manager->GetBrowserContext())));
-    } else {
-      delegate_.reset(new DownloadShelfUIControllerDelegate(
-          Profile::FromBrowserContext(manager->GetBrowserContext())));
-    }
-#endif
+#if defined(OS_CHROMEOS)
+  if (!delegate_ && DownloadNotificationManager::IsEnabled()) {
+    // The Profile is guaranteed to be valid since DownloadUIController is owned
+    // by DownloadService, which in turn is a profile keyed service.
+    delegate_.reset(new DownloadNotificationManager(
+        Profile::FromBrowserContext(manager->GetBrowserContext())));
   }
+#endif  // defined(OS_CHROMEOS)
+  if (!delegate_) {
+    delegate_.reset(new DownloadShelfUIControllerDelegate(
+        Profile::FromBrowserContext(manager->GetBrowserContext())));
+  }
+#endif  // defined(OS_ANDROID)
 }
 
 DownloadUIController::~DownloadUIController() {
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index acc044c..bb7ed7d 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -32,15 +32,12 @@
 #include "ui/base/l10n/time_format.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/codec/jpeg_codec.h"
-#include "ui/gfx/image/image.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_style.h"
-
-#if !defined(OS_MACOSX)
 #include "ui/gfx/color_palette.h"
+#include "ui/gfx/image/image.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/vector_icons_public.h"
-#endif
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_style.h"
 
 using base::UserMetricsAction;
 
@@ -513,12 +510,8 @@
                                   gfx::kChromeIconGrey);
 #endif
       } else {
-#if defined(OS_MACOSX)
-        SetNotificationIcon(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING);
-#else
         SetNotificationVectorIcon(gfx::VectorIconId::FILE_DOWNLOAD,
                                   gfx::kGoogleBlue);
-#endif
       }
       break;
 
@@ -561,7 +554,6 @@
   notification_->set_icon(bundle.GetImageNamed(image_resource_id_));
 }
 
-#if !defined(OS_MACOSX)
 void DownloadItemNotification::SetNotificationVectorIcon(gfx::VectorIconId id,
                                                          SkColor color) {
   if (vector_icon_params_ == std::make_pair(id, color))
@@ -570,7 +562,6 @@
   image_resource_id_ = 0;
   notification_->set_icon(gfx::Image(gfx::CreateVectorIcon(id, 40, color)));
 }
-#endif
 
 void DownloadItemNotification::OnImageLoaded(const std::string& image_data) {
   if (image_data.empty())
diff --git a/chrome/browser/download/notification/download_item_notification.h b/chrome/browser/download/notification/download_item_notification.h
index d712893d..ce5c97b 100644
--- a/chrome/browser/download/notification/download_item_notification.h
+++ b/chrome/browser/download/notification/download_item_notification.h
@@ -18,10 +18,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_observer.h"
-
-#if !defined(OS_MACOSX)
 #include "ui/native_theme/native_theme.h"
-#endif
 
 namespace test {
 class DownloadItemNotificationTest;
@@ -67,10 +64,7 @@
 
   // Set icon of the notification.
   void SetNotificationIcon(int resource_id);
-
-#if !defined(OS_MACOSX)
   void SetNotificationVectorIcon(gfx::VectorIconId id, SkColor color);
-#endif
 
   // Set preview image of the notification. Must be called on IO thread.
   void OnImageLoaded(const std::string& image_data);
@@ -112,9 +106,7 @@
   bool visible_ = false;
 
   int image_resource_id_ = 0;
-#if !defined(OS_MACOSX)
   std::pair<gfx::VectorIconId, SkColor> vector_icon_params_;
-#endif
   content::DownloadItem::DownloadState previous_download_state_ =
       content::DownloadItem::MAX_DOWNLOAD_STATE;  // As uninitialized state
   bool previous_dangerous_state_ = false;
diff --git a/chrome/browser/download/notification/download_notification_manager.cc b/chrome/browser/download/notification/download_notification_manager.cc
index 64ad9a7..41e75a8 100644
--- a/chrome/browser/download/notification/download_notification_manager.cc
+++ b/chrome/browser/download/notification/download_notification_manager.cc
@@ -24,12 +24,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool DownloadNotificationManager::IsEnabled() {
-#if defined(OS_CHROMEOS)
   bool enable_download_notification = true;
-#else
-  bool enable_download_notification = false;
-#endif
-
   std::string arg = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
       switches::kEnableDownloadNotification);
   if (!arg.empty()) {
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
index ddfb53e9..67ba5402 100644
--- a/chrome/browser/download/save_page_browsertest.cc
+++ b/chrome/browser/download/save_page_browsertest.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/download/download_service.h"
 #include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/download/notification/download_notification_manager.h"
 #include "chrome/browser/download/save_package_file_picker.h"
 #include "chrome/browser/net/url_request_mock_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -47,6 +46,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/url_request/url_request_mock_http_job.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using content::BrowserContext;
@@ -55,6 +55,7 @@
 using content::DownloadManager;
 using content::WebContents;
 using net::URLRequestMockHTTPJob;
+using testing::HasSubstr;
 
 namespace {
 
@@ -774,6 +775,28 @@
   EXPECT_EQ("foo", contents);
 }
 
+// Test that we don't crash when the page contains an iframe that
+// was handled as a download (http://crbug.com/42212).
+// Flaky: https://crbug.com/537530.
+IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveDownloadableIFrame) {
+  GURL url = URLRequestMockHTTPJob::GetMockUrl(
+      base::FilePath(FILE_PATH_LITERAL("downloads"))
+          .AppendASCII("iframe-src-is-a-download.htm"));
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Wait for and then dismiss the non-save-page-as-related download item
+  // (the one associated with downloading of "thisdayinhistory.xls" file).
+  VerifySavePackageExpectations(browser(), url);
+  GetDownloadManager()->RemoveAllDownloads();
+
+  base::FilePath full_file_name, dir;
+  SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML,
+                 "iframe-src-is-a-download", 2, &dir, &full_file_name);
+  ASSERT_FALSE(HasFailure());
+
+  EXPECT_TRUE(base::PathExists(full_file_name));
+}
+
 class SavePageSitePerProcessBrowserTest : public SavePageBrowserTest {
  public:
   SavePageSitePerProcessBrowserTest() {}
@@ -784,7 +807,9 @@
 
     // TODO(lukasza): Enable --site-per-process once crbug.com/526786 is fixed.
     // (currently, when the line below is uncommented out, the test crashes
-    // under RenderViewImpl::OnGetSerializedHtmlDataForCu...PageWithLocalLinks).
+    // under blink::WebLocalFrameImpl::fromFrameOwnerElement called from
+    // blink::WebPageSerializerImpl::openTagToString).
+    //
     // content::IsolateAllSitesForTesting(command_line);
   }
 
@@ -809,19 +834,21 @@
     return;  // Avoid failing on Site Isolation FYI bot.
   }
 
-  GURL url(embedded_test_server()->GetURL(
-      "a.com", "/frame_tree/page_with_two_frames_remote_and_local.html"));
+  GURL url(embedded_test_server()->GetURL("a.com", "/save_page/iframes.htm"));
   ui_test_utils::NavigateToURL(browser(), url);
 
   base::FilePath full_file_name, dir;
-  SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, "xsite1", 3,
+  SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, "iframes", 5,
                  &dir, &full_file_name);
   ASSERT_FALSE(HasFailure());
 
   EXPECT_TRUE(base::DirectoryExists(dir));
   base::FilePath expected_files[] = {
-      full_file_name, dir.AppendASCII("title1.html"),
-      dir.AppendASCII("title1(1).html"),
+      full_file_name,
+      dir.AppendASCII("a.html"),  // From iframes.htm
+      dir.AppendASCII("b.html"),  // From iframes.htm
+      dir.AppendASCII("1.css"),   // From b.htm
+      dir.AppendASCII("1.png"),   // Deduplicated from iframes.htm and b.htm.
   };
   for (auto file_path : expected_files) {
     EXPECT_TRUE(base::PathExists(file_path)) << "Does " << file_path.value()
@@ -831,6 +858,18 @@
     EXPECT_NE(0, actual_file_size) << "Is " << file_path.value()
                                    << " non-empty?";
   }
+
+  // Verify that local links got correctly replaced with local paths
+  // (most importantly for iframe elements, which are only exercised
+  // by this particular test).
+  std::string main_contents;
+  ASSERT_TRUE(base::ReadFileToString(full_file_name, &main_contents));
+  EXPECT_THAT(main_contents,
+              HasSubstr("<iframe src=\"./iframes_files/a.html\"></iframe>"));
+  EXPECT_THAT(main_contents,
+              HasSubstr("<iframe src=\"./iframes_files/b.html\"></iframe>"));
+  EXPECT_THAT(main_contents,
+              HasSubstr("<img src=\"./iframes_files/1.png\">"));
 }
 
 }  // namespace
diff --git a/chrome/browser/engagement/OWNERS b/chrome/browser/engagement/OWNERS
index 86e271a..3bbe63ea 100644
--- a/chrome/browser/engagement/OWNERS
+++ b/chrome/browser/engagement/OWNERS
@@ -1,2 +1,3 @@
 benwells@chromium.org
+calamity@chromium.org
 raymes@chromium.org
diff --git a/chrome/browser/extensions/active_script_controller.cc b/chrome/browser/extensions/active_script_controller.cc
index e5c3f03..11a97eb 100644
--- a/chrome/browser/extensions/active_script_controller.cc
+++ b/chrome/browser/extensions/active_script_controller.cc
@@ -89,26 +89,26 @@
   URLPatternSet new_explicit_hosts;
   URLPatternSet new_scriptable_hosts;
 
-  const PermissionSet* withheld_permissions =
+  const PermissionSet& withheld_permissions =
       extension->permissions_data()->withheld_permissions();
-  if (withheld_permissions->explicit_hosts().MatchesURL(url)) {
+  if (withheld_permissions.explicit_hosts().MatchesURL(url)) {
     new_explicit_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                                  url.GetOrigin());
   }
-  if (withheld_permissions->scriptable_hosts().MatchesURL(url)) {
+  if (withheld_permissions.scriptable_hosts().MatchesURL(url)) {
     new_scriptable_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                                    url.GetOrigin());
   }
 
-  PermissionSet new_permissions(APIPermissionSet(), ManifestPermissionSet(),
-                                new_explicit_hosts, new_scriptable_hosts);
 
   // Update permissions for the session. This adds |new_permissions| to active
   // permissions and granted permissions.
   // TODO(devlin): Make sure that the permission is removed from
   // withheld_permissions if appropriate.
   PermissionsUpdater(browser_context_)
-      .AddPermissions(extension, &new_permissions);
+      .AddPermissions(extension,
+                      PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+                                    new_explicit_hosts, new_scriptable_hosts));
 
   // Allow current tab to run injection.
   OnClicked(extension);
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
index 834cda50..ebf771a 100644
--- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -37,7 +37,7 @@
   const PermissionsData* permissions_data = ext->permissions_data();
   const URLPatternSet& pattern_set =
       effective_perm ? permissions_data->GetEffectiveHostPermissions()
-                     : permissions_data->active_permissions()->explicit_hosts();
+                     : permissions_data->active_permissions().explicit_hosts();
 
   base::ListValue* permissions = new base::ListValue;
   for (URLPatternSet::const_iterator perm = pattern_set.begin();
@@ -52,7 +52,7 @@
 base::ListValue* GetAPIPermissions(const Extension* ext) {
   base::ListValue* permissions = new base::ListValue;
   std::set<std::string> perm_list =
-      ext->permissions_data()->active_permissions()->GetAPIsAsStrings();
+      ext->permissions_data()->active_permissions().GetAPIsAsStrings();
   for (std::set<std::string>::const_iterator perm = perm_list.begin();
        perm != perm_list.end(); ++perm) {
     permissions->Append(new base::StringValue(perm->c_str()));
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
index 2b927349..122dcffd 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -673,7 +673,13 @@
   for (size_t i = 0; i < params->devices.size(); ++i) {
     devices.Append(params->devices[i]->ToValue().release());
   }
-  EasyUnlockService::Get(profile)->SetRemoteDevices(devices);
+  // Store the BLE device if we are trying out the BLE experiment.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery)) {
+    EasyUnlockService::Get(profile)->SetRemoteBleDevices(devices);
+  } else {
+    EasyUnlockService::Get(profile)->SetRemoteDevices(devices);
+  }
 
   return true;
 }
@@ -1039,7 +1045,12 @@
           make_scoped_ptr(new base::DefaultTickClock()))) {}
 
 EasyUnlockPrivateFindSetupConnectionFunction::
-    ~EasyUnlockPrivateFindSetupConnectionFunction() {}
+    ~EasyUnlockPrivateFindSetupConnectionFunction() {
+  // |connection_finder_| has a raw pointer to |bluetooth_throttler_|, so it
+  // should be destroyed first.
+  connection_finder_.reset();
+  bluetooth_throttler_.reset();
+}
 
 void EasyUnlockPrivateFindSetupConnectionFunction::
     OnConnectionFinderTimedOut() {
@@ -1141,4 +1152,27 @@
   return true;
 }
 
+EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction::
+    EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction() {}
+
+EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction::
+    ~EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction() {}
+
+bool EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction::RunSync() {
+  scoped_ptr<easy_unlock_private::SetupConnectionGetDeviceAddress::Params>
+      params =
+          easy_unlock_private::SetupConnectionGetDeviceAddress::Params::Create(
+              *args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+  std::string device_address =
+      GetConnectionManager(browser_context())
+          ->GetDeviceAddress(extension(), params->connection_id);
+  results_ =
+      easy_unlock_private::SetupConnectionGetDeviceAddress::Results::Create(
+          device_address);
+  if (device_address.empty())
+    SetError("Invalid connectionId.");
+  return true;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
index 31c15ca..347c6606 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h
@@ -535,6 +535,24 @@
   DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateSetupConnectionSendFunction);
 };
 
+class EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction
+    : public SyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION(
+      "easyUnlockPrivate.setupConnectionGetDeviceAddress",
+      EASYUNLOCKPRIVATE_SETUPCONNECTIONGETDEVICEADDRESS)
+  EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction();
+
+ private:
+  ~EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction() override;
+
+  // SyncExtensionFunction:
+  bool RunSync() override;
+
+  DISALLOW_COPY_AND_ASSIGN(
+      EasyUnlockPrivateSetupConnectionGetDeviceAddressFunction);
+};
+
 }  // namespace extensions
 
 #endif  // CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
index 912bd70..fc1c8c8 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
@@ -26,6 +26,7 @@
 #include "chromeos/dbus/fake_easy_unlock_client.h"
 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/proximity_auth/switches.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "extensions/browser/api_test_utils.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/event_router_factory.h"
@@ -127,6 +128,10 @@
  protected:
   void SetUp() override {
     chromeos::DBusThreadManager::Initialize();
+    bluez::BluezDBusManager::Initialize(
+        chromeos::DBusThreadManager::Get()->GetSystemBus(),
+        chromeos::DBusThreadManager::Get()->IsUsingStub(
+            chromeos::DBusClientBundle::BLUETOOTH));
     client_ = chromeos::DBusThreadManager::Get()->GetEasyUnlockClient();
 
     extensions::ExtensionApiUnittest::SetUp();
@@ -135,6 +140,7 @@
   void TearDown() override {
     extensions::ExtensionApiUnittest::TearDown();
 
+    bluez::BluezDBusManager::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
   }
 
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
index 9003855f..878e6ab6 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
@@ -70,6 +70,15 @@
   return api::easy_unlock_private::CONNECTION_STATUS_NONE;
 }
 
+std::string EasyUnlockPrivateConnectionManager::GetDeviceAddress(
+    const Extension* extension,
+    int connection_id) const {
+  Connection* connection = GetConnection(extension->id(), connection_id);
+  if (!connection)
+    return std::string();
+  return connection->GetDeviceAddress();
+}
+
 bool EasyUnlockPrivateConnectionManager::Disconnect(const Extension* extension,
                                                     int connection_id) {
   Connection* connection = GetConnection(extension->id(), connection_id);
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h
index 3d2f7a61..a0ca893a 100644
--- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h
+++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h
@@ -52,6 +52,11 @@
                    int connection_id,
                    const std::string& payload);
 
+  // Returns the Bluetooth address of the device connected with a given
+  // |connection_id|, and an empty string if |connection_id| was not found.
+  std::string GetDeviceAddress(const Extension* extension,
+                               int connection_id) const;
+
   // proximity_auth::ConnectionObserver:
   void OnConnectionStatusChanged(
       proximity_auth::Connection* connection,
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index 9aa4d7f..58391bf9 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -72,6 +72,16 @@
 static const char kChromiumDomainRedirectUrlPattern[] =
     "https://%s.chromiumapp.org/";
 
+#if defined(OS_CHROMEOS)
+// The list of apps that are allowed to use the Identity API to retrieve the
+// token from the device robot account in a public session.
+const char* const kPublicSessionAllowedOrigins[] = {
+    // Chrome Remote Desktop - Chromium branding.
+    "chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
+    // Chrome Remote Desktop - Official branding.
+    "chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/"};
+#endif
+
 std::string GetPrimaryAccountId(content::BrowserContext* context) {
   SigninManagerBase* signin_manager =
       SigninManagerFactory::GetForProfile(Profile::FromBrowserContext(context));
@@ -371,8 +381,16 @@
 #if defined(OS_CHROMEOS)
   policy::BrowserPolicyConnectorChromeOS* connector =
       g_browser_process->platform_part()->browser_policy_connector_chromeos();
-  if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp() &&
-      connector->IsEnterpriseManaged()) {
+  bool is_kiosk = user_manager::UserManager::Get()->IsLoggedInAsKioskApp();
+  bool is_public_session =
+      user_manager::UserManager::Get()->IsLoggedInAsPublicAccount();
+
+  if (connector->IsEnterpriseManaged() && (is_kiosk || is_public_session)) {
+    if (is_public_session && !IsOriginWhitelistedInPublicSession()) {
+      CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+      return true;
+    }
+
     StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
     return true;
   }
@@ -494,8 +512,15 @@
     switch (cache_status) {
       case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
 #if defined(OS_CHROMEOS)
-        // Always force minting token for ChromeOS kiosk app.
-        if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp()) {
+        // Always force minting token for ChromeOS kiosk app and public session.
+        if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
+            !IsOriginWhitelistedInPublicSession()) {
+          CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+          return;
+        }
+
+        if (user_manager::UserManager::Get()->IsLoggedInAsKioskApp() ||
+            user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()) {
           gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
           policy::BrowserPolicyConnectorChromeOS* connector =
               g_browser_process->platform_part()
@@ -753,6 +778,19 @@
                             scopes,
                             this);
 }
+
+bool IdentityGetAuthTokenFunction::IsOriginWhitelistedInPublicSession() {
+  DCHECK(extension());
+  GURL extension_url = extension()->url();
+  for (size_t i = 0; i < arraysize(kPublicSessionAllowedOrigins); i++) {
+    URLPattern allowed_origin(URLPattern::SCHEME_ALL,
+                              kPublicSessionAllowedOrigins[i]);
+    if (allowed_origin.MatchesSecurityOrigin(extension_url)) {
+      return true;
+    }
+  }
+  return false;
+}
 #endif
 
 void IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest() {
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h
index 1155adc..067dac3 100644
--- a/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -264,8 +264,12 @@
 
 #if defined(OS_CHROMEOS)
   // Starts a login access token request for device robot account. This method
-  // will be called only in enterprise kiosk mode in ChromeOS.
+  // will be called only in Chrome OS for:
+  // 1. Enterprise kiosk mode.
+  // 2. Whitelisted first party apps in public session.
   virtual void StartDeviceLoginAccessTokenRequest();
+
+  bool IsOriginWhitelistedInPublicSession();
 #endif
 
   // Methods for invoking UI. Overridable for testing.
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 93028b4..8d84b3d 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -12,6 +12,13 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
+#include "extensions/common/extension_builder.h"
+#endif
 #include "chrome/browser/extensions/api/identity/identity_api.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/extension_apitest.h"
@@ -340,6 +347,12 @@
     }
   }
 
+#if defined(OS_CHROMEOS)
+  void StartDeviceLoginAccessTokenRequest() override {
+    StartLoginAccessTokenRequest();
+  }
+#endif
+
   void ShowLoginPopup() override {
     EXPECT_FALSE(login_ui_shown_);
     login_ui_shown_ = true;
@@ -1614,6 +1627,84 @@
   EXPECT_TRUE(ContainsKey(token_key->scopes, "bar"));
 }
 
+
+#if defined(OS_CHROMEOS)
+class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest {
+ public:
+  GetAuthTokenFunctionPublicSessionTest()
+      : user_manager_(new chromeos::MockUserManager) {}
+
+ protected:
+  void SetUpInProcessBrowserTestFixture() override {
+     GetAuthTokenFunctionTest::SetUpInProcessBrowserTestFixture();
+
+     // Set up the user manager to fake a public session.
+     EXPECT_CALL(*user_manager_, IsLoggedInAsKioskApp())
+         .WillRepeatedly(Return(false));
+     EXPECT_CALL(*user_manager_, IsLoggedInAsPublicAccount())
+         .WillRepeatedly(Return(true));
+
+    // Set up fake install attributes to make the device appeared as
+    // enterprise-managed.
+    scoped_ptr<policy::StubEnterpriseInstallAttributes> attributes(
+        new policy::StubEnterpriseInstallAttributes());
+    attributes->SetDomain("example.com");
+    attributes->SetRegistrationUser("user@example.com");
+    policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
+        attributes.release());
+  }
+
+  scoped_refptr<Extension> CreateTestExtension(const std::string& id) {
+    return ExtensionBuilder()
+        .SetManifest(
+             DictionaryBuilder()
+                 .Set("name", "Test")
+                 .Set("version", "1.0")
+                 .Set(
+                     "oauth2",
+                     DictionaryBuilder()
+                         .Set("client_id", "clientId")
+                         .Set(
+                             "scopes",
+                             ListBuilder().Append("scope1"))))
+        .SetLocation(Manifest::UNPACKED)
+        .SetID(id)
+        .Build();
+  }
+
+  // Owned by |user_manager_enabler|.
+  chromeos::MockUserManager* user_manager_;
+};
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest, NonWhitelisted) {
+  // GetAuthToken() should return UserNotSignedIn in public sessions for
+  // non-whitelisted extensions.
+  chromeos::ScopedUserManagerEnabler user_manager_enabler(user_manager_);
+  scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+  func->set_extension(CreateTestExtension("test-id"));
+  std::string error = utils::RunFunctionAndReturnError(
+      func.get(), "[]", browser());
+  EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
+  EXPECT_FALSE(func->login_ui_shown());
+  EXPECT_FALSE(func->scope_ui_shown());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest, Whitelisted) {
+  // GetAuthToken() should return a token for whitelisted extensions.
+  chromeos::ScopedUserManagerEnabler user_manager_enabler(user_manager_);
+  scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+  func->set_extension(CreateTestExtension("ljacajndfccfgnfohlgkdphmbnpkjflk"));
+  func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+  scoped_ptr<base::Value> value(
+      utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
+  std::string access_token;
+  EXPECT_TRUE(value->GetAsString(&access_token));
+  EXPECT_EQ(std::string(kAccessToken), access_token);
+}
+
+#endif
+
+
 class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
  protected:
   bool InvalidateDefaultToken() {
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 9e55149..1a76caf 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -26,6 +26,7 @@
 #include "chrome/common/extensions/api/language_settings_private.h"
 #include "chrome/common/spellcheck_common.h"
 #include "components/translate/core/browser/translate_download_manager.h"
+#include "components/translate/core/common/translate_util.h"
 #include "third_party/icu/source/i18n/unicode/coll.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_collator.h"
@@ -113,9 +114,11 @@
       language.display_name_rtl.reset(new bool(true));
     if (locale_set.count(pair.first) > 0)
       language.supports_ui.reset(new bool(true));
-    if (spellcheck_language_set.count(pair.first) > 0)
+    if (spellcheck_language_set.count(language.code) > 0)
       language.supports_spellcheck.reset(new bool(true));
-    if (translate_language_set.count(pair.first) > 0)
+    std::string translate_code = language.code;
+    translate::ToTranslateLanguageSynonym(&translate_code);
+    if (translate_language_set.count(translate_code) > 0)
       language.supports_translate.reset(new bool(true));
 
     language_list->Append(language.ToValue());
diff --git a/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
index 9580f41..af119115 100644
--- a/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
@@ -108,7 +108,8 @@
     network_portal_detector_ = new NetworkPortalDetectorImpl(
         g_browser_process->system_request_context(),
         true /* create_notification_controller */);
-    NetworkPortalDetector::InitializeForTesting(network_portal_detector_);
+    chromeos::network_portal_detector::InitializeForTesting(
+        network_portal_detector_);
     network_portal_detector_->Enable(false /* start_detection */);
     set_detector(network_portal_detector_->captive_portal_detector_.get());
   }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index f17f57a..e8336cc 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -223,6 +223,7 @@
                                     base::StringValue("Cellular1_Carrier"));
     base::DictionaryValue home_provider;
     home_provider.SetString("name", "Cellular1_Provider");
+    home_provider.SetString("code", "000000");
     home_provider.SetString("country", "us");
     device_test_->SetDeviceProperty(
         kCellularDevicePath, shill::kHomeProviderProperty, home_provider);
@@ -272,7 +273,7 @@
 
   void SetUpOnMainThread() override {
     detector_ = new NetworkPortalDetectorTestImpl();
-    NetworkPortalDetector::InitializeForTesting(detector_);
+    chromeos::network_portal_detector::InitializeForTesting(detector_);
 
     ExtensionApiTest::SetUpOnMainThread();
     content::RunAllPendingInMessageLoop();
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api_browsertest.cc b/chrome/browser/extensions/api/omnibox/omnibox_api_browsertest.cc
index e646b7e..ae9e76f 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api_browsertest.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api_browsertest.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/metrics/proto/omnibox_event.pb.h"
 #include "components/omnibox/browser/autocomplete_controller.h"
 #include "components/omnibox/browser/autocomplete_input.h"
@@ -31,7 +31,7 @@
   // The results depend on the TemplateURLService being loaded. Make sure it is
   // loaded so that the autocomplete results are consistent.
   Profile* profile = browser()->profile();
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(profile));
 
   AutocompleteController* autocomplete_controller =
@@ -161,7 +161,7 @@
 IN_PROC_BROWSER_TEST_F(OmniboxApiTest, OnInputEntered) {
   ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
   Profile* profile = browser()->profile();
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(profile));
 
   LocationBar* location_bar = GetLocationBar(browser());
@@ -216,7 +216,7 @@
 
   // The results depend on the TemplateURLService being loaded. Make sure it is
   // loaded so that the autocomplete results are consistent.
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(browser()->profile()));
 
   LocationBar* location_bar = GetLocationBar(incognito_browser);
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
index 79c4ad8..1d1f00b6 100644
--- a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
+++ b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/metrics/proto/omnibox_event.pb.h"
 #include "extensions/test/result_catcher.h"
 
@@ -18,7 +18,7 @@
   // The results depend on the TemplateURLService being loaded. Make sure it is
   // loaded so that the autocomplete results are consistent.
   Profile* profile = browser()->profile();
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(profile));
 
   LocationBar* location_bar = GetLocationBar(browser());
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc
index da393353..e5a83a24d 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api.cc
@@ -64,7 +64,7 @@
     return false;
 
   results_ = Contains::Results::Create(
-      extension()->permissions_data()->active_permissions()->Contains(
+      extension()->permissions_data()->active_permissions().Contains(
           *permissions));
   return true;
 }
@@ -103,13 +103,13 @@
   // optional and required (and should assume its required), so we need both of
   // these checks.
   // TODO(devlin): *Why* do we support that? Should be a load error.
-  const PermissionSet* optional =
+  const PermissionSet& optional =
       PermissionsParser::GetOptionalPermissions(extension());
-  const PermissionSet* required =
+  const PermissionSet& required =
       PermissionsParser::GetRequiredPermissions(extension());
-  if (!optional->Contains(*permissions) ||
+  if (!optional.Contains(*permissions) ||
       !scoped_ptr<const PermissionSet>(
-           PermissionSet::CreateIntersection(*permissions, *required))
+           PermissionSet::CreateIntersection(*permissions, required))
            ->IsEmpty()) {
     error_ = kCantRemoveRequiredPermissionsError;
     return false;
@@ -119,10 +119,10 @@
   // For backwards compatability with behavior before this check was added, just
   // silently remove any that aren't present.
   permissions = PermissionSet::CreateIntersection(
-      *permissions, *extension()->permissions_data()->active_permissions());
+      *permissions, extension()->permissions_data()->active_permissions());
 
   PermissionsUpdater(GetProfile())
-      .RemovePermissions(extension(), permissions.get(),
+      .RemovePermissions(extension(), *permissions,
                          PermissionsUpdater::REMOVE_SOFT);
   results_ = Remove::Results::Create(true);
   return true;
@@ -143,7 +143,7 @@
 
 void PermissionsRequestFunction::InstallUIProceed() {
   PermissionsUpdater perms_updater(GetProfile());
-  perms_updater.AddPermissions(extension(), requested_permissions_.get());
+  perms_updater.AddPermissions(extension(), *requested_permissions_);
 
   results_ = Request::Results::Create(true);
   SendResponse(true);
@@ -192,7 +192,7 @@
 
   // The requested permissions must be defined as optional in the manifest.
   if (!PermissionsParser::GetOptionalPermissions(extension())
-           ->Contains(*requested_permissions_)) {
+           .Contains(*requested_permissions_)) {
     error_ = kNotInOptionalPermissionsError;
     return false;
   }
@@ -212,7 +212,7 @@
           ->GetGrantedPermissions(extension()->id());
   if (granted.get() && granted->Contains(*requested_permissions_)) {
     PermissionsUpdater perms_updater(GetProfile());
-    perms_updater.AddPermissions(extension(), requested_permissions_.get());
+    perms_updater.AddPermissions(extension(), *requested_permissions_);
     results_ = Request::Results::Create(true);
     SendResponse(true);
     return true;
@@ -225,7 +225,7 @@
   // Filter out the active permissions.
   requested_permissions_ = PermissionSet::CreateDifference(
       *requested_permissions_,
-      *extension()->permissions_data()->active_permissions());
+      extension()->permissions_data()->active_permissions());
 
   AddRef();  // Balanced in InstallUIProceed() / InstallUIAbort().
 
@@ -236,9 +236,9 @@
       PermissionMessageProvider::Get();
   bool has_no_warnings =
       message_provider->GetPermissionMessages(
-                            message_provider->GetAllPermissionIDs(
-                                requested_permissions_.get(),
-                                extension()->GetType())).empty();
+                          message_provider->GetAllPermissionIDs(
+                              *requested_permissions_, extension()->GetType()))
+          .empty();
   if (auto_confirm_for_tests == PROCEED || has_no_warnings ||
       extension_->location() == Manifest::COMPONENT) {
     InstallUIProceed();
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
index 298ece3f..b4cb705e 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
@@ -35,17 +35,16 @@
 
 }  // namespace
 
-scoped_ptr<Permissions> PackPermissionSet(const PermissionSet* set) {
-  Permissions* permissions(new Permissions());
+scoped_ptr<Permissions> PackPermissionSet(const PermissionSet& set) {
+  scoped_ptr<Permissions> permissions(new Permissions());
 
   permissions->permissions.reset(new std::vector<std::string>());
-  for (APIPermissionSet::const_iterator i = set->apis().begin();
-       i != set->apis().end(); ++i) {
-    scoped_ptr<base::Value> value(i->ToValue());
+  for (const APIPermission* api : set.apis()) {
+    scoped_ptr<base::Value> value(api->ToValue());
     if (!value) {
-      permissions->permissions->push_back(i->name());
+      permissions->permissions->push_back(api->name());
     } else {
-      std::string name(i->name());
+      std::string name(api->name());
       std::string json;
       base::JSONWriter::Write(*value, &json);
       permissions->permissions->push_back(name + kDelimiter + json);
@@ -56,11 +55,10 @@
   // to apps/extensions via the permissions API.
 
   permissions->origins.reset(new std::vector<std::string>());
-  URLPatternSet hosts = set->explicit_hosts();
-  for (URLPatternSet::const_iterator i = hosts.begin(); i != hosts.end(); ++i)
-    permissions->origins->push_back(i->GetAsString());
+  for (const URLPattern& pattern : set.explicit_hosts())
+    permissions->origins->push_back(pattern.GetAsString());
 
-  return scoped_ptr<Permissions>(permissions);
+  return permissions.Pass();
 }
 
 scoped_ptr<const PermissionSet> UnpackPermissionSet(
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers.h b/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
index 5284c44..89e866a 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
@@ -27,7 +27,7 @@
 
 // Converts the permission |set| to a permissions object.
 scoped_ptr<api::permissions::Permissions> PackPermissionSet(
-    const PermissionSet* set);
+    const PermissionSet& set);
 
 // Creates a permission set from |permissions|. Returns NULL if the permissions
 // cannot be converted to a permission set, in which case |error| will be set.
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
index 0cd5c85..88ba016 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
@@ -40,7 +40,7 @@
                                URLPatternSet());
 
   // Pack the permission set to value and verify its contents.
-  scoped_ptr<Permissions> permissions(PackPermissionSet(&permission_set));
+  scoped_ptr<Permissions> permissions(PackPermissionSet(permission_set));
   scoped_ptr<base::DictionaryValue> value(permissions->ToValue());
   base::ListValue* api_list = NULL;
   base::ListValue* origin_list = NULL;
diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
index 37f82c84..bab711a9 100644
--- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -92,12 +92,11 @@
   ManifestPermissionSet manifest_permissions;
   URLPatternSet explicit_hosts;
   AddPattern(&explicit_hosts, "http://*.c.com/*");
-  PermissionSet granted_permissions(apis, manifest_permissions, explicit_hosts,
-                                    URLPatternSet());
 
   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
   prefs->AddGrantedPermissions("kjmkgkdkpedkejedfhmfcenooemhbpbo",
-                               &granted_permissions);
+                               PermissionSet(apis, manifest_permissions,
+                                             explicit_hosts, URLPatternSet()));
 
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   host_resolver()->AddRule("*.com", "127.0.0.1");
diff --git a/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc b/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
index a119636d..db0eea7 100644
--- a/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
+++ b/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -46,8 +47,9 @@
  public:
   explicit FakeProfileSyncService(Profile* profile)
       : ProfileSyncService(
-            scoped_ptr<sync_driver::SyncApiComponentFactory>(
-                new ProfileSyncComponentsFactoryMock()),
+            make_scoped_ptr(new browser_sync::ChromeSyncClient(
+                profile,
+                make_scoped_ptr(new ProfileSyncComponentsFactoryMock()))),
             profile,
             make_scoped_ptr<SigninManagerWrapper>(NULL),
             ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index 8a61cde8..5e752f4 100644
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "components/update_client/update_query_params.h"
 #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/extensions/api/sessions/sessions_api.cc b/chrome/browser/extensions/api/sessions/sessions_api.cc
index 94930c5f..72c053a 100644
--- a/chrome/browser/extensions/api/sessions/sessions_api.cc
+++ b/chrome/browser/extensions/api/sessions/sessions_api.cc
@@ -26,7 +26,7 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
@@ -457,11 +457,11 @@
   }
 
   bool is_window = is_window_entry(entries.front());
-  sessions::TabRestoreServiceDelegate* delegate =
-      BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+  sessions::LiveTabContext* context =
+      BrowserLiveTabContext::FindContextForWebContents(
           browser->tab_strip_model()->GetActiveWebContents());
   std::vector<sessions::LiveTab*> restored_tabs =
-      tab_restore_service->RestoreMostRecentEntry(delegate, host_desktop_type);
+      tab_restore_service->RestoreMostRecentEntry(context, host_desktop_type);
   DCHECK(restored_tabs.size());
 
   sessions::ContentLiveTab* first_tab =
@@ -499,11 +499,11 @@
     }
   }
 
-  sessions::TabRestoreServiceDelegate* delegate =
-      BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+  sessions::LiveTabContext* context =
+      BrowserLiveTabContext::FindContextForWebContents(
           browser->tab_strip_model()->GetActiveWebContents());
   std::vector<sessions::LiveTab*> restored_tabs =
-      tab_restore_service->RestoreEntryById(delegate, session_id.id(),
+      tab_restore_service->RestoreEntryById(context, session_id.id(),
                                             host_desktop_type, UNKNOWN);
   // If the ID is invalid, restored_tabs will be empty.
   if (!restored_tabs.size()) {
diff --git a/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index 90ebba8..e711896 100644
--- a/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -137,7 +138,9 @@
               "device_id")));
 
   return make_scoped_ptr(new ProfileSyncServiceMock(
-      factory.Pass(), static_cast<Profile*>(context)));
+      make_scoped_ptr(new browser_sync::ChromeSyncClient(
+          static_cast<Profile*>(context), factory.Pass())),
+      static_cast<Profile*>(context)));
 }
 
 void ExtensionSessionsTest::CreateTestProfileSyncService() {
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index ba87a08..11612f2 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -110,6 +110,10 @@
       settings_private::PrefType::PREF_TYPE_BOOLEAN;
   (*s_whitelist)["browser.clear_data.time_period"] =
       settings_private::PrefType::PREF_TYPE_NUMBER;
+  (*s_whitelist)["translate.enabled"] =
+      settings_private::PrefType::PREF_TYPE_BOOLEAN;
+  (*s_whitelist)["translate_blocked_languages"] =
+      settings_private::PrefType::PREF_TYPE_LIST;
 
 #if defined(OS_CHROMEOS)
   (*s_whitelist)["cros.accounts.allowBWSI"] =
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index 09a2680..dc2ac63 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc
index c8f6b7b..0da8e740 100644
--- a/chrome/browser/extensions/bundle_installer.cc
+++ b/chrome/browser/extensions/bundle_installer.cc
@@ -268,7 +268,7 @@
     // and doesn't compile. Use a more verbose, but compilable, workaround.
     permissions = PermissionSet::CreateUnion(
         permissions ? *permissions : empty,
-        *dummy_extensions_[i]->permissions_data()->active_permissions());
+        dummy_extensions_[i]->permissions_data()->active_permissions());
   }
 
   if (g_auto_approve_for_test == PROCEED) {
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index e2dce03..c1eb2d74 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -50,6 +50,7 @@
 #include "chrome/browser/extensions/updater/chromeos_extension_cache_delegate.h"
 #include "chrome/browser/extensions/updater/extension_cache_impl.h"
 #include "chromeos/chromeos_switches.h"
+#include "components/user_manager/user_manager.h"
 #else
 #include "extensions/browser/updater/null_extension_cache.h"
 #endif
@@ -225,6 +226,14 @@
   return chrome::IsRunningInForcedAppMode();
 }
 
+bool ChromeExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
+#if defined(OS_CHROMEOS)
+  return user_manager::UserManager::Get()->IsLoggedInAsPublicAccount();
+#else
+  return false;
+#endif
+}
+
 ApiActivityMonitor* ChromeExtensionsBrowserClient::GetApiActivityMonitor(
     content::BrowserContext* context) {
   // The ActivityLog monitors and records function calls and events.
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.h b/chrome/browser/extensions/chrome_extensions_browser_client.h
index 852a27c..c9d41a34 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.h
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.h
@@ -83,6 +83,7 @@
   bool DidVersionUpdate(content::BrowserContext* context) override;
   void PermitExternalProtocolHandler() override;
   bool IsRunningInForcedAppMode() override;
+  bool IsLoggedInAsPublicAccount() override;
   ApiActivityMonitor* GetApiActivityMonitor(
       content::BrowserContext* context) override;
   ExtensionSystemProvider* GetExtensionSystemFactory() override;
diff --git a/chrome/browser/extensions/convert_web_app_browsertest.cc b/chrome/browser/extensions/convert_web_app_browsertest.cc
index 5210ca0..2ee3c54d 100644
--- a/chrome/browser/extensions/convert_web_app_browsertest.cc
+++ b/chrome/browser/extensions/convert_web_app_browsertest.cc
@@ -94,11 +94,10 @@
             AppLaunchInfo::GetLaunchWebURL(installed_extension_));
   EXPECT_EQ(LAUNCH_CONTAINER_TAB,
             AppLaunchInfo::GetLaunchContainer(installed_extension_));
-  EXPECT_EQ(0u,
-            installed_extension_->permissions_data()
-                ->active_permissions()
-                ->apis()
-                .size());
+  EXPECT_EQ(0u, installed_extension_->permissions_data()
+                    ->active_permissions()
+                    .apis()
+                    .size());
   EXPECT_EQ(0u, IconsInfo::GetIcons(installed_extension_).map().size());
 }
 
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc
index 644369ac..bdc5e5f 100644
--- a/chrome/browser/extensions/convert_web_app_unittest.cc
+++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -131,7 +131,7 @@
   EXPECT_EQ(base::UTF16ToUTF8(web_app.description), extension->description());
   EXPECT_EQ(web_app.app_url, AppLaunchInfo::GetFullLaunchURL(extension.get()));
   EXPECT_EQ(0u,
-            extension->permissions_data()->active_permissions()->apis().size());
+            extension->permissions_data()->active_permissions().apis().size());
   ASSERT_EQ(0u, extension->web_extent().patterns().size());
 
   EXPECT_EQ(web_app.icons.size(),
@@ -178,7 +178,7 @@
   EXPECT_EQ(web_app.app_url, AppLaunchInfo::GetFullLaunchURL(extension.get()));
   EXPECT_EQ(0u, IconsInfo::GetIcons(extension.get()).map().size());
   EXPECT_EQ(0u,
-            extension->permissions_data()->active_permissions()->apis().size());
+            extension->permissions_data()->active_permissions().apis().size());
   ASSERT_EQ(0u, extension->web_extent().patterns().size());
 }
 
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index f0c319c3..bcfd265 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -278,12 +278,12 @@
     bool valid = false;
     if (expected_manifest_check_level_ ==
         WebstoreInstaller::MANIFEST_CHECK_LEVEL_NONE) {
-        // To skip manifest checking, the extension must be a shared module
-        // and not request any permissions.
+      // To skip manifest checking, the extension must be a shared module
+      // and not request any permissions.
       if (SharedModuleInfo::IsSharedModule(extension) &&
-          extension->permissions_data()->active_permissions()->IsEmpty()) {
-          valid = true;
-        }
+          extension->permissions_data()->active_permissions().IsEmpty()) {
+        valid = true;
+      }
     } else {
       valid = expected_manifest_->Equals(original_manifest_.get());
       if (!valid && expected_manifest_check_level_ ==
@@ -297,10 +297,8 @@
                               extension->id(),
                               &error);
         if (error.empty()) {
-          const PermissionSet* expected_permissions =
-              dummy_extension->permissions_data()->active_permissions();
           valid = !(PermissionMessageProvider::Get()->IsPrivilegeIncrease(
-              expected_permissions,
+              dummy_extension->permissions_data()->active_permissions(),
               extension->permissions_data()->active_permissions(),
               extension->GetType()));
         }
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index 9f0ad7d..9a90a37 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -856,15 +856,15 @@
         profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
         .InitializePermissions(extension_);
     permissions_to_display =
-        extension_->permissions_data()->active_permissions();
+        &extension_->permissions_data()->active_permissions();
     // For delegated installs, all optional permissions are pre-approved by the
     // person who triggers the install, so add them to the list.
     if (prompt_->type() == DELEGATED_PERMISSIONS_PROMPT ||
         prompt_->type() == DELEGATED_BUNDLE_PERMISSIONS_PROMPT) {
-      const PermissionSet* optional_permissions =
+      const PermissionSet& optional_permissions =
           extensions::PermissionsParser::GetOptionalPermissions(extension_);
       permissions_wrapper = PermissionSet::CreateUnion(*permissions_to_display,
-                                                       *optional_permissions);
+                                                       optional_permissions);
       permissions_to_display = permissions_wrapper.get();
     }
   }
@@ -880,16 +880,16 @@
 
     prompt_->SetPermissions(message_provider->GetPermissionMessages(
                                 message_provider->GetAllPermissionIDs(
-                                    permissions_to_display, type)),
+                                    *permissions_to_display, type)),
                             REGULAR_PERMISSIONS);
 
     const PermissionSet* withheld =
-        extension_ ? extension_->permissions_data()->withheld_permissions()
+        extension_ ? &extension_->permissions_data()->withheld_permissions()
                    : nullptr;
     if (withheld && !withheld->IsEmpty()) {
       prompt_->SetPermissions(
           message_provider->GetPermissionMessages(
-              message_provider->GetAllPermissionIDs(withheld, type)),
+              message_provider->GetAllPermissionIDs(*withheld, type)),
           WITHHELD_PERMISSIONS);
     }
   }
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 66e9c7a..501976d4 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -213,76 +213,70 @@
     EXPECT_TRUE(prefs()->GetGrantedPermissions(extension_id_)->IsEmpty());
 
     {
-      PermissionSet permissions(api_perm_set1_, empty_manifest_permissions,
-                                empty_extent, empty_extent);
-
-    // Add part of the api permissions.
-    prefs()->AddGrantedPermissions(extension_id_, &permissions);
-    scoped_ptr<const PermissionSet> granted_permissions =
-        prefs()->GetGrantedPermissions(extension_id_);
-    EXPECT_TRUE(granted_permissions.get());
-    EXPECT_FALSE(granted_permissions->IsEmpty());
-    EXPECT_EQ(expected_apis, granted_permissions->apis());
-    EXPECT_TRUE(granted_permissions->effective_hosts().is_empty());
-    EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
+      // Add part of the api permissions.
+      prefs()->AddGrantedPermissions(
+          extension_id_,
+          PermissionSet(api_perm_set1_, empty_manifest_permissions,
+                        empty_extent, empty_extent));
+      scoped_ptr<const PermissionSet> granted_permissions =
+          prefs()->GetGrantedPermissions(extension_id_);
+      EXPECT_TRUE(granted_permissions.get());
+      EXPECT_FALSE(granted_permissions->IsEmpty());
+      EXPECT_EQ(expected_apis, granted_permissions->apis());
+      EXPECT_TRUE(granted_permissions->effective_hosts().is_empty());
+      EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
     }
 
     {
-    // Add part of the explicit host permissions.
-    PermissionSet permissions(empty_set, empty_manifest_permissions,
-                              ehost_perm_set1_, empty_extent);
-    prefs()->AddGrantedPermissions(extension_id_, &permissions);
-    scoped_ptr<const PermissionSet> granted_permissions =
-        prefs()->GetGrantedPermissions(extension_id_);
-    EXPECT_FALSE(granted_permissions->IsEmpty());
-    EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
-    EXPECT_EQ(expected_apis, granted_permissions->apis());
-    EXPECT_EQ(ehost_perm_set1_,
-              granted_permissions->explicit_hosts());
-    EXPECT_EQ(ehost_perm_set1_,
-              granted_permissions->effective_hosts());
+      // Add part of the explicit host permissions.
+      prefs()->AddGrantedPermissions(
+          extension_id_, PermissionSet(empty_set, empty_manifest_permissions,
+                                       ehost_perm_set1_, empty_extent));
+      scoped_ptr<const PermissionSet> granted_permissions =
+          prefs()->GetGrantedPermissions(extension_id_);
+      EXPECT_FALSE(granted_permissions->IsEmpty());
+      EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
+      EXPECT_EQ(expected_apis, granted_permissions->apis());
+      EXPECT_EQ(ehost_perm_set1_, granted_permissions->explicit_hosts());
+      EXPECT_EQ(ehost_perm_set1_, granted_permissions->effective_hosts());
     }
 
     {
-    // Add part of the scriptable host permissions.
-    PermissionSet permissions(empty_set, empty_manifest_permissions,
-                              empty_extent, shost_perm_set1_);
-    prefs()->AddGrantedPermissions(extension_id_, &permissions);
-    scoped_ptr<const PermissionSet> granted_permissions =
-        prefs()->GetGrantedPermissions(extension_id_);
-    EXPECT_FALSE(granted_permissions->IsEmpty());
-    EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
-    EXPECT_EQ(expected_apis, granted_permissions->apis());
-    EXPECT_EQ(ehost_perm_set1_,
-              granted_permissions->explicit_hosts());
-    EXPECT_EQ(shost_perm_set1_,
-              granted_permissions->scriptable_hosts());
+      // Add part of the scriptable host permissions.
+      prefs()->AddGrantedPermissions(
+          extension_id_, PermissionSet(empty_set, empty_manifest_permissions,
+                                       empty_extent, shost_perm_set1_));
+      scoped_ptr<const PermissionSet> granted_permissions =
+          prefs()->GetGrantedPermissions(extension_id_);
+      EXPECT_FALSE(granted_permissions->IsEmpty());
+      EXPECT_FALSE(granted_permissions->HasEffectiveFullAccess());
+      EXPECT_EQ(expected_apis, granted_permissions->apis());
+      EXPECT_EQ(ehost_perm_set1_, granted_permissions->explicit_hosts());
+      EXPECT_EQ(shost_perm_set1_, granted_permissions->scriptable_hosts());
 
-    effective_permissions_ =
-        URLPatternSet::CreateUnion(ehost_perm_set1_, shost_perm_set1_);
-    EXPECT_EQ(effective_permissions_, granted_permissions->effective_hosts());
+      effective_permissions_ =
+          URLPatternSet::CreateUnion(ehost_perm_set1_, shost_perm_set1_);
+      EXPECT_EQ(effective_permissions_, granted_permissions->effective_hosts());
     }
 
     {
-    // Add the rest of the permissions.
-    PermissionSet permissions(api_perm_set2_, empty_manifest_permissions,
-                              ehost_perm_set2_, shost_perm_set2_);
+      // Add the rest of the permissions.
+      APIPermissionSet::Union(expected_apis, api_perm_set2_, &api_permissions_);
+      prefs()->AddGrantedPermissions(
+          extension_id_,
+          PermissionSet(api_perm_set2_, empty_manifest_permissions,
+                        ehost_perm_set2_, shost_perm_set2_));
 
-    APIPermissionSet::Union(expected_apis, api_perm_set2_, &api_permissions_);
-
-    prefs()->AddGrantedPermissions(extension_id_, &permissions);
-    scoped_ptr<const PermissionSet> granted_permissions =
-        prefs()->GetGrantedPermissions(extension_id_);
-    EXPECT_TRUE(granted_permissions.get());
-    EXPECT_FALSE(granted_permissions->IsEmpty());
-    EXPECT_EQ(api_permissions_, granted_permissions->apis());
-    EXPECT_EQ(ehost_permissions_,
-              granted_permissions->explicit_hosts());
-    EXPECT_EQ(shost_permissions_,
-              granted_permissions->scriptable_hosts());
-    effective_permissions_ =
-        URLPatternSet::CreateUnion(ehost_permissions_, shost_permissions_);
-    EXPECT_EQ(effective_permissions_, granted_permissions->effective_hosts());
+      scoped_ptr<const PermissionSet> granted_permissions =
+          prefs()->GetGrantedPermissions(extension_id_);
+      EXPECT_TRUE(granted_permissions.get());
+      EXPECT_FALSE(granted_permissions->IsEmpty());
+      EXPECT_EQ(api_permissions_, granted_permissions->apis());
+      EXPECT_EQ(ehost_permissions_, granted_permissions->explicit_hosts());
+      EXPECT_EQ(shost_permissions_, granted_permissions->scriptable_hosts());
+      effective_permissions_ =
+          URLPatternSet::CreateUnion(ehost_permissions_, shost_permissions_);
+      EXPECT_EQ(effective_permissions_, granted_permissions->effective_hosts());
     }
   }
 
@@ -345,18 +339,18 @@
     EXPECT_TRUE(active->IsEmpty());
 
     // Set the active permissions.
-    prefs()->SetActivePermissions(extension_id_, active_perms_.get());
+    prefs()->SetActivePermissions(extension_id_, *active_perms_);
     active = prefs()->GetActivePermissions(extension_id_);
     EXPECT_EQ(active_perms_->apis(), active->apis());
     EXPECT_EQ(active_perms_->explicit_hosts(), active->explicit_hosts());
     EXPECT_EQ(active_perms_->scriptable_hosts(), active->scriptable_hosts());
-    EXPECT_EQ(*active_perms_.get(), *active.get());
+    EXPECT_EQ(*active_perms_, *active);
   }
 
   void Verify() override {
     scoped_ptr<const PermissionSet> permissions =
         prefs()->GetActivePermissions(extension_id_);
-    EXPECT_EQ(*active_perms_.get(), *permissions.get());
+    EXPECT_EQ(*active_perms_, *permissions);
   }
 
  private:
@@ -961,10 +955,9 @@
     active_perms_.reset(new PermissionSet(api_perms, empty_manifest_permissions,
                                           ehosts, shosts));
     // Set the active permissions.
-    prefs()->SetActivePermissions(component_extension_->id(),
-                                  active_perms_.get());
+    prefs()->SetActivePermissions(component_extension_->id(), *active_perms_);
     prefs()->SetActivePermissions(no_component_extension_->id(),
-                                  active_perms_.get());
+                                  *active_perms_);
   }
 
   void Verify() override {
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 19fc175..f008366 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -1612,7 +1612,7 @@
     // to a version that requires additional privileges.
     is_privilege_increase =
         extensions::PermissionMessageProvider::Get()->IsPrivilegeIncrease(
-            granted_permissions.get(),
+            *granted_permissions,
             extension->permissions_data()->active_permissions(),
             extension->GetType());
   }
@@ -1848,10 +1848,9 @@
   for (const auto& extension : *all_extensions.get()) {
     if (!settings->IsPermissionSetAllowed(
             extension.get(),
-            *extension->permissions_data()->active_permissions())) {
+            extension->permissions_data()->active_permissions())) {
       extensions::PermissionsUpdater(profile()).RemovePermissionsUnsafe(
-          extension.get(),
-          settings->GetBlockedPermissions(extension.get()).get());
+          extension.get(), *settings->GetBlockedPermissions(extension.get()));
     }
   }
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index d40ebf1..f23ebee 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -792,7 +792,7 @@
   // set for extension |id|.
   void GrantAllOptionalPermissions(const std::string& id) {
     const Extension* extension = service()->GetInstalledExtension(id);
-    const PermissionSet* all_optional_permissions =
+    const PermissionSet& all_optional_permissions =
         extensions::PermissionsParser::GetOptionalPermissions(extension);
     extensions::PermissionsUpdater perms_updater(profile());
     perms_updater.AddPermissions(extension, all_optional_permissions);
@@ -1320,7 +1320,7 @@
   AddPattern(&expected_patterns, "https://*.google.com/*");
   EXPECT_EQ(
       expected_patterns,
-      extension->permissions_data()->active_permissions()->explicit_hosts());
+      extension->permissions_data()->active_permissions().explicit_hosts());
 
   EXPECT_EQ(std::string(good1), loaded_[1]->id());
   EXPECT_EQ(std::string("My extension 2"), loaded_[1]->name());
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index d6bba33..0d87ec3 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -17,6 +17,7 @@
 #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_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/browser/ui/singleton_tabs.h"
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.cc b/chrome/browser/extensions/extension_uninstall_dialog.cc
index da9f0a0..36552a06 100644
--- a/chrome/browser/extensions/extension_uninstall_dialog.cc
+++ b/chrome/browser/extensions/extension_uninstall_dialog.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/grit/generated_resources.h"
 #include "extensions/browser/extension_dialog_auto_confirm.h"
 #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/extensions/fetch_apitest.cc b/chrome/browser/extensions/fetch_apitest.cc
index 3d85099..c35ad6e 100644
--- a/chrome/browser/extensions/fetch_apitest.cc
+++ b/chrome/browser/extensions/fetch_apitest.cc
@@ -6,6 +6,7 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/test_extension_dir.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/extensions/permission_messages_unittest.cc b/chrome/browser/extensions/permission_messages_unittest.cc
index be230e5..895bc2d 100644
--- a/chrome/browser/extensions/permission_messages_unittest.cc
+++ b/chrome/browser/extensions/permission_messages_unittest.cc
@@ -80,10 +80,10 @@
   std::vector<base::string16> GetOptionalPermissionMessages() {
     scoped_ptr<const PermissionSet> granted_permissions =
         env_.GetExtensionPrefs()->GetGrantedPermissions(app_->id());
-    const PermissionSet* optional_permissions =
+    const PermissionSet& optional_permissions =
         PermissionsParser::GetOptionalPermissions(app_.get());
     scoped_ptr<const PermissionSet> requested_permissions =
-        PermissionSet::CreateDifference(*optional_permissions,
+        PermissionSet::CreateDifference(optional_permissions,
                                         *granted_permissions);
     return GetMessages(*requested_permissions);
   }
@@ -95,15 +95,15 @@
   }
 
   std::vector<base::string16> active_permissions() {
-    return GetMessages(*app_->permissions_data()->active_permissions());
+    return GetMessages(app_->permissions_data()->active_permissions());
   }
 
   std::vector<base::string16> required_permissions() {
-    return GetMessages(*PermissionsParser::GetRequiredPermissions(app_.get()));
+    return GetMessages(PermissionsParser::GetRequiredPermissions(app_.get()));
   }
 
   std::vector<base::string16> optional_permissions() {
-    return GetMessages(*PermissionsParser::GetOptionalPermissions(app_.get()));
+    return GetMessages(PermissionsParser::GetOptionalPermissions(app_.get()));
   }
 
  private:
@@ -111,7 +111,7 @@
     std::vector<base::string16> messages;
     for (const PermissionMessage& msg :
          message_provider_->GetPermissionMessages(
-             message_provider_->GetAllPermissionIDs(&permissions,
+             message_provider_->GetAllPermissionIDs(permissions,
                                                     app_->GetType()))) {
       messages.push_back(msg.message());
     }
diff --git a/chrome/browser/extensions/permissions_based_management_policy_provider.cc b/chrome/browser/extensions/permissions_based_management_policy_provider.cc
index 4b4094e..feda69a 100644
--- a/chrome/browser/extensions/permissions_based_management_policy_provider.cc
+++ b/chrome/browser/extensions/permissions_based_management_policy_provider.cc
@@ -41,10 +41,8 @@
   if (Manifest::IsComponentLocation(extension->location()))
     return true;
 
-  const PermissionSet* required_permissions =
-      PermissionsParser::GetRequiredPermissions(extension);
-
-  if (!settings_->IsPermissionSetAllowed(extension, *required_permissions)) {
+  if (!settings_->IsPermissionSetAllowed(
+          extension, PermissionsParser::GetRequiredPermissions(extension))) {
     if (error) {
       *error =
           l10n_util::GetStringFUTF16(IDS_EXTENSION_CANT_INSTALL_POLICY_BLOCKED,
diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc
index 2505836..7ad22f6 100644
--- a/chrome/browser/extensions/permissions_updater.cc
+++ b/chrome/browser/extensions/permissions_updater.cc
@@ -66,9 +66,9 @@
   // custom set of active permissions defined in the extension prefs. Here,
   // we update the extension's active permissions based on the prefs.
   if (!active_permissions)
-    return extension->permissions_data()->active_permissions()->Clone();
+    return extension->permissions_data()->active_permissions().Clone();
 
-  const PermissionSet* required_permissions =
+  const PermissionSet& required_permissions =
       PermissionsParser::GetRequiredPermissions(extension);
 
   // We restrict the active permissions to be within the bounds defined in the
@@ -77,8 +77,8 @@
   //  b) active permissions must contains all default permissions
   scoped_ptr<const PermissionSet> total_permissions =
       PermissionSet::CreateUnion(
-          *required_permissions,
-          *PermissionsParser::GetOptionalPermissions(extension));
+          required_permissions,
+          PermissionsParser::GetOptionalPermissions(extension));
 
   // Make sure the active permissions contain no more than optional + default.
   scoped_ptr<const PermissionSet> adjusted_active =
@@ -87,7 +87,7 @@
 
   // Make sure the active permissions contain the default permissions.
   adjusted_active =
-      PermissionSet::CreateUnion(*required_permissions, *adjusted_active);
+      PermissionSet::CreateUnion(required_permissions, *adjusted_active);
 
   return adjusted_active;
 }
@@ -122,14 +122,14 @@
 
 PermissionsUpdater::~PermissionsUpdater() {}
 
-void PermissionsUpdater::AddPermissions(
-    const Extension* extension, const PermissionSet* permissions) {
-  const PermissionSet* active(
-      extension->permissions_data()->active_permissions());
+void PermissionsUpdater::AddPermissions(const Extension* extension,
+                                        const PermissionSet& permissions) {
+  const PermissionSet& active =
+      extension->permissions_data()->active_permissions();
   scoped_ptr<const PermissionSet> total =
-      PermissionSet::CreateUnion(*active, *permissions);
+      PermissionSet::CreateUnion(active, permissions);
   scoped_ptr<const PermissionSet> added =
-      PermissionSet::CreateDifference(*total, *active);
+      PermissionSet::CreateDifference(*total, active);
 
   SetPermissions(extension, total.Pass(), nullptr);
 
@@ -140,15 +140,15 @@
 }
 
 void PermissionsUpdater::RemovePermissions(const Extension* extension,
-                                           const PermissionSet* to_remove,
+                                           const PermissionSet& to_remove,
                                            RemoveType remove_type) {
   // We should only be revoking revokable permissions.
-  CHECK(GetRevokablePermissions(extension)->Contains(*to_remove));
+  CHECK(GetRevokablePermissions(extension)->Contains(to_remove));
 
-  const PermissionSet* active =
+  const PermissionSet& active =
       extension->permissions_data()->active_permissions();
   scoped_ptr<const PermissionSet> remaining =
-      PermissionSet::CreateDifference(*active, *to_remove);
+      PermissionSet::CreateDifference(active, to_remove);
 
   // Move any granted permissions that were in the withheld set back to the
   // withheld set so they can be added back later.
@@ -156,10 +156,9 @@
   // be a withheld permission.
   scoped_ptr<const PermissionSet> removed_withheld =
       PermissionSet::CreateDifference(
-          *to_remove, *PermissionsParser::GetOptionalPermissions(extension));
+          to_remove, PermissionsParser::GetOptionalPermissions(extension));
   scoped_ptr<const PermissionSet> withheld = PermissionSet::CreateUnion(
-      *removed_withheld,
-      *extension->permissions_data()->withheld_permissions());
+      *removed_withheld, extension->permissions_data()->withheld_permissions());
 
   SetPermissions(extension, remaining.Pass(), withheld.Pass());
 
@@ -171,20 +170,20 @@
         ->RemoveGrantedPermissions(extension->id(), to_remove);
   }
 
-  NotifyPermissionsUpdated(REMOVED, extension, *to_remove);
+  NotifyPermissionsUpdated(REMOVED, extension, to_remove);
 }
 
 void PermissionsUpdater::RemovePermissionsUnsafe(
     const Extension* extension,
-    const PermissionSet* to_remove) {
-  const PermissionSet* active =
+    const PermissionSet& to_remove) {
+  const PermissionSet& active =
       extension->permissions_data()->active_permissions();
   scoped_ptr<const PermissionSet> total =
-      PermissionSet::CreateDifference(*active, *to_remove);
+      PermissionSet::CreateDifference(active, to_remove);
   // |successfully_removed| might not equal |to_remove| if |to_remove| contains
   // permissions the extension didn't have.
   scoped_ptr<const PermissionSet> successfully_removed =
-      PermissionSet::CreateDifference(*active, *total);
+      PermissionSet::CreateDifference(active, *total);
 
   SetPermissions(extension, total.Pass(), nullptr);
   NotifyPermissionsUpdated(REMOVED, extension, *successfully_removed);
@@ -195,13 +194,13 @@
   // Optional permissions are revokable.
   scoped_ptr<const PermissionSet> wrapper;
   const PermissionSet* revokable_permissions =
-      PermissionsParser::GetOptionalPermissions(extension);
-  const PermissionSet* active_permissions =
+      &PermissionsParser::GetOptionalPermissions(extension);
+  const PermissionSet& active_permissions =
       extension->permissions_data()->active_permissions();
   // If click-to-script is enabled, then any hosts that are granted, but not
   // listed explicitly as a required permission, are also revokable.
   if (FeatureSwitch::scripts_require_action()->IsEnabled()) {
-    const PermissionSet* required_permissions =
+    const PermissionSet& required_permissions =
         PermissionsParser::GetRequiredPermissions(extension);
     auto find_revokable_hosts = [](const URLPatternSet& active_hosts,
                                    const URLPatternSet& required_hosts) {
@@ -215,11 +214,11 @@
       return revokable_hosts;
     };
     URLPatternSet revokable_explicit_hosts =
-        find_revokable_hosts(active_permissions->explicit_hosts(),
-                             required_permissions->explicit_hosts());
+        find_revokable_hosts(active_permissions.explicit_hosts(),
+                             required_permissions.explicit_hosts());
     URLPatternSet revokable_scriptable_hosts =
-        find_revokable_hosts(active_permissions->scriptable_hosts(),
-                             required_permissions->scriptable_hosts());
+        find_revokable_hosts(active_permissions.scriptable_hosts(),
+                             required_permissions.scriptable_hosts());
     scoped_ptr<const PermissionSet> revokable_host_permissions(
         new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
                           revokable_explicit_hosts,
@@ -228,7 +227,7 @@
                                          *revokable_host_permissions);
     revokable_permissions = wrapper.get();
   }
-  return PermissionSet::CreateIntersection(*active_permissions,
+  return PermissionSet::CreateIntersection(active_permissions,
                                            *revokable_permissions);
 }
 
@@ -249,7 +248,7 @@
   // it in preferences.
   if (init_flag_ & INIT_FLAG_TRANSIENT) {
     active_permissions = bounded_active =
-        extension->permissions_data()->active_permissions();
+        &extension->permissions_data()->active_permissions();
   } else {
     // As part of initializing permissions, we restrict access to the main
     // thread.
@@ -264,7 +263,7 @@
   // Determine whether or not to withhold host permissions.
   bool should_withhold_permissions = false;
   if (PermissionsData::ScriptsMayRequireActionForExtension(extension,
-                                                           bounded_active)) {
+                                                           *bounded_active)) {
     should_withhold_permissions =
         init_flag_ & INIT_FLAG_TRANSIENT ?
             !util::DefaultAllowedScriptingOnAllUrls() :
@@ -310,35 +309,33 @@
 }
 
 void PermissionsUpdater::WithholdImpliedAllHosts(const Extension* extension) {
-  const PermissionSet* active =
+  const PermissionSet& active =
       extension->permissions_data()->active_permissions();
-  const PermissionSet* withheld =
+  const PermissionSet& withheld =
       extension->permissions_data()->withheld_permissions();
 
-  URLPatternSet withheld_scriptable = withheld->scriptable_hosts();
+  URLPatternSet withheld_scriptable = withheld.scriptable_hosts();
   URLPatternSet active_scriptable;
-  SegregateUrlPermissions(active->scriptable_hosts(),
+  SegregateUrlPermissions(active.scriptable_hosts(),
                           true,  // withhold permissions
-                          &active_scriptable,
-                          &withheld_scriptable);
+                          &active_scriptable, &withheld_scriptable);
 
-  URLPatternSet withheld_explicit = withheld->explicit_hosts();
+  URLPatternSet withheld_explicit = withheld.explicit_hosts();
   URLPatternSet active_explicit;
-  SegregateUrlPermissions(active->explicit_hosts(),
+  SegregateUrlPermissions(active.explicit_hosts(),
                           true,  // withhold permissions
-                          &active_explicit,
-                          &withheld_explicit);
+                          &active_explicit, &withheld_explicit);
 
-  URLPatternSet delta_explicit = URLPatternSet::CreateDifference(
-      active->explicit_hosts(), active_explicit);
+  URLPatternSet delta_explicit =
+      URLPatternSet::CreateDifference(active.explicit_hosts(), active_explicit);
   URLPatternSet delta_scriptable = URLPatternSet::CreateDifference(
-      active->scriptable_hosts(), active_scriptable);
+      active.scriptable_hosts(), active_scriptable);
 
   SetPermissions(extension, make_scoped_ptr(new PermissionSet(
-                                active->apis(), active->manifest_permissions(),
+                                active.apis(), active.manifest_permissions(),
                                 active_explicit, active_scriptable)),
                  make_scoped_ptr(new PermissionSet(
-                     withheld->apis(), withheld->manifest_permissions(),
+                     withheld.apis(), withheld.manifest_permissions(),
                      withheld_explicit, withheld_scriptable)));
 
   NotifyPermissionsUpdated(
@@ -349,9 +346,9 @@
 
 void PermissionsUpdater::GrantWithheldImpliedAllHosts(
     const Extension* extension) {
-  const PermissionSet* active =
+  const PermissionSet& active =
       extension->permissions_data()->active_permissions();
-  const PermissionSet* withheld =
+  const PermissionSet& withheld =
       extension->permissions_data()->withheld_permissions();
 
   // Move the all-hosts permission from withheld to active.
@@ -359,19 +356,19 @@
   // withhold is allhosts (or something similar enough to it), so we can just
   // grant all withheld host permissions.
   URLPatternSet explicit_hosts = URLPatternSet::CreateUnion(
-      active->explicit_hosts(), withheld->explicit_hosts());
+      active.explicit_hosts(), withheld.explicit_hosts());
   URLPatternSet scriptable_hosts = URLPatternSet::CreateUnion(
-      active->scriptable_hosts(), withheld->scriptable_hosts());
+      active.scriptable_hosts(), withheld.scriptable_hosts());
 
   URLPatternSet delta_explicit =
-      URLPatternSet::CreateDifference(explicit_hosts, active->explicit_hosts());
+      URLPatternSet::CreateDifference(explicit_hosts, active.explicit_hosts());
   URLPatternSet delta_scriptable = URLPatternSet::CreateDifference(
-      scriptable_hosts, active->scriptable_hosts());
+      scriptable_hosts, active.scriptable_hosts());
 
   // Since we only withhold host permissions (so far), we know that withheld
   // permissions will be empty.
   SetPermissions(extension, make_scoped_ptr(new PermissionSet(
-                                active->apis(), active->manifest_permissions(),
+                                active.apis(), active.manifest_permissions(),
                                 explicit_hosts, scriptable_hosts)),
                  make_scoped_ptr(new PermissionSet()));
 
@@ -386,7 +383,7 @@
     scoped_ptr<const PermissionSet> active,
     scoped_ptr<const PermissionSet> withheld) {
   DCHECK(active);
-  const PermissionSet* active_weak = active.get();
+  const PermissionSet& active_weak = *active;
   if (withheld) {
     extension->permissions_data()->SetPermissions(active.Pass(),
                                                   withheld.Pass());
@@ -411,7 +408,7 @@
 
   scoped_ptr<base::ListValue> value(new base::ListValue());
   scoped_ptr<api::permissions::Permissions> permissions =
-      PackPermissionSet(&changed_permissions);
+      PackPermissionSet(changed_permissions);
   value->Append(permissions->ToValue().release());
   scoped_ptr<Event> event(new Event(histogram_value, event_name, value.Pass()));
   event->restrict_to_browser_context = browser_context_;
@@ -453,9 +450,9 @@
   ExtensionMsg_UpdatePermissions_Params params;
   params.extension_id = extension->id();
   params.active_permissions = ExtensionMsg_PermissionSetStruct(
-      *extension->permissions_data()->active_permissions());
+      extension->permissions_data()->active_permissions());
   params.withheld_permissions = ExtensionMsg_PermissionSetStruct(
-      *extension->permissions_data()->withheld_permissions());
+      extension->permissions_data()->withheld_permissions());
 
   // Send the new permissions to the renderers.
   for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
diff --git a/chrome/browser/extensions/permissions_updater.h b/chrome/browser/extensions/permissions_updater.h
index c7b1628..47d63c4 100644
--- a/chrome/browser/extensions/permissions_updater.h
+++ b/chrome/browser/extensions/permissions_updater.h
@@ -47,7 +47,7 @@
   // and sends the relevant messages and notifications. This method assumes the
   // user has already been prompted, if necessary, for the extra permissions.
   void AddPermissions(const Extension* extension,
-                      const PermissionSet* permissions);
+                      const PermissionSet& permissions);
 
   // Removes the set of |permissions| from the |extension|'s active permission
   // set and sends the relevant messages and notifications.
@@ -59,14 +59,14 @@
   // user. If it's the extension itself removing the permission, it is safe to
   // use REMOVE_SOFT.
   void RemovePermissions(const Extension* extension,
-                         const PermissionSet* permissions,
+                         const PermissionSet& permissions,
                          RemoveType remove_type);
 
   // Removes the |permissions| from |extension| and makes no effort to determine
   // if doing so is safe in the slightlest. This method shouldn't be used,
   // except for removing permissions totally blacklisted by management.
   void RemovePermissionsUnsafe(const Extension* extension,
-                               const PermissionSet* permissions);
+                               const PermissionSet& permissions);
 
   // Returns the set of revokable permissions.
   scoped_ptr<const PermissionSet> GetRevokablePermissions(
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index 26684581..91e383e 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -215,7 +215,7 @@
 
   // Make sure it loaded properly.
   ASSERT_EQ(default_permissions,
-            *extension->permissions_data()->active_permissions());
+            extension->permissions_data()->active_permissions());
 
   ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_.get());
   scoped_ptr<const PermissionSet> active_permissions;
@@ -232,7 +232,7 @@
                         URLPatternSet());
 
   PermissionsUpdaterListener listener;
-  PermissionsUpdater(profile_.get()).AddPermissions(extension.get(), &delta);
+  PermissionsUpdater(profile_.get()).AddPermissions(extension.get(), delta);
 
   listener.Wait();
 
@@ -245,7 +245,7 @@
   // Make sure the extension's active permissions reflect the change.
   active_permissions = PermissionSet::CreateUnion(default_permissions, delta);
   ASSERT_EQ(*active_permissions.get(),
-            *extension->permissions_data()->active_permissions());
+            extension->permissions_data()->active_permissions());
 
   // Verify that the new granted and active permissions were also stored
   // in the extension preferences. In this case, the granted permissions should
@@ -265,7 +265,7 @@
 
   PermissionsUpdaterListener listener;
   PermissionsUpdater(profile_.get())
-      .RemovePermissions(extension.get(), &delta,
+      .RemovePermissions(extension.get(), delta,
                          PermissionsUpdater::REMOVE_SOFT);
   listener.Wait();
 
@@ -278,8 +278,8 @@
   // Make sure the extension's active permissions reflect the change.
   active_permissions =
       PermissionSet::CreateDifference(*active_permissions, delta);
-  ASSERT_EQ(*active_permissions.get(),
-            *extension->permissions_data()->active_permissions());
+  ASSERT_EQ(*active_permissions,
+            extension->permissions_data()->active_permissions());
 
   // Verify that the extension prefs hold the new active permissions and the
   // same granted permissions.
@@ -326,16 +326,16 @@
   // At first, the active permissions should have only the safe patterns and
   // the withheld permissions should have only the all host patterns.
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       safe_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->explicit_hosts().patterns(),
+      permissions_data->active_permissions().explicit_hosts().patterns(),
       safe_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
+      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->explicit_hosts().patterns(),
+      permissions_data->withheld_permissions().explicit_hosts().patterns(),
       all_host_patterns));
 
   // Then, we grant the withheld all-hosts permissions.
@@ -343,17 +343,17 @@
   // Now, active permissions should have all patterns, and withheld permissions
   // should have none.
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->scriptable_hosts()
+                  .scriptable_hosts()
                   .patterns()
                   .empty());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->explicit_hosts().patterns(),
+      permissions_data->active_permissions().explicit_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->explicit_hosts()
+                  .explicit_hosts()
                   .patterns()
                   .empty());
 
@@ -363,16 +363,16 @@
   // We should be back to our initial state - all_hosts should be withheld, and
   // the safe patterns should be granted.
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       safe_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->explicit_hosts().patterns(),
+      permissions_data->active_permissions().explicit_hosts().patterns(),
       safe_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
+      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->explicit_hosts().patterns(),
+      permissions_data->withheld_permissions().explicit_hosts().patterns(),
       all_host_patterns));
 
   // Creating a component extension should result in no withheld permissions.
@@ -381,17 +381,17 @@
   permissions_data = extension->permissions_data();
   updater.InitializePermissions(extension.get());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->scriptable_hosts()
+                  .scriptable_hosts()
                   .patterns()
                   .empty());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->explicit_hosts().patterns(),
+      permissions_data->active_permissions().explicit_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->explicit_hosts()
+                  .explicit_hosts()
                   .patterns()
                   .empty());
 
@@ -402,17 +402,17 @@
   permissions_data = extension->permissions_data();
   updater.InitializePermissions(extension.get());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->scriptable_hosts()
+                  .scriptable_hosts()
                   .patterns()
                   .empty());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->explicit_hosts().patterns(),
+      permissions_data->active_permissions().explicit_hosts().patterns(),
       all_patterns));
   EXPECT_TRUE(permissions_data->withheld_permissions()
-                  ->explicit_hosts()
+                  .explicit_hosts()
                   .patterns()
                   .empty());
 }
@@ -435,10 +435,10 @@
   // Since the extension was created without the switch on, it should default
   // to having all urls access.
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_TRUE(
-      permissions_data->withheld_permissions()->scriptable_hosts().is_empty());
+      permissions_data->withheld_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(util::AllowedScriptingOnAllUrls(extension_a->id(), profile()));
 
   // Enable the switch, and re-init permission for the extension.
@@ -451,10 +451,10 @@
   // have the all urls pref.
   permissions_data = extension_a->permissions_data();
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions()->scriptable_hosts().patterns(),
+      permissions_data->active_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_TRUE(
-      permissions_data->withheld_permissions()->scriptable_hosts().is_empty());
+      permissions_data->withheld_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(util::AllowedScriptingOnAllUrls(extension_a->id(), profile()));
 
   // Load a new extension, which also has all urls. Since the switch is now on,
@@ -465,9 +465,9 @@
   permissions_data = extension_b->permissions_data();
 
   EXPECT_TRUE(
-      permissions_data->active_permissions()->scriptable_hosts().is_empty());
+      permissions_data->active_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
+      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_FALSE(util::AllowedScriptingOnAllUrls(extension_b->id(), profile()));
 
@@ -479,9 +479,9 @@
   // restricted with the switch off.
   permissions_data = extension_b->permissions_data();
   EXPECT_TRUE(
-      permissions_data->active_permissions()->scriptable_hosts().is_empty());
+      permissions_data->active_permissions().scriptable_hosts().is_empty());
   EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
+      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
       all_host_patterns));
   EXPECT_FALSE(util::AllowedScriptingOnAllUrls(extension_b->id(), profile()));
 }
@@ -522,7 +522,7 @@
 
     // Add the optional "cookies" permission.
     updater.AddPermissions(extension.get(),
-                           api_permission_set(APIPermission::kCookie).get());
+                           *api_permission_set(APIPermission::kCookie));
     const PermissionsData* permissions = extension->permissions_data();
     // The extension should have the permission in its active permissions and
     // its granted permissions (stored in prefs). And, the permission should
@@ -536,7 +536,7 @@
 
     // Repeat with "tabs".
     updater.AddPermissions(extension.get(),
-                           api_permission_set(APIPermission::kTab).get());
+                           *api_permission_set(APIPermission::kTab));
     EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab));
     granted_permissions = prefs->GetGrantedPermissions(extension->id());
     EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kTab));
@@ -547,7 +547,7 @@
     // in its active or granted permissions, and it shouldn't be revokable.
     // The extension should still have the "cookies" permission.
     updater.RemovePermissions(extension.get(),
-                              api_permission_set(APIPermission::kTab).get(),
+                              *api_permission_set(APIPermission::kTab),
                               PermissionsUpdater::REMOVE_HARD);
     EXPECT_FALSE(permissions->HasAPIPermission(APIPermission::kTab));
     granted_permissions = prefs->GetGrantedPermissions(extension->id());
@@ -583,38 +583,37 @@
     const GURL kOrigin("http://foo.com");
     EXPECT_FALSE(extension->permissions_data()
                      ->active_permissions()
-                     ->HasExplicitAccessToOrigin(kOrigin));
+                     .HasExplicitAccessToOrigin(kOrigin));
     EXPECT_TRUE(extension->permissions_data()
                     ->withheld_permissions()
-                    ->HasExplicitAccessToOrigin(kOrigin));
+                    .HasExplicitAccessToOrigin(kOrigin));
 
     const GURL kRequiredOrigin("http://www.google.com/");
     EXPECT_TRUE(extension->permissions_data()
                     ->active_permissions()
-                    ->HasExplicitAccessToOrigin(kRequiredOrigin));
+                    .HasExplicitAccessToOrigin(kRequiredOrigin));
     EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
                      ->HasExplicitAccessToOrigin(kRequiredOrigin));
 
     // Give the extension access to foo.com. Now, the foo.com permission should
     // be revokable.
-    updater.AddPermissions(extension.get(), url_permission_set(kOrigin).get());
+    updater.AddPermissions(extension.get(), *url_permission_set(kOrigin));
     EXPECT_TRUE(extension->permissions_data()
                     ->active_permissions()
-                    ->HasExplicitAccessToOrigin(kOrigin));
+                    .HasExplicitAccessToOrigin(kOrigin));
     EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
                     ->HasExplicitAccessToOrigin(kOrigin));
 
     // Revoke the foo.com permission. The extension should no longer have
     // access to foo.com, and the revokable permissions should be empty.
-    updater.RemovePermissions(extension.get(),
-                              url_permission_set(kOrigin).get(),
+    updater.RemovePermissions(extension.get(), *url_permission_set(kOrigin),
                               PermissionsUpdater::REMOVE_HARD);
     EXPECT_FALSE(extension->permissions_data()
                      ->active_permissions()
-                     ->HasExplicitAccessToOrigin(kOrigin));
+                     .HasExplicitAccessToOrigin(kOrigin));
     EXPECT_TRUE(extension->permissions_data()
                     ->withheld_permissions()
-                    ->HasExplicitAccessToOrigin(kOrigin));
+                    .HasExplicitAccessToOrigin(kOrigin));
     EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
   }
 }
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index c8a8e00..980318c 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -157,4 +157,40 @@
   EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id()));
 }
 
+// Verify correct keepalive count behavior on network request events.
+// Regression test for http://crbug.com/535716.
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) {
+  // Load an extension with a lazy background page.
+  scoped_refptr<const Extension> extension =
+      LoadExtension(test_data_dir_.AppendASCII("api_test")
+                        .AppendASCII("lazy_background_page")
+                        .AppendASCII("broadcast_event"));
+  ASSERT_TRUE(extension.get());
+
+  ProcessManager* pm = ProcessManager::Get(profile());
+  ProcessManager::FrameSet frames =
+      pm->GetRenderFrameHostsForExtension(extension->id());
+  ASSERT_EQ(1u, frames.size());
+
+  // Keepalive count at this point is unpredictable as there may be an
+  // outstanding event dispatch. We use the current keepalive count as a
+  // reliable baseline for future expectations.
+  int baseline_keepalive = pm->GetLazyKeepaliveCount(extension.get());
+
+  // Simulate some network events. This test assumes no other network requests
+  // are pending, i.e., that there are no conflicts with the fake request IDs
+  // we're using. This should be a safe assumption because LoadExtension should
+  // wait for loads to complete, and we don't run the message loop otherwise.
+  content::RenderFrameHost* frame_host = *frames.begin();
+  pm->OnNetworkRequestStarted(frame_host, 1);
+  EXPECT_EQ(baseline_keepalive + 1, pm->GetLazyKeepaliveCount(extension.get()));
+  pm->OnNetworkRequestDone(frame_host, 1);
+  EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get()));
+
+  // Simulate only a request completion for this ID and ensure it doesn't result
+  // in keepalive decrement.
+  pm->OnNetworkRequestDone(frame_host, 2);
+  EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get()));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/updater/extension_updater.cc b/chrome/browser/extensions/updater/extension_updater.cc
index 9343753..ac81a70 100644
--- a/chrome/browser/extensions/updater/extension_updater.cc
+++ b/chrome/browser/extensions/updater/extension_updater.cc
@@ -495,8 +495,7 @@
     for (std::list<std::string>::const_iterator it = params.ids.begin();
          it != params.ids.end(); ++it) {
       const Extension* extension = service_->GetExtensionById(*it, true);
-      DCHECK(extension);
-      if (downloader_->AddExtension(*extension, request_id))
+      if (extension && downloader_->AddExtension(*extension, request_id))
         request.in_progress_ids_.push_back(extension->id());
     }
   }
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 837e7a9e..32185a71 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -2235,6 +2235,34 @@
   TestPingMetrics(0, disabled);
 }
 
+TEST_F(ExtensionUpdaterTest, TestUninstallWhileUpdateCheck) {
+  ServiceForManifestTests service(prefs_.get());
+  ExtensionList tmp;
+  service.CreateTestExtensions(1, 1, &tmp, nullptr, Manifest::INTERNAL);
+  service.set_extensions(tmp, ExtensionList());
+
+  ASSERT_EQ(1u, tmp.size());
+  ExtensionId id = tmp.front()->id();
+  ASSERT_TRUE(service.GetExtensionById(id, false));
+
+  ExtensionUpdater updater(&service,
+                           service.extension_prefs(),
+                           service.pref_service(),
+                           service.profile(),
+                           kUpdateFrequencySecs,
+                           NULL,
+                           service.GetDownloaderFactory());
+  ExtensionUpdater::CheckParams params;
+  params.ids.push_back(id);
+  updater.Start();
+  updater.CheckNow(params);
+
+  service.set_extensions(ExtensionList(), ExtensionList());
+  ASSERT_FALSE(service.GetExtensionById(id, false));
+
+  content::RunAllBlockingPoolTasksUntilIdle();
+}
+
 // TODO(asargent) - (http://crbug.com/12780) add tests for:
 // -prodversionmin (shouldn't update if browser version too old)
 // -manifests & updates arriving out of order / interleaved
diff --git a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
index c3f74e9..9014479 100644
--- a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
+++ b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
@@ -145,8 +145,9 @@
   ProgrammableInstallPrompt::Accept();
 }
 
+// Flaky: https://crbug.com/537526.
 IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerTest,
-                       ShouldBlockInlineInstallFromPopupWindow) {
+                       DISABLED_ShouldBlockInlineInstallFromPopupWindow) {
   GURL install_url =
       GenerateTestServerUrl(kAppDomain, "install_from_popup.html");
   // Disable popup blocking for the test url.
diff --git a/chrome/browser/first_run/first_run_internal_posix.cc b/chrome/browser/first_run/first_run_internal_posix.cc
index 683b9371..6e97dd8 100644
--- a/chrome/browser/first_run/first_run_internal_posix.cc
+++ b/chrome/browser/first_run/first_run_internal_posix.cc
@@ -38,7 +38,7 @@
   // this is POSIX-specific).
   if (GoogleUpdateSettings::GetCollectStatsConsent()) {
     g_browser_process->local_state()->SetBoolean(
-        prefs::kMetricsReportingEnabled, true);
+        metrics::prefs::kMetricsReportingEnabled, true);
   }
 #endif
 }
diff --git a/chrome/browser/interstitials/chrome_metrics_helper.cc b/chrome/browser/interstitials/chrome_metrics_helper.cc
index c886e44..711ecf1 100644
--- a/chrome/browser/interstitials/chrome_metrics_helper.cc
+++ b/chrome/browser/interstitials/chrome_metrics_helper.cc
@@ -15,6 +15,10 @@
 #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h"
 #endif
 
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+#include "chrome/browser/ssl/captive_portal_metrics_recorder.h"
+#endif
+
 ChromeMetricsHelper::ChromeMetricsHelper(
     content::WebContents* web_contents,
     const GURL& request_url,
@@ -35,6 +39,22 @@
 
 ChromeMetricsHelper::~ChromeMetricsHelper() {}
 
+void ChromeMetricsHelper::StartRecordingCaptivePortalMetrics(bool overridable) {
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  captive_portal_recorder_.reset(
+      new CaptivePortalMetricsRecorder(web_contents_, overridable));
+#endif
+}
+
+void ChromeMetricsHelper::RecordExtraShutdownMetrics() {
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  // The captive portal metrics should be recorded when the interstitial is
+  // closing (or destructing).
+  if (captive_portal_recorder_)
+    captive_portal_recorder_->RecordCaptivePortalUMAStatistics();
+#endif
+}
+
 void ChromeMetricsHelper::RecordExtraUserDecisionMetrics(
     security_interstitials::MetricsHelper::Decision decision) {
 #if defined(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/interstitials/chrome_metrics_helper.h b/chrome/browser/interstitials/chrome_metrics_helper.h
index e56e59a..0c82e84 100644
--- a/chrome/browser/interstitials/chrome_metrics_helper.h
+++ b/chrome/browser/interstitials/chrome_metrics_helper.h
@@ -18,9 +18,13 @@
 class ExperienceSamplingEvent;
 }
 
+class CaptivePortalMetricsRecorder;
+
 // This class adds desktop-Chrome-specific metrics (extension experience
 // sampling) to the security_interstitials::MetricsHelper. Together, they
 // record UMA, Rappor, and experience sampling metrics.
+
+// This class is meant to be used on the UI thread for captive portal metrics.
 class ChromeMetricsHelper : public security_interstitials::MetricsHelper {
  public:
   ChromeMetricsHelper(
@@ -30,12 +34,15 @@
       const std::string& sampling_event_name);
   ~ChromeMetricsHelper() override;
 
+  void StartRecordingCaptivePortalMetrics(bool overridable);
+
  protected:
   // security_interstitials::MetricsHelper methods:
   void RecordExtraUserDecisionMetrics(
       security_interstitials::MetricsHelper::Decision decision) override;
   void RecordExtraUserInteractionMetrics(
       security_interstitials::MetricsHelper::Interaction interaction) override;
+  void RecordExtraShutdownMetrics() override;
 
  private:
   content::WebContents* web_contents_;
@@ -44,6 +51,9 @@
 #if defined(ENABLE_EXTENSIONS)
   scoped_ptr<extensions::ExperienceSamplingEvent> sampling_event_;
 #endif
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  scoped_ptr<CaptivePortalMetricsRecorder> captive_portal_recorder_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(ChromeMetricsHelper);
 };
diff --git a/chrome/browser/interstitials/security_interstitial_page.cc b/chrome/browser/interstitials/security_interstitial_page.cc
index 876f55b8..0cc658e 100644
--- a/chrome/browser/interstitials/security_interstitial_page.cc
+++ b/chrome/browser/interstitials/security_interstitial_page.cc
@@ -115,8 +115,8 @@
 }
 
 void SecurityInterstitialPage::set_metrics_helper(
-    security_interstitials::MetricsHelper* metrics_helper) {
-  metrics_helper_.reset(metrics_helper);
+    scoped_ptr<security_interstitials::MetricsHelper> metrics_helper) {
+  metrics_helper_ = metrics_helper.Pass();
 }
 
 base::string16 SecurityInterstitialPage::GetFormattedHostName() const {
diff --git a/chrome/browser/interstitials/security_interstitial_page.h b/chrome/browser/interstitials/security_interstitial_page.h
index 0bd632b..13c547df 100644
--- a/chrome/browser/interstitials/security_interstitial_page.h
+++ b/chrome/browser/interstitials/security_interstitial_page.h
@@ -99,7 +99,7 @@
 
   security_interstitials::MetricsHelper* metrics_helper() const;
   void set_metrics_helper(
-      security_interstitials::MetricsHelper* metrics_helper);
+      scoped_ptr<security_interstitials::MetricsHelper> metrics_helper);
 
  private:
   scoped_ptr<security_interstitials::MetricsHelper> metrics_helper_;
diff --git a/chrome/browser/jumplist_win.cc b/chrome/browser/jumplist_win.cc
index 9ea1f98..91e536f 100644
--- a/chrome/browser/jumplist_win.cc
+++ b/chrome/browser/jumplist_win.cc
@@ -82,7 +82,8 @@
   // save it as the temporary file.
   gfx::ImageFamily image_family;
   image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap));
-  if (!IconUtil::CreateIconFileFromImageFamily(image_family, path))
+  if (!IconUtil::CreateIconFileFromImageFamily(image_family, path,
+                                               IconUtil::NORMAL_WRITE))
     return false;
 
   // Add this icon file to the list and return its absolute path.
diff --git a/chrome/browser/local_discovery/privet_notifications.cc b/chrome/browser/local_discovery/privet_notifications.cc
index 3e1e5c8..9c529a9 100644
--- a/chrome/browser/local_discovery/privet_notifications.cc
+++ b/chrome/browser/local_discovery/privet_notifications.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc
index a89f961c..758d6251f 100644
--- a/chrome/browser/media/android/router/media_router_android.cc
+++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -185,7 +185,7 @@
 
 void MediaRouterAndroid::OnPresentationSessionDetached(
     const MediaRoute::Id& route_id) {
-  NOTIMPLEMENTED();
+  CloseRoute(route_id);
 }
 
 void MediaRouterAndroid::RegisterMediaSinksObserver(
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
index e3bb54d..e0e05336 100644
--- a/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
+++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.cc
@@ -54,23 +54,41 @@
                       route_response_callbacks);
 }
 
-void MediaRouterDialogControllerAndroid::OnDialogDismissed(
+void MediaRouterDialogControllerAndroid::OnRouteClosed(
+    JNIEnv* env,
+    jobject obj,
+    jstring jmedia_route_id) {
+  std::string media_route_id = ConvertJavaStringToUTF8(env, jmedia_route_id);
+
+  MediaRouter* router = MediaRouterFactory::GetApiForBrowserContext(
+      initiator()->GetBrowserContext());
+
+  router->CloseRoute(media_route_id);
+
+  CancelPresentationRequest();
+}
+
+void MediaRouterDialogControllerAndroid::OnDialogCancelled(
     JNIEnv* env, jobject obj) {
+  CancelPresentationRequest();
+}
+
+void MediaRouterDialogControllerAndroid::CancelPresentationRequest() {
   scoped_ptr<CreatePresentationSessionRequest> request(
       TakePresentationRequest());
 
-  // If OnDialogDismissed is called after OnSinkSelected, do nothing.
-  if (!request)
-    return;
+  DCHECK(request);
 
   request->InvokeErrorCallback(content::PresentationError(
       content::PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED,
-      "The device picker dialog has been dismissed"));
+      "Dialog closed."));
 }
 
 MediaRouterDialogControllerAndroid::MediaRouterDialogControllerAndroid(
     WebContents* web_contents)
-    : MediaRouterDialogController(web_contents) {
+    : MediaRouterDialogController(web_contents),
+      MediaRoutesObserver(MediaRouterFactory::GetApiForBrowserContext(
+          initiator()->GetBrowserContext())) {
   JNIEnv* env = base::android::AttachCurrentThread();
   java_dialog_controller_.Reset(Java_ChromeMediaRouterDialogController_create(
       env,
@@ -89,11 +107,29 @@
 void MediaRouterDialogControllerAndroid::CreateMediaRouterDialog() {
   JNIEnv* env = base::android::AttachCurrentThread();
 
+  const MediaSource::Id& media_source_id =
+      presentation_request()->media_source().id();
   ScopedJavaLocalRef<jstring> jsource_urn =
-      base::android::ConvertUTF8ToJavaString(
-          env, presentation_request()->media_source().id());
+      base::android::ConvertUTF8ToJavaString(env, media_source_id);
 
-  Java_ChromeMediaRouterDialogController_createDialog(
+  // If it's a single route with the same source, show the controller dialog
+  // instead of the device picker.
+  // TODO(avayvod): maybe this logic should be in
+  // PresentationServiceDelegateImpl: if the route exists for the same frame
+  // and tab, show the route controller dialog, if not, show the device picker.
+  if (single_existing_route_.get() &&
+      single_existing_route_->media_source().id() == media_source_id) {
+    ScopedJavaLocalRef<jstring> jmedia_route_id =
+        base::android::ConvertUTF8ToJavaString(
+            env, single_existing_route_->media_route_id());
+
+    Java_ChromeMediaRouterDialogController_openRouteControllerDialog(
+        env, java_dialog_controller_.obj(), jsource_urn.obj(),
+        jmedia_route_id.obj());
+    return;
+  }
+
+  Java_ChromeMediaRouterDialogController_openRouteChooserDialog(
       env, java_dialog_controller_.obj(), jsource_urn.obj());
 }
 
@@ -110,5 +146,20 @@
       env, java_dialog_controller_.obj());
 }
 
+void MediaRouterDialogControllerAndroid::OnRoutesUpdated(
+    const std::vector<MediaRoute>& routes) {
+  if (routes.size() != 1) {
+    single_existing_route_.reset();
+    return;
+  }
+
+  if (single_existing_route_.get() &&
+      single_existing_route_->media_route_id() == routes[0].media_route_id()) {
+    return;
+  }
+
+  single_existing_route_.reset(new MediaRoute(routes[0]));
+}
+
 }  // namespace media_router
 
diff --git a/chrome/browser/media/android/router/media_router_dialog_controller_android.h b/chrome/browser/media/android/router/media_router_dialog_controller_android.h
index bbe4a3f..cbd5928 100644
--- a/chrome/browser/media/android/router/media_router_dialog_controller_android.h
+++ b/chrome/browser/media/android/router/media_router_dialog_controller_android.h
@@ -9,7 +9,9 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
+#include "chrome/browser/media/router/media_routes_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
 namespace media_router {
@@ -17,7 +19,8 @@
 // Android implementation of the MediaRouterDialogController.
 class MediaRouterDialogControllerAndroid
     : public content::WebContentsUserData<MediaRouterDialogControllerAndroid>,
-      public MediaRouterDialogController {
+      public MediaRouterDialogController,
+      public MediaRoutesObserver {
  public:
   ~MediaRouterDialogControllerAndroid() override;
 
@@ -30,9 +33,11 @@
 
   // Notifies the controller that user has selected a sink with |jsink_id|.
   void OnSinkSelected(JNIEnv* env, jobject obj, jstring jsink_id);
-  // Notifies the controller that the dialog has been dismissed and no device
-  // has been picked.
-  void OnDialogDismissed(JNIEnv* env, jobject obj);
+  // Notifies the controller that user chose to close the route.
+  void OnRouteClosed(JNIEnv* env, jobject obj, jstring jmedia_route_id);
+  // Notifies the controller that the dialog has been closed without the user
+  // taking any action (e.g. closing the route or selecting a sink).
+  void OnDialogCancelled(JNIEnv* env, jobject obj);
 
  private:
   friend class content::WebContentsUserData<MediaRouterDialogControllerAndroid>;
@@ -47,8 +52,18 @@
   void CloseMediaRouterDialog() override;
   bool IsShowingMediaRouterDialog() const override;
 
+  // MediaRoutesObserver:
+  void OnRoutesUpdated(const std::vector<MediaRoute>& routes) override;
+
+  void CancelPresentationRequest();
+
   base::android::ScopedJavaGlobalRef<jobject> java_dialog_controller_;
 
+  // Null if no routes or more than one route exist. If there's only one route,
+  // keeps a copy to determine if the route controller dialog needs to be shown
+  // vs. the route chooser one.
+  scoped_ptr<MediaRoute> single_existing_route_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerAndroid);
 };
 
diff --git a/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc b/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc
index b2645cbc..102801c 100644
--- a/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc
+++ b/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc
@@ -240,9 +240,7 @@
   if (OnWinXp())
     return;
 
-  // Temporarily disabled due to http://crbug.com/535588, while AppRTC
-  // gets updated.
-  // DetectErrorsInJavaScript();
+  DetectErrorsInJavaScript();
   ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost("9999"));
   ASSERT_TRUE(LaunchColliderOnLocalHost("http://localhost:9999", "8089"));
   while (!LocalApprtcInstanceIsUp())
@@ -294,9 +292,7 @@
   if (OnWinXp())
     return;
 
-  // Temporarily disabled due to http://crbug.com/535588, while AppRTC
-  // gets updated.
-  // DetectErrorsInJavaScript();
+  DetectErrorsInJavaScript();
   ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost("9999"));
   ASSERT_TRUE(LaunchColliderOnLocalHost("http://localhost:9999", "8089"));
   while (!LocalApprtcInstanceIsUp())
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
index ef876ba..75f43559 100644
--- a/chrome/browser/media/media_stream_devices_controller.cc
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/media/media_stream_devices_controller.h"
 
+#include "base/auto_reset.h"
+#include "base/callback_helpers.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/scoped_user_pref_update.h"
 #include "base/strings/utf_string_conversions.h"
@@ -31,7 +33,10 @@
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_ANDROID)
+#include <vector>
+
 #include "chrome/browser/android/preferences/pref_service_bridge.h"
+#include "chrome/browser/permissions/permission_update_infobar_delegate_android.h"
 #include "content/public/browser/android/content_view_core.h"
 #include "ui/android/window_android.h"
 #endif  // OS_ANDROID
@@ -72,7 +77,8 @@
     const content::MediaResponseCallback& callback)
     : web_contents_(web_contents),
       request_(request),
-      callback_(callback) {
+      callback_(callback),
+      persist_permission_changes_(true) {
   if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
     UMA_HISTOGRAM_BOOLEAN("Pepper.SecureOrigin.MediaStreamRequest",
                           content::IsOriginSecure(request_.security_origin));
@@ -92,6 +98,26 @@
     return;
   }
 
+#if defined(OS_ANDROID)
+  std::vector<ContentSettingsType> content_settings_types;
+  if (IsAllowedForAudio())
+    content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
+
+  if (IsAllowedForVideo()) {
+    content_settings_types.push_back(
+        CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
+  }
+
+  // If the site had been previously granted the access to audio or video but
+  // Chrome is now missing the necessary permission, we need to show an infobar
+  // to resolve the difference.
+  if (!content_settings_types.empty() &&
+      PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
+          web_contents, content_settings_types)) {
+    return;
+  }
+#endif
+
   // Otherwise we can run the callback immediately.
   RunCallback(old_audio_setting_, old_video_setting_, denial_reason);
 }
@@ -113,6 +139,14 @@
   prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls);
 }
 
+bool MediaStreamDevicesController::IsAllowedForAudio() const {
+  return old_audio_setting_ == CONTENT_SETTING_ALLOW;
+}
+
+bool MediaStreamDevicesController::IsAllowedForVideo() const {
+  return old_video_setting_ == CONTENT_SETTING_ALLOW;
+}
+
 bool MediaStreamDevicesController::IsAskingForAudio() const {
   return old_audio_setting_ == CONTENT_SETTING_ASK;
 }
@@ -125,6 +159,16 @@
   return request_.security_origin.spec();
 }
 
+void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() {
+  base::AutoReset<bool> persist_permissions(
+      &persist_permission_changes_, false);
+  UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions",
+                            kDeny, kPermissionActionsMax);
+  RunCallback(CONTENT_SETTING_BLOCK,
+              CONTENT_SETTING_BLOCK,
+              content::MEDIA_DEVICE_PERMISSION_DENIED);
+}
+
 int MediaStreamDevicesController::GetIconId() const {
   if (IsAskingForVideo())
     return IDR_INFOBAR_MEDIA_STREAM_CAMERA;
@@ -309,8 +353,12 @@
     ContentSetting audio_setting,
     ContentSetting video_setting,
     content::MediaStreamRequestResult denial_reason) {
-  StorePermission(audio_setting, video_setting);
-  UpdateTabSpecificContentSettings(audio_setting, video_setting);
+  CHECK(!callback_.is_null());
+
+  if (persist_permission_changes_) {
+    StorePermission(audio_setting, video_setting);
+    UpdateTabSpecificContentSettings(audio_setting, video_setting);
+  }
 
   content::MediaStreamDevices devices =
       GetDevices(audio_setting, video_setting);
@@ -334,9 +382,7 @@
              ->GetMediaStreamCaptureIndicator()
              ->RegisterMediaStream(web_contents_, devices);
   }
-  content::MediaResponseCallback cb = callback_;
-  callback_.Reset();
-  cb.Run(devices, request_result, ui.Pass());
+  base::ResetAndReturn(&callback_).Run(devices, request_result, ui.Pass());
 }
 
 void MediaStreamDevicesController::StorePermission(
diff --git a/chrome/browser/media/media_stream_devices_controller.h b/chrome/browser/media/media_stream_devices_controller.h
index fd53d30..21695ab4 100644
--- a/chrome/browser/media/media_stream_devices_controller.h
+++ b/chrome/browser/media/media_stream_devices_controller.h
@@ -34,11 +34,21 @@
   // Registers the prefs backing the audio and video policies.
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  // Public methods to be called by MediaStreamInfoBarDelegate;
+  bool IsAllowedForAudio() const;
+  bool IsAllowedForVideo() const;
   bool IsAskingForAudio() const;
   bool IsAskingForVideo() const;
   const std::string& GetSecurityOriginSpec() const;
 
+  // Forces the permissions to be denied (without being persisted) regardless
+  // of what the previous state was.  If the user had previously allowed the
+  // site video or audio access, this ignores that and informs the site it was
+  // denied.
+  //
+  // This differs from PermissionGranted/PermissionDenied as they only operate
+  // on the permissions if they are in the ASK state.
+  void ForcePermissionDeniedTemporarily();
+
   // PermissionBubbleRequest:
   int GetIconId() const override;
   base::string16 GetMessageText() const override;
@@ -114,6 +124,8 @@
   // audio/video devices was granted or not.
   content::MediaResponseCallback callback_;
 
+  // Whether the permissions granted or denied by the user should be persisted.
+  bool persist_permission_changes_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaStreamDevicesController);
 };
diff --git a/chrome/browser/media/media_stream_infobar_delegate.cc b/chrome/browser/media/media_stream_infobar_delegate.cc
index 5f0e875c2..76f6c53 100644
--- a/chrome/browser/media/media_stream_infobar_delegate.cc
+++ b/chrome/browser/media/media_stream_infobar_delegate.cc
@@ -37,12 +37,7 @@
 // static
 bool MediaStreamInfoBarDelegate::Create(
     content::WebContents* web_contents,
-    const content::MediaStreamRequest& request,
-    const content::MediaResponseCallback& callback) {
-  scoped_ptr<MediaStreamDevicesController> controller(
-      new MediaStreamDevicesController(web_contents, request, callback));
-  if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo())
-    return false;
+    scoped_ptr<MediaStreamDevicesController> controller) {
 
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(web_contents);
diff --git a/chrome/browser/media/media_stream_infobar_delegate.h b/chrome/browser/media/media_stream_infobar_delegate.h
index 9bf55d7f..0d63d0e 100644
--- a/chrome/browser/media/media_stream_infobar_delegate.h
+++ b/chrome/browser/media/media_stream_infobar_delegate.h
@@ -21,14 +21,12 @@
  public:
   ~MediaStreamInfoBarDelegate() override;
 
-  // Handles a permission request (in |request|) for |web_contents|.  If this
-  // involves prompting the user, creates a media stream infobar and delegate,
+  // Prompts the user by creating a media stream infobar and delegate,
   // then checks for an existing infobar for |web_contents| and replaces it if
   // found, or just adds the new infobar otherwise.  Returns whether an infobar
   // was created.
   static bool Create(content::WebContents* web_contents,
-                     const content::MediaStreamRequest& request,
-                     const content::MediaResponseCallback& callback);
+                     scoped_ptr<MediaStreamDevicesController> controller);
 
   bool IsRequestingVideoAccess() const;
   bool IsRequestingMicrophoneAccess() const;
diff --git a/chrome/browser/media/permission_bubble_media_access_handler.cc b/chrome/browser/media/permission_bubble_media_access_handler.cc
index b32c59b..ca24c45 100644
--- a/chrome/browser/media/permission_bubble_media_access_handler.cc
+++ b/chrome/browser/media/permission_bubble_media_access_handler.cc
@@ -17,6 +17,27 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 
+#if defined(OS_ANDROID)
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/permissions/permission_update_infobar_delegate_android.h"
+
+namespace {
+// Callback for the permission update infobar when the site and Chrome
+// permissions are mismatched on Android.
+void OnPermissionConflictResolved(
+    scoped_ptr<MediaStreamDevicesController> controller, bool allowed) {
+  if (allowed)
+    controller->PermissionGranted();
+  else
+    controller->ForcePermissionDeniedTemporarily();
+}
+}  // namespace
+
+#endif  // OS_ANDROID
+
 using content::BrowserThread;
 
 struct PermissionBubbleMediaAccessHandler::PendingAccessRequest {
@@ -102,28 +123,47 @@
 
   DCHECK(!it->second.empty());
 
+  scoped_ptr<MediaStreamDevicesController> controller(
+      new MediaStreamDevicesController(
+          web_contents, it->second.front().request,
+          base::Bind(
+              &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
+              base::Unretained(this), web_contents)));
+  if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) {
+#if defined(OS_ANDROID)
+    // If either audio or video was previously allowed and Chrome no longer has
+    // the necessary permissions, show a infobar to attempt to address this
+    // mismatch.
+    std::vector<ContentSettingsType> content_settings_types;
+    if (controller->IsAllowedForAudio())
+      content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
+
+    if (controller->IsAllowedForVideo()) {
+      content_settings_types.push_back(
+          CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
+    }
+    if (!content_settings_types.empty() &&
+        PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
+            web_contents, content_settings_types)) {
+      PermissionUpdateInfoBarDelegate::Create(
+          web_contents, content_settings_types,
+          base::Bind(
+              &OnPermissionConflictResolved, base::Passed(&controller)));
+    }
+#endif
+    return;
+  }
+
   if (PermissionBubbleManager::Enabled()) {
-    scoped_ptr<MediaStreamDevicesController> controller(
-        new MediaStreamDevicesController(
-            web_contents, it->second.front().request,
-            base::Bind(
-                &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
-                base::Unretained(this), web_contents)));
-    if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo())
-      return;
     PermissionBubbleManager* bubble_manager =
         PermissionBubbleManager::FromWebContents(web_contents);
     if (bubble_manager)
       bubble_manager->AddRequest(controller.release());
-    return;
+  } else {
+    // TODO(gbillock): delete this block and the MediaStreamInfoBarDelegate
+    // when we've transitioned to bubbles. (https://crbug/337458)
+    MediaStreamInfoBarDelegate::Create(web_contents, controller.Pass());
   }
-
-  // TODO(gbillock): delete this block and the MediaStreamInfoBarDelegate
-  // when we've transitioned to bubbles. (crbug/337458)
-  MediaStreamInfoBarDelegate::Create(
-      web_contents, it->second.front().request,
-      base::Bind(&PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
-                 base::Unretained(this), web_contents));
 }
 
 void PermissionBubbleMediaAccessHandler::UpdateMediaRequestState(
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc
index 63000f6..df1f1cc 100644
--- a/chrome/browser/memory/tab_manager.cc
+++ b/chrome/browser/memory/tab_manager.cc
@@ -40,6 +40,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/page_importance_signals.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/memory/tab_manager_delegate_chromeos.h"
@@ -358,6 +359,8 @@
         stats.is_pinned = model->IsTabPinned(i);
         stats.is_selected = browser_active && model->IsTabSelected(i);
         stats.is_discarded = TabDiscardState::IsDiscarded(contents);
+        stats.has_form_entry =
+            contents->GetPageImportanceSignals().had_form_interaction;
         stats.discard_count = TabDiscardState::DiscardCount(contents);
         stats.last_active = contents->GetLastActiveTime();
         stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
@@ -415,13 +418,18 @@
     return false;
 
   WebContents* web_contents = model->GetWebContentsAt(idx);
-  // We do not discard tabs that are playing audio as it's too distruptive to
-  // the user experience.
+
+  // Do not discard tabs in which the user has entered text in a form, lest we
+  // lose that state.
+  if (web_contents->GetPageImportanceSignals().had_form_interaction)
+    return false;
+
+  // Do not discard tabs that are playing audio as it's too distruptive to the
+  // user experience.
   if (web_contents->WasRecentlyAudible())
     return false;
 
-  // We also make sure not to discard a previously discarded tab if that's the
-  // desired behavior.
+  // Do not discard a previously discarded tab if that's the desired behavior.
   if (discard_once_ && TabDiscardState::DiscardCount(web_contents) > 0)
     return false;
 
@@ -449,6 +457,10 @@
   if (first.is_selected != second.is_selected)
     return first.is_selected;
 
+  // Protect tabs with pending form entries.
+  if (first.has_form_entry != second.has_form_entry)
+    return first.has_form_entry;
+
   // Protect streaming audio and video conferencing tabs as these are similar to
   // active tabs.
   if (first.is_playing_audio != second.is_playing_audio)
diff --git a/chrome/browser/memory/tab_manager_unittest.cc b/chrome/browser/memory/tab_manager_unittest.cc
index 721dd54..c123470 100644
--- a/chrome/browser/memory/tab_manager_unittest.cc
+++ b/chrome/browser/memory/tab_manager_unittest.cc
@@ -25,6 +25,7 @@
   kPinned,
   kApp,
   kPlayingAudio,
+  kFormEntry,
   kRecent,
   kOld,
   kReallyOld,
@@ -67,6 +68,14 @@
 
   {
     TabStats stats;
+    stats.last_active = now;
+    stats.has_form_entry = true;
+    stats.child_process_host_id = kFormEntry;
+    test_list.push_back(stats);
+  }
+
+  {
+    TabStats stats;
     stats.last_active = now - base::TimeDelta::FromSeconds(10);
     stats.child_process_host_id = kRecent;
     test_list.push_back(stats);
@@ -116,6 +125,7 @@
 
   int index = 0;
   EXPECT_EQ(kSelected, test_list[index++].child_process_host_id);
+  EXPECT_EQ(kFormEntry, test_list[index++].child_process_host_id);
   EXPECT_EQ(kPlayingAudio, test_list[index++].child_process_host_id);
   EXPECT_EQ(kPinned, test_list[index++].child_process_host_id);
   EXPECT_EQ(kOldButPinned, test_list[index++].child_process_host_id);
diff --git a/chrome/browser/memory/tab_stats.cc b/chrome/browser/memory/tab_stats.cc
index 3bf12db..94f2f29 100644
--- a/chrome/browser/memory/tab_stats.cc
+++ b/chrome/browser/memory/tab_stats.cc
@@ -13,6 +13,7 @@
       is_pinned(false),
       is_selected(false),
       is_discarded(false),
+      has_form_entry(false),
       discard_count(0),
       renderer_handle(0),
       child_process_host_id(0),
diff --git a/chrome/browser/memory/tab_stats.h b/chrome/browser/memory/tab_stats.h
index dcc979d7..8f40c51 100644
--- a/chrome/browser/memory/tab_stats.h
+++ b/chrome/browser/memory/tab_stats.h
@@ -22,6 +22,7 @@
   bool is_pinned;
   bool is_selected;  // Selected in the currently active browser window.
   bool is_discarded;
+  bool has_form_entry;  // User has entered text in a form.
   int discard_count;
   base::TimeTicks last_active;
   base::ProcessHandle renderer_handle;
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.cc b/chrome/browser/metrics/chrome_metrics_service_accessor.cc
index 50ee2fa..c2fe6ce 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.cc
@@ -11,7 +11,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/metrics/metrics_service.h"
-#include "components/variations/metrics_util.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -42,7 +41,7 @@
       prefs::kCrashReportingEnabled);
 #else
   enabled = g_browser_process->local_state()->
-      GetBoolean(prefs::kMetricsReportingEnabled);
+      GetBoolean(metrics::prefs::kMetricsReportingEnabled);
 #endif  // #if defined(OS_CHROMEOS)
 #endif  // defined(GOOGLE_CHROME_BUILD)
   return enabled;
@@ -52,16 +51,15 @@
 bool ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
     const std::string& trial_name,
     const std::string& group_name) {
-  return RegisterSyntheticFieldTrialWithNameHash(metrics::HashName(trial_name),
-                                                 group_name);
+  return metrics::MetricsServiceAccessor::RegisterSyntheticFieldTrial(
+      g_browser_process->metrics_service(), trial_name, group_name);
 }
 
 // static
 bool ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameHash(
     uint32_t trial_name_hash,
     const std::string& group_name) {
-  return metrics::MetricsServiceAccessor::RegisterSyntheticFieldTrial(
-      g_browser_process->metrics_service(),
-      trial_name_hash,
-      metrics::HashName(group_name));
+  return metrics::MetricsServiceAccessor::
+      RegisterSyntheticFieldTrialWithNameHash(
+          g_browser_process->metrics_service(), trial_name_hash, group_name);
 }
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h
index 9c34966..018a297 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.h
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -94,18 +94,16 @@
   // http://crbug.com/362192,  http://crbug.com/532084
   static bool IsMetricsAndCrashReportingEnabled();
 
-  // Registers a field trial name and group to be used to annotate a UMA report
-  // with a particular Chrome configuration state. A UMA report will be
-  // annotated with this trial group if and only if all events in the report
-  // were created after the trial is registered. Only one group name may be
-  // registered at a time for a given trial name. Only the last group name that
-  // is registered for a given trial name will be recorded. The values passed
-  // in must not correspond to any real field trial in the code.
+  // Calls metrics::MetricsServiceAccessor::RegisterSyntheticFieldTrial() with
+  // g_browser_process->metrics_service(). See that function's declaration for
+  // details.
   static bool RegisterSyntheticFieldTrial(const std::string& trial_name,
                                           const std::string& group_name);
 
-  // Same as RegisterSyntheticFieldTrial above, but takes a hash for the trial
-  // name, rather than computing it from the string.
+  // Calls
+  // metrics::MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameHash()
+  // with g_browser_process->metrics_service(). See that function's declaration
+  // for details.
   static bool RegisterSyntheticFieldTrialWithNameHash(
       uint32_t trial_name_hash,
       const std::string& group_name);
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc
index dc70144..237539bb 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc
@@ -31,7 +31,7 @@
 #if defined(OS_ANDROID)
   const char* pref = prefs::kCrashReportingEnabled;
 #else
-  const char* pref = prefs::kMetricsReportingEnabled;
+  const char* pref = metrics::prefs::kMetricsReportingEnabled;
 #endif  // defined(OS_ANDROID)
   GetLocalState()->SetDefaultPrefValue(pref, new base::FundamentalValue(false));
 
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index e9858a6c..a8cf6efe 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -113,7 +113,7 @@
 bool ShouldClearSavedMetrics() {
 #if defined(OS_ANDROID)
   PrefService* local_state = g_browser_process->local_state();
-  return !local_state->HasPrefPath(prefs::kMetricsReportingEnabled) &&
+  return !local_state->HasPrefPath(metrics::prefs::kMetricsReportingEnabled) &&
          variations::GetVariationParamValue("UMA_EnableCellularLogUpload",
                                             "Enabled") == "true";
 #else
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
index f47b5d9..1eeb373a 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -11,41 +11,44 @@
 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/login/login_state.h"
 #include "components/metrics/proto/system_profile.pb.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(USE_X11)
 #include "ui/events/devices/x11/device_data_manager_x11.h"
 #endif
 
+using bluez::BluetoothAdapterClient;
+using bluez::BluetoothAgentManagerClient;
+using bluez::BluetoothDeviceClient;
+using bluez::BluetoothGattCharacteristicClient;
+using bluez::BluetoothGattDescriptorClient;
+using bluez::BluetoothGattServiceClient;
+using bluez::BluetoothInputClient;
+using bluez::BluezDBusManager;
+using bluez::BluezDBusManagerSetter;
+using bluez::FakeBluetoothAdapterClient;
+using bluez::FakeBluetoothAgentManagerClient;
+using bluez::FakeBluetoothDeviceClient;
+using bluez::FakeBluetoothGattCharacteristicClient;
+using bluez::FakeBluetoothGattDescriptorClient;
+using bluez::FakeBluetoothGattServiceClient;
+using bluez::FakeBluetoothInputClient;
 using chromeos::DBusThreadManager;
 using chromeos::DBusThreadManagerSetter;
-using chromeos::BluetoothAdapterClient;
-using chromeos::BluetoothAgentManagerClient;
-using chromeos::BluetoothDeviceClient;
-using chromeos::BluetoothGattCharacteristicClient;
-using chromeos::BluetoothGattDescriptorClient;
-using chromeos::BluetoothGattServiceClient;
-using chromeos::BluetoothInputClient;
-using chromeos::FakeBluetoothAdapterClient;
-using chromeos::FakeBluetoothAgentManagerClient;
-using chromeos::FakeBluetoothDeviceClient;
-using chromeos::FakeBluetoothGattCharacteristicClient;
-using chromeos::FakeBluetoothGattDescriptorClient;
-using chromeos::FakeBluetoothGattServiceClient;
-using chromeos::FakeBluetoothInputClient;
 using chromeos::PowerManagerClient;
 using chromeos::STUB_DBUS_CLIENT_IMPLEMENTATION;
 
@@ -60,37 +63,39 @@
 #endif
 
     // Set up the fake Bluetooth environment,
-    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
-        DBusThreadManager::GetSetterForTesting();
-    dbus_setter->SetBluetoothAdapterClient(
+    scoped_ptr<BluezDBusManagerSetter> bluez_dbus_setter =
+        BluezDBusManager::GetSetterForTesting();
+    bluez_dbus_setter->SetBluetoothAdapterClient(
         scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
-    dbus_setter->SetBluetoothDeviceClient(
+    bluez_dbus_setter->SetBluetoothDeviceClient(
         scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
-    dbus_setter->SetBluetoothGattCharacteristicClient(
+    bluez_dbus_setter->SetBluetoothGattCharacteristicClient(
         scoped_ptr<BluetoothGattCharacteristicClient>(
             new FakeBluetoothGattCharacteristicClient));
-    dbus_setter->SetBluetoothGattDescriptorClient(
+    bluez_dbus_setter->SetBluetoothGattDescriptorClient(
         scoped_ptr<BluetoothGattDescriptorClient>(
             new FakeBluetoothGattDescriptorClient));
-    dbus_setter->SetBluetoothGattServiceClient(
+    bluez_dbus_setter->SetBluetoothGattServiceClient(
         scoped_ptr<BluetoothGattServiceClient>(
             new FakeBluetoothGattServiceClient));
-    dbus_setter->SetBluetoothInputClient(
+    bluez_dbus_setter->SetBluetoothInputClient(
         scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
-    dbus_setter->SetBluetoothAgentManagerClient(
+    bluez_dbus_setter->SetBluetoothAgentManagerClient(
         scoped_ptr<BluetoothAgentManagerClient>(
             new FakeBluetoothAgentManagerClient));
 
     // Set up a PowerManagerClient instance for PerfProvider.
+    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
+        DBusThreadManager::GetSetterForTesting();
     dbus_setter->SetPowerManagerClient(
         scoped_ptr<PowerManagerClient>(
             PowerManagerClient::Create(STUB_DBUS_CLIENT_IMPLEMENTATION)));
 
     // Grab pointers to members of the thread manager for easier testing.
     fake_bluetooth_adapter_client_ = static_cast<FakeBluetoothAdapterClient*>(
-        DBusThreadManager::Get()->GetBluetoothAdapterClient());
+        BluezDBusManager::Get()->GetBluetoothAdapterClient());
     fake_bluetooth_device_client_ = static_cast<FakeBluetoothDeviceClient*>(
-        DBusThreadManager::Get()->GetBluetoothDeviceClient());
+        BluezDBusManager::Get()->GetBluetoothDeviceClient());
 
     // Initialize the login state trackers.
     if (!chromeos::LoginState::IsInitialized())
diff --git a/chrome/browser/metrics/metrics_reporting_state.cc b/chrome/browser/metrics/metrics_reporting_state.cc
index 318766b..e9d658e 100644
--- a/chrome/browser/metrics/metrics_reporting_state.cc
+++ b/chrome/browser/metrics/metrics_reporting_state.cc
@@ -60,7 +60,7 @@
   }
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
   g_browser_process->local_state()->SetBoolean(
-      prefs::kMetricsReportingEnabled, updated_pref);
+      metrics::prefs::kMetricsReportingEnabled, updated_pref);
 #endif
   // When a user opts in to the metrics reporting service, the previously
   // collected data should be cleared to ensure that nothing is reported before
@@ -103,6 +103,6 @@
 bool IsMetricsReportingUserChangable() {
   const PrefService* pref_service = g_browser_process->local_state();
   const PrefService::Preference* pref =
-      pref_service->FindPreference(prefs::kMetricsReportingEnabled);
+      pref_service->FindPreference(metrics::prefs::kMetricsReportingEnabled);
   return pref && !pref->IsManaged();
 }
diff --git a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
index 2b5fcb9..4b3f4a6 100644
--- a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
+++ b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/net/ssl_config_service_manager_pref.cc b/chrome/browser/net/ssl_config_service_manager_pref.cc
index f419580..9a400ec 100644
--- a/chrome/browser/net/ssl_config_service_manager_pref.cc
+++ b/chrome/browser/net/ssl_config_service_manager_pref.cc
@@ -20,7 +20,6 @@
 #include "components/content_settings/core/browser/content_settings_utils.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/socket/ssl_client_socket.h"
 #include "net/ssl/ssl_cipher_suite_names.h"
 #include "net/ssl/ssl_config_service.h"
 
@@ -159,7 +158,6 @@
   StringPrefMember ssl_version_min_;
   StringPrefMember ssl_version_max_;
   StringPrefMember ssl_version_fallback_min_;
-  BooleanPrefMember ssl_record_splitting_disabled_;
 
   // The cached list of disabled SSL cipher suites.
   std::vector<uint16> disabled_cipher_suites_;
@@ -191,8 +189,6 @@
       prefs::kSSLVersionMax, local_state, local_state_callback);
   ssl_version_fallback_min_.Init(
       prefs::kSSLVersionFallbackMin, local_state, local_state_callback);
-  ssl_record_splitting_disabled_.Init(
-      prefs::kDisableSSLRecordSplitting, local_state, local_state_callback);
 
   local_state_change_registrar_.Init(local_state);
   local_state_change_registrar_.Add(
@@ -216,8 +212,6 @@
   registry->RegisterStringPref(prefs::kSSLVersionMin, std::string());
   registry->RegisterStringPref(prefs::kSSLVersionMax, std::string());
   registry->RegisterStringPref(prefs::kSSLVersionFallbackMin, std::string());
-  registry->RegisterBooleanPref(prefs::kDisableSSLRecordSplitting,
-                                !default_config.false_start_enabled);
   registry->RegisterListPref(prefs::kCipherSuiteBlacklist);
 }
 
@@ -261,7 +255,7 @@
   std::string version_max_str = ssl_version_max_.GetValue();
   std::string version_fallback_min_str = ssl_version_fallback_min_.GetValue();
   config->version_min = net::kDefaultSSLVersionMin;
-  config->version_max = net::SSLClientSocket::GetMaxSupportedSSLVersion();
+  config->version_max = net::kDefaultSSLVersionMax;
   config->version_fallback_min = net::kDefaultSSLVersionFallbackMin;
   uint16 version_min = SSLProtocolVersionFromString(version_min_str);
   uint16 version_max = SSLProtocolVersionFromString(version_max_str);
@@ -278,8 +272,6 @@
     config->version_fallback_min = version_fallback_min;
   }
   config->disabled_cipher_suites = disabled_cipher_suites_;
-  // disabling False Start also happens to disable record splitting.
-  config->false_start_enabled = !ssl_record_splitting_disabled_.GetValue();
 }
 
 void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
diff --git a/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
index 88506b9..3216632 100644
--- a/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
@@ -19,7 +19,7 @@
 #include "components/syncable_prefs/pref_service_mock_factory.h"
 #include "components/syncable_prefs/testing_pref_service_syncable.h"
 #include "content/public/test/test_browser_thread.h"
-#include "net/socket/ssl_client_socket.h"
+#include "net/ssl/ssl_config.h"
 #include "net/ssl/ssl_config_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -148,12 +148,10 @@
 
   SSLConfig ssl_config;
   config_service->GetSSLConfig(&ssl_config);
-  // In the absence of command-line options, TLS versions from 1.0 up to 1.1 or
-  // 1.2 (depending on the underlying library and cryptographic implementation)
-  // are enabled.
-  EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_min);
-  EXPECT_EQ(net::SSLClientSocket::GetMaxSupportedSSLVersion(),
-            ssl_config.version_max);
+  // In the absence of command-line options, the default TLS version range is
+  // enabled.
+  EXPECT_EQ(net::kDefaultSSLVersionMin, ssl_config.version_min);
+  EXPECT_EQ(net::kDefaultSSLVersionMax, ssl_config.version_max);
 
   // The settings should not be added to the local_state.
   EXPECT_FALSE(local_state->HasPrefPath(prefs::kSSLVersionMin));
diff --git a/chrome/browser/notifications/extension_welcome_notification.cc b/chrome/browser/notifications/extension_welcome_notification.cc
index b34bf3df..2d49ee4 100644
--- a/chrome/browser/notifications/extension_welcome_notification.cc
+++ b/chrome/browser/notifications/extension_welcome_notification.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc
index d221a234..7e3fbcf 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -197,10 +197,7 @@
           continue;
         }
         psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND;
-        form->original_signon_realm = form->signon_realm;
-        form->signon_realm = lookup_form->signon_realm;
-        form->origin = lookup_form->origin;
-        form->action = lookup_form->action;
+        form->is_public_suffix_match = true;
       }
       if (data->secret) {
         form->password_value = UTF8ToUTF16(data->secret);
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
index 01ef6ea5..adcd284c 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -582,8 +582,8 @@
     EXPECT_EQ(1u, form_list.size());
     PasswordForm m_facebook = *form_list[0];
     form_list.clear();
-    EXPECT_EQ(kMobileURL, m_facebook.origin);
-    EXPECT_EQ(kMobileURL.spec(), m_facebook.signon_realm);
+    m_facebook.origin = kMobileURL;
+    m_facebook.signon_realm = kMobileURL.spec();
 
     // Add the PSL-matched copy to saved logins.
     BrowserThread::PostTask(
@@ -648,7 +648,7 @@
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
     size_t index_non_psl = 0;
-    if (!form_list[index_non_psl]->original_signon_realm.empty())
+    if (form_list[index_non_psl]->is_public_suffix_match)
       index_non_psl = 1;
     EXPECT_EQ(kMobileURL, form_list[index_non_psl]->origin);
     EXPECT_EQ(kMobileURL.spec(), form_list[index_non_psl]->signon_realm);
@@ -668,7 +668,7 @@
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
     index_non_psl = 0;
-    if (!form_list[index_non_psl]->original_signon_realm.empty())
+    if (form_list[index_non_psl]->is_public_suffix_match)
       index_non_psl = 1;
     EXPECT_EQ(form_facebook_.origin, form_list[index_non_psl]->origin);
     EXPECT_EQ(form_facebook_.signon_realm,
@@ -831,8 +831,8 @@
   const GURL kMobileURL("http://m.facebook.com/");
   EXPECT_TRUE(CheckCredentialAvailability(
       form_facebook_, kMobileURL, PasswordForm::SCHEME_HTML, &result));
-  EXPECT_EQ(kMobileURL, result.origin);
-  EXPECT_EQ(kMobileURL.spec(), result.signon_realm);
+  EXPECT_EQ(form_facebook_.origin, result.origin);
+  EXPECT_EQ(form_facebook_.signon_realm, result.signon_realm);
 }
 
 // Save a password for www.facebook.com and see it not suggested for
diff --git a/chrome/browser/password_manager/native_backend_libsecret.cc b/chrome/browser/password_manager/native_backend_libsecret.cc
index fdd95a3..a0d81ef 100644
--- a/chrome/browser/password_manager/native_backend_libsecret.cc
+++ b/chrome/browser/password_manager/native_backend_libsecret.cc
@@ -614,9 +614,7 @@
           continue;
         }
         psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND;
-        form->original_signon_realm = form->signon_realm;
-        form->signon_realm = lookup_form->signon_realm;
-        form->origin = lookup_form->origin;
+        form->is_public_suffix_match = true;
       }
       SecretValue* secretValue = secret_item_get_secret(secretItem);
       if (secretValue) {
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
index 6b5c21d0..759ba3f 100644
--- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -464,8 +464,8 @@
     EXPECT_EQ(1u, form_list.size());
     PasswordForm m_facebook = *form_list[0];
     form_list.clear();
-    EXPECT_EQ(kMobileURL, m_facebook.origin);
-    EXPECT_EQ(kMobileURL.spec(), m_facebook.signon_realm);
+    m_facebook.origin = kMobileURL;
+    m_facebook.signon_realm = kMobileURL.spec();
 
     // Add the PSL-matched copy to saved logins.
     VerifiedAdd(&backend, m_facebook);
@@ -495,7 +495,7 @@
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
     size_t index_non_psl = 0;
-    if (!form_list[index_non_psl]->original_signon_realm.empty())
+    if (form_list[index_non_psl]->is_public_suffix_match)
       index_non_psl = 1;
     EXPECT_EQ(kMobileURL, form_list[index_non_psl]->origin);
     EXPECT_EQ(kMobileURL.spec(), form_list[index_non_psl]->signon_realm);
@@ -507,7 +507,7 @@
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
     index_non_psl = 0;
-    if (!form_list[index_non_psl]->original_signon_realm.empty())
+    if (form_list[index_non_psl]->is_public_suffix_match)
       index_non_psl = 1;
     EXPECT_EQ(form_facebook_.origin, form_list[index_non_psl]->origin);
     EXPECT_EQ(form_facebook_.signon_realm,
@@ -632,8 +632,8 @@
   const GURL kMobileURL("http://m.facebook.com/");
   EXPECT_TRUE(CheckCredentialAvailability(form_facebook_, kMobileURL,
                                           PasswordForm::SCHEME_HTML, &result));
-  EXPECT_EQ(kMobileURL, result.origin);
-  EXPECT_EQ(kMobileURL.spec(), result.signon_realm);
+  EXPECT_EQ(form_facebook_.origin, result.origin);
+  EXPECT_EQ(form_facebook_.signon_realm, result.signon_realm);
 }
 
 // Save a password for www.facebook.com and see it not suggested for
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index ea107e0..7688c10 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/password_manager/test_password_store_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/browser/ui/login/login_prompt_test_utils.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service.cc b/chrome/browser/password_manager/password_manager_setting_migrator_service.cc
index 301b136..10797ec 100644
--- a/chrome/browser/password_manager/password_manager_setting_migrator_service.cc
+++ b/chrome/browser/password_manager/password_manager_setting_migrator_service.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -120,9 +121,13 @@
   DCHECK_EQ(chrome::NOTIFICATION_PROFILE_ADDED, type);
   SaveCurrentPrefState(profile_->GetPrefs(), &initial_new_pref_value_,
                        &initial_legacy_pref_value_);
+  const int kMaxInitialValues = 4;
+  UMA_HISTOGRAM_ENUMERATION(
+      "PasswordManager.SettingsReconciliation.InitialValues",
+      (static_cast<int>(initial_new_pref_value_) << 1 |
+       static_cast<int>(initial_legacy_pref_value_)),
+      kMaxInitialValues);
   if (!password_manager::IsSettingsMigrationActive()) {
-    // TODO(melandory) Add histogram which will log initial values for the both
-    // settings.
     return;
   }
   if (ProfileSyncServiceFactory::HasProfileSyncService(profile_))
@@ -230,4 +235,6 @@
       UpdatePreferencesValues(prefs, false);
     }
   }
+  // TODO(melandory) Add histogram which will log combination of initial and
+  // final values for the both preferences.
 }
diff --git a/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc b/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc
index beadf71..961218c 100644
--- a/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc
+++ b/chrome/browser/password_manager/password_manager_setting_migrator_service_unittest.cc
@@ -5,8 +5,10 @@
 #include "base/json/json_writer.h"
 #include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
+#include "base/test/histogram_tester.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/password_manager/password_manager_setting_migrator_service.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
@@ -31,12 +33,25 @@
 const char kEnabledGroupName[] = "Enable";
 const char kDisabledGroupName[] = "Disable";
 
+const char kInitialValuesHistogramName[] =
+    "PasswordManager.SettingsReconciliation.InitialValues";
+
 enum BooleanPrefState {
   OFF,
   ON,
   EMPTY,  // datatype bucket is empty
 };
 
+// Enum used for histogram tracking of the initial values for the legacy and new
+// preferences.
+enum PasswordManagerPreferencesInitialValues {
+  N0L0,
+  N0L1,
+  N1L0,
+  N1L1,
+  NUM_INITIAL_VALUES,
+};
+
 syncer::SyncData CreatePrefSyncData(const std::string& name, bool value) {
   base::FundamentalValue bool_value(value);
   std::string serialized;
@@ -145,30 +160,6 @@
     base::FieldTrialList::CreateFieldTrial(kFieldTrialName, name);
   }
 
-  void TestOnLocalChange(const std::string& name, bool value) {
-    PrefService* prefs = profile()->GetPrefs();
-    prefs->SetBoolean(prefs::kCredentialsEnableService, !value);
-    prefs->SetBoolean(prefs::kPasswordManagerSavingEnabled, !value);
-    NotifyProfileAdded();
-    prefs->SetBoolean(name, value);
-    ExpectValuesForBothPrefValues(value, value);
-  }
-
-  void TestOnLocalChangeWhenMigrationIsDisabled(const std::string& name,
-                                                bool value) {
-    ResetProfile();
-    EnforcePasswordManagerSettingMigrationExperiment(kDisabledGroupName);
-    PrefService* prefs = profile()->GetPrefs();
-    prefs->SetBoolean(prefs::kCredentialsEnableService, !value);
-    prefs->SetBoolean(prefs::kPasswordManagerSavingEnabled, !value);
-    NotifyProfileAdded();
-    prefs->SetBoolean(name, value);
-    if (name == prefs::kPasswordManagerSavingEnabled)
-      ExpectValuesForBothPrefValues(!value, value);
-    else
-      ExpectValuesForBothPrefValues(value, !value);
-  }
-
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<TestingProfile> profile_;
@@ -177,36 +168,41 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordManagerSettingMigratorServiceTest);
 };
 
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       ReconcileOnLocalChangeOfPasswordManagerSavingEnabledOn) {
-  TestOnLocalChange(prefs::kPasswordManagerSavingEnabled, true);
-}
+TEST_F(PasswordManagerSettingMigratorServiceTest, TestMigrationOnLocalChanges) {
+  const struct {
+    const char* group;
+    const char* pref_name;
+    bool pref_value;
+    bool expected_new_pref_value;
+    bool expected_old_pref_value;
+  } kTestingTable[] = {
+      {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, true, true,
+       true},
+      {kEnabledGroupName, prefs::kPasswordManagerSavingEnabled, false, false,
+       false},
+      {kEnabledGroupName, prefs::kCredentialsEnableService, true, true, true},
+      {kEnabledGroupName, prefs::kCredentialsEnableService, false, false,
+       false},
+      {kDisabledGroupName, prefs::kPasswordManagerSavingEnabled, false, true,
+       false},
+      {kDisabledGroupName, prefs::kCredentialsEnableService, false, false,
+       true}};
 
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       ReconcileOnLocalChangeOfPasswordManagerSavingEnabledOff) {
-  TestOnLocalChange(prefs::kPasswordManagerSavingEnabled, false);
-}
-
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       ReconcileOnLocalChangeOfCredentialsEnableServiceOn) {
-  TestOnLocalChange(prefs::kCredentialsEnableService, true);
-}
-
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       ReconcileOnLocalChangeOfCredentialsEnableServiceOff) {
-  TestOnLocalChange(prefs::kCredentialsEnableService, false);
-}
-
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       DoNotReconcileOnLocalChangeOfNewPrefWhenMigrationIsDisabled) {
-  TestOnLocalChangeWhenMigrationIsDisabled(prefs::kCredentialsEnableService,
-                                           false);
-}
-
-TEST_F(PasswordManagerSettingMigratorServiceTest,
-       DoNotReconcileOnLocalChangeOfLegacyPrefWhenMigrationIsDisabled) {
-  TestOnLocalChangeWhenMigrationIsDisabled(prefs::kPasswordManagerSavingEnabled,
-                                           false);
+  for (const auto& test_case : kTestingTable) {
+    ResetProfile();
+    EnforcePasswordManagerSettingMigrationExperiment(test_case.group);
+    PrefService* prefs = profile()->GetPrefs();
+    prefs->SetBoolean(prefs::kCredentialsEnableService, !test_case.pref_value);
+    prefs->SetBoolean(prefs::kPasswordManagerSavingEnabled,
+                      !test_case.pref_value);
+    NotifyProfileAdded();
+    base::HistogramTester tester;
+    prefs->SetBoolean(test_case.pref_name, test_case.pref_value);
+    ExpectValuesForBothPrefValues(test_case.expected_new_pref_value,
+                                  test_case.expected_old_pref_value);
+    EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName),
+                testing::IsEmpty());
+  }
 }
 
 TEST_F(PasswordManagerSettingMigratorServiceTest,
@@ -217,31 +213,32 @@
     BooleanPrefState new_pref_sync_value;
     BooleanPrefState old_pref_sync_value;
     bool result_value;
+    PasswordManagerPreferencesInitialValues histogram_initial_value;
   } kTestingTable[] = {
-      {EMPTY, EMPTY, EMPTY, EMPTY, true},
-      {EMPTY, EMPTY, EMPTY, OFF, false},
-      {EMPTY, EMPTY, EMPTY, ON, true},
-      {EMPTY, EMPTY, OFF, EMPTY, false},
-      {EMPTY, EMPTY, ON, EMPTY, true},
-      {OFF, OFF, EMPTY, EMPTY, false},
-      {OFF, OFF, OFF, OFF, false},
-      {OFF, OFF, OFF, ON, true},
-      {OFF, OFF, ON, OFF, true},
-      {OFF, ON, OFF, ON, false},
-      {OFF, ON, ON, OFF, false},
-      {OFF, ON, ON, ON, true},
-      {ON, OFF, EMPTY, EMPTY, false},
-      {ON, OFF, OFF, ON, false},
-      {ON, OFF, ON, OFF, false},
-      {ON, OFF, ON, ON, true},
-      {ON, ON, EMPTY, OFF, false},
-      {ON, ON, EMPTY, ON, true},
-      {ON, ON, OFF, EMPTY, false},
-      {ON, ON, OFF, OFF, false},
-      {ON, ON, OFF, ON, false},
-      {ON, ON, ON, EMPTY, true},
-      {ON, ON, ON, OFF, false},
-      {ON, ON, ON, ON, true},
+      {EMPTY, EMPTY, EMPTY, EMPTY, true, N1L1},
+      {EMPTY, EMPTY, EMPTY, OFF, false, N1L1},
+      {EMPTY, EMPTY, EMPTY, ON, true, N1L1},
+      {EMPTY, EMPTY, OFF, EMPTY, false, N1L1},
+      {EMPTY, EMPTY, ON, EMPTY, true, N1L1},
+      {OFF, OFF, EMPTY, EMPTY, false, N0L0},
+      {OFF, OFF, OFF, OFF, false, N0L0},
+      {OFF, OFF, OFF, ON, true, N0L0},
+      {OFF, OFF, ON, OFF, true, N0L0},
+      {OFF, ON, OFF, ON, false, N0L1},
+      {OFF, ON, ON, OFF, false, N0L1},
+      {OFF, ON, ON, ON, true, N0L1},
+      {ON, OFF, EMPTY, EMPTY, false, N1L0},
+      {ON, OFF, OFF, ON, false, N1L0},
+      {ON, OFF, ON, OFF, false, N1L0},
+      {ON, OFF, ON, ON, true, N1L0},
+      {ON, ON, EMPTY, OFF, false, N1L1},
+      {ON, ON, EMPTY, ON, true, N1L1},
+      {ON, ON, OFF, EMPTY, false, N1L1},
+      {ON, ON, OFF, OFF, false, N1L1},
+      {ON, ON, OFF, ON, false, N1L1},
+      {ON, ON, ON, EMPTY, true, N1L1},
+      {ON, ON, ON, OFF, false, N1L1},
+      {ON, ON, ON, ON, true, N1L1},
   };
 
   for (const auto& test_case : kTestingTable) {
@@ -257,6 +254,7 @@
                         test_case.old_pref_local_value);
     SetupLocalPrefState(prefs::kCredentialsEnableService,
                         test_case.new_pref_local_value);
+    base::HistogramTester tester;
     NotifyProfileAdded();
     syncable_prefs::PrefServiceSyncable* prefs =
         PrefServiceSyncableFromProfile(profile());
@@ -266,6 +264,9 @@
                      test_case.old_pref_sync_value);
     ExpectValuesForBothPrefValues(test_case.result_value,
                                   test_case.result_value);
+    EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName),
+                testing::ElementsAre(
+                    base::Bucket(test_case.histogram_initial_value, 1)));
   }
 }
 
@@ -278,29 +279,30 @@
     BooleanPrefState old_pref_sync_value;
     bool result_new_pref_value;
     bool result_old_pref_value;
+    PasswordManagerPreferencesInitialValues histogram_initial_value;
   } kTestingTable[] = {
-      {OFF, OFF, OFF, ON, false, true},
-      {OFF, OFF, ON, OFF, true, false},
-      {OFF, OFF, ON, ON, true, true},
-      {OFF, ON, EMPTY, OFF, false, false},
-      {OFF, ON, EMPTY, ON, false, true},
-      {OFF, ON, OFF, EMPTY, false, true},
-      {OFF, ON, OFF, OFF, false, false},
-      {OFF, ON, OFF, ON, false, true},
-      {OFF, ON, ON, EMPTY, true, true},
-      {OFF, ON, ON, OFF, true, false},
-      {OFF, ON, ON, ON, true, true},
-      {ON, OFF, OFF, ON, false, true},
-      {ON, OFF, ON, OFF, true, false},
-      {ON, OFF, ON, ON, true, true},
-      {ON, ON, EMPTY, OFF, true, false},
-      {ON, ON, EMPTY, ON, true, true},
-      {ON, ON, OFF, EMPTY, false, true},
-      {ON, ON, OFF, OFF, false, false},
-      {ON, ON, OFF, ON, false, true},
-      {ON, ON, ON, EMPTY, true, true},
-      {ON, ON, ON, OFF, true, false},
-      {ON, ON, ON, ON, true, true},
+      {OFF, OFF, OFF, ON, false, true, N0L0},
+      {OFF, OFF, ON, OFF, true, false, N0L0},
+      {OFF, OFF, ON, ON, true, true, N0L0},
+      {OFF, ON, EMPTY, OFF, false, false, N0L1},
+      {OFF, ON, EMPTY, ON, false, true, N0L1},
+      {OFF, ON, OFF, EMPTY, false, true, N0L1},
+      {OFF, ON, OFF, OFF, false, false, N0L1},
+      {OFF, ON, OFF, ON, false, true, N0L1},
+      {OFF, ON, ON, EMPTY, true, true, N0L1},
+      {OFF, ON, ON, OFF, true, false, N0L1},
+      {OFF, ON, ON, ON, true, true, N0L1},
+      {ON, OFF, OFF, ON, false, true, N1L0},
+      {ON, OFF, ON, OFF, true, false, N1L0},
+      {ON, OFF, ON, ON, true, true, N1L0},
+      {ON, ON, EMPTY, OFF, true, false, N1L1},
+      {ON, ON, EMPTY, ON, true, true, N1L1},
+      {ON, ON, OFF, EMPTY, false, true, N1L1},
+      {ON, ON, OFF, OFF, false, false, N1L1},
+      {ON, ON, OFF, ON, false, true, N1L1},
+      {ON, ON, ON, EMPTY, true, true, N1L1},
+      {ON, ON, ON, OFF, true, false, N1L1},
+      {ON, ON, ON, ON, true, true, N1L1},
   };
 
   for (const auto& test_case : kTestingTable) {
@@ -316,6 +318,7 @@
                         test_case.old_pref_local_value);
     SetupLocalPrefState(prefs::kCredentialsEnableService,
                         test_case.new_pref_local_value);
+    base::HistogramTester tester;
     NotifyProfileAdded();
     syncable_prefs::PrefServiceSyncable* prefs =
         PrefServiceSyncableFromProfile(profile());
@@ -325,6 +328,9 @@
                      test_case.old_pref_sync_value);
     ExpectValuesForBothPrefValues(test_case.result_new_pref_value,
                                   test_case.result_old_pref_value);
+    EXPECT_THAT(tester.GetAllSamples(kInitialValuesHistogramName),
+                testing::ElementsAre(
+                    base::Bucket(test_case.histogram_initial_value, 1)));
   }
 }
 
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index c7642219..f067dd8 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -478,8 +478,7 @@
   }
   bool equal_realm = form_a.signon_realm == form_b.signon_realm;
   if (strictness == FUZZY_FORM_MATCH) {
-    equal_realm |= (!form_a.original_signon_realm.empty()) &&
-                   form_a.original_signon_realm == form_b.signon_realm;
+    equal_realm |= form_a.is_public_suffix_match;
   }
   return form_a.scheme == form_b.scheme && equal_realm &&
          form_a.username_value == form_b.username_value;
@@ -1183,9 +1182,8 @@
     // http://crbug.com/340112
     if (form.scheme != db_form->scheme)
       continue;  // Forms with different schemes never match.
-    const std::string& original_singon_realm(db_form->original_signon_realm);
-    if (!original_singon_realm.empty())
-      realm_set.insert(original_singon_realm);
+    if (db_form->is_public_suffix_match)
+      realm_set.insert(db_form->signon_realm);
   }
   ScopedVector<autofill::PasswordForm> keychain_forms;
   for (std::set<std::string>::const_iterator realm = realm_set.begin();
@@ -1277,9 +1275,9 @@
   if (!login_metadata_db_->GetLogins(form, &database_forms))
     return false;
   for (const autofill::PasswordForm* db_form : database_forms) {
-    // Below we filter out forms with non-empty original_signon_realm, because
-    // those signal fuzzy matches, and we are only interested in exact ones.
-    if (db_form->original_signon_realm.empty() &&
+    // Below we filter out fuzzy matched forms because we are only interested
+    // in exact ones.
+    if (!db_form->is_public_suffix_match &&
         internal_keychain_helpers::FormsMatchForMerge(
             form, *db_form, internal_keychain_helpers::STRICT_FORM_MATCH) &&
         db_form->origin == form.origin) {
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc
index a201fcbe..412e6778 100644
--- a/chrome/browser/password_manager/password_store_mac_unittest.cc
+++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -1451,6 +1451,8 @@
   base::MessageLoop::current()->Run();
 
   // 3. Add the returned password for m.facebook.com.
+  returned_form.signon_realm = "http://m.facebook.com";
+  returned_form.origin = GURL("http://m.facebook.com/index.html");
   EXPECT_EQ(AddChangeForForm(returned_form),
             login_db()->AddLogin(returned_form));
   owned_keychain_adapter.AddPassword(m_form);
@@ -1528,8 +1530,6 @@
   scoped_ptr<PasswordForm> form_other =
       CreatePasswordFormFromDataForTesting(www_form_data_other);
   base::Time now = base::Time::Now();
-  // TODO(vasilii): remove the next line once crbug/374132 is fixed.
-  now = base::Time::FromTimeT(now.ToTimeT());
   base::Time next_day = now + base::TimeDelta::FromDays(1);
   if (check_created) {
     form_facebook_old->date_created = now;
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.cc b/chrome/browser/permissions/permission_bubble_request_impl.cc
index 8336f92f..6e2e480 100644
--- a/chrome/browser/permissions/permission_bubble_request_impl.cc
+++ b/chrome/browser/permissions/permission_bubble_request_impl.cc
@@ -80,10 +80,6 @@
       icon_id = IDR_INFOBAR_PROTECTED_MEDIA_IDENTIFIER;
       break;
 #endif
-    // TODO(dgrogan): Get a real icon. https://crbug.com/516069
-    case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE:
-      icon_id = IDR_INFOBAR_WARNING;
-      break;
     default:
       NOTREACHED();
       return IDR_INFOBAR_WARNING;
diff --git a/chrome/browser/permissions/permission_update_infobar_delegate_android.cc b/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
index 35ad885..3edeaaf 100644
--- a/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
+++ b/chrome/browser/permissions/permission_update_infobar_delegate_android.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/android/jni_array.h"
+#include "base/callback_helpers.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/android/preferences/pref_service_bridge.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -76,7 +77,7 @@
 
 void PermissionUpdateInfoBarDelegate::OnPermissionResult(
     JNIEnv* env, jobject obj, jboolean all_permissions_granted) {
-  callback_.Run(all_permissions_granted);
+  base::ResetAndReturn(&callback_).Run(all_permissions_granted);
   infobar()->RemoveSelf();
 }
 
@@ -106,6 +107,9 @@
 PermissionUpdateInfoBarDelegate::~PermissionUpdateInfoBarDelegate() {
   Java_PermissionUpdateInfoBarDelegate_onNativeDestroyed(
       base::android::AttachCurrentThread(), java_delegate_.obj());
+
+  if (!callback_.is_null())
+    callback_.Run(false);
 }
 
 int PermissionUpdateInfoBarDelegate::GetIconId() const {
@@ -167,6 +171,10 @@
 }
 
 bool PermissionUpdateInfoBarDelegate::Cancel() {
-  callback_.Run(false);
+  base::ResetAndReturn(&callback_).Run(false);
   return true;
 }
+
+void PermissionUpdateInfoBarDelegate::InfoBarDismissed() {
+  base::ResetAndReturn(&callback_).Run(false);
+}
diff --git a/chrome/browser/permissions/permission_update_infobar_delegate_android.h b/chrome/browser/permissions/permission_update_infobar_delegate_android.h
index 28767382..1500e7971 100644
--- a/chrome/browser/permissions/permission_update_infobar_delegate_android.h
+++ b/chrome/browser/permissions/permission_update_infobar_delegate_android.h
@@ -65,9 +65,12 @@
   bool Accept() override;
   bool Cancel() override;
 
+  // InfoBarDelegate:
+  void InfoBarDismissed() override;
+
   base::android::ScopedJavaGlobalRef<jobject> java_delegate_;
   std::vector<ContentSettingsType> content_settings_types_;
-  const PermissionUpdatedCallback callback_;
+  PermissionUpdatedCallback callback_;
   ui::WindowAndroid* window_android_;
 
   DISALLOW_COPY_AND_ASSIGN(PermissionUpdateInfoBarDelegate);
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc
index 077a044..305c797 100644
--- a/chrome/browser/platform_util_chromeos.cc
+++ b/chrome/browser/platform_util_chromeos.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/simple_message_box.h"
 #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.cc b/chrome/browser/plugins/plugin_infobar_delegates.cc
index 01739b4..b9ebe0f3 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.cc
+++ b/chrome/browser/plugins/plugin_infobar_delegates.cc
@@ -46,41 +46,6 @@
 
 using base::UserMetricsAction;
 
-
-// PluginInfoBarDelegate ------------------------------------------------------
-
-PluginInfoBarDelegate::PluginInfoBarDelegate(const std::string& identifier)
-    : ConfirmInfoBarDelegate(),
-      identifier_(identifier) {
-}
-
-PluginInfoBarDelegate::~PluginInfoBarDelegate() {
-}
-
-bool PluginInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
-  InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
-      content::OpenURLParams(
-          GURL(GetLearnMoreURL()), content::Referrer(),
-          (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
-          ui::PAGE_TRANSITION_LINK, false));
-  return false;
-}
-
-void PluginInfoBarDelegate::LoadBlockedPlugins() {
-  content::WebContents* web_contents =
-      InfoBarService::WebContentsFromInfoBar(infobar());
-  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
-      web_contents, true, identifier_);
-}
-
-int PluginInfoBarDelegate::GetIconId() const {
-  return IDR_INFOBAR_PLUGIN_INSTALL;
-}
-
-base::string16 PluginInfoBarDelegate::GetLinkText() const {
-  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
-}
-
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 
 // OutdatedPluginInfoBarDelegate ----------------------------------------------
@@ -105,8 +70,9 @@
     PluginInstaller* installer,
     scoped_ptr<PluginMetadata> plugin_metadata,
     const base::string16& message)
-    : PluginInfoBarDelegate(plugin_metadata->identifier()),
+    : ConfirmInfoBarDelegate(),
       WeakPluginInstallerObserver(installer),
+      identifier_(plugin_metadata->identifier()),
       plugin_metadata_(plugin_metadata.Pass()),
       message_(message) {
   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
@@ -140,6 +106,10 @@
   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
 }
 
+int OutdatedPluginInfoBarDelegate::GetIconId() const {
+  return IDR_INFOBAR_PLUGIN_INSTALL;
+}
+
 base::string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
   return message_;
 }
@@ -169,18 +139,28 @@
 bool OutdatedPluginInfoBarDelegate::Cancel() {
   content::RecordAction(
       UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
-  LoadBlockedPlugins();
+
+  content::WebContents* web_contents =
+      InfoBarService::WebContentsFromInfoBar(infobar());
+  ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
+      web_contents, true, identifier_);
+
   return true;
 }
 
+base::string16 OutdatedPluginInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
 bool OutdatedPluginInfoBarDelegate::LinkClicked(
     WindowOpenDisposition disposition) {
   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
-  return PluginInfoBarDelegate::LinkClicked(disposition);
-}
-
-std::string OutdatedPluginInfoBarDelegate::GetLearnMoreURL() const {
-  return chrome::kOutdatedPluginLearnMoreURL;
+  InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
+      content::OpenURLParams(
+          GURL(chrome::kOutdatedPluginLearnMoreURL), content::Referrer(),
+          (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
+          ui::PAGE_TRANSITION_LINK, false));
+  return false;
 }
 
 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.h b/chrome/browser/plugins/plugin_infobar_delegates.h
index ba1249a..79174c3 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.h
+++ b/chrome/browser/plugins/plugin_infobar_delegates.h
@@ -21,32 +21,9 @@
 class WebContents;
 }
 
-// Base class for blocked plugin infobars.
-class PluginInfoBarDelegate : public ConfirmInfoBarDelegate {
- protected:
-  explicit PluginInfoBarDelegate(const std::string& identifier);
-  ~PluginInfoBarDelegate() override;
-
-  // ConfirmInfoBarDelegate:
-  bool LinkClicked(WindowOpenDisposition disposition) override;
-
-  virtual std::string GetLearnMoreURL() const = 0;
-
-  void LoadBlockedPlugins();
-
- private:
-  // ConfirmInfoBarDelegate:
-  int GetIconId() const override;
-  base::string16 GetLinkText() const override;
-
-  std::string identifier_;
-
-  DISALLOW_COPY_AND_ASSIGN(PluginInfoBarDelegate);
-};
-
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 // Infobar that's shown when a plugin is out of date.
-class OutdatedPluginInfoBarDelegate : public PluginInfoBarDelegate,
+class OutdatedPluginInfoBarDelegate : public ConfirmInfoBarDelegate,
                                       public WeakPluginInstallerObserver {
  public:
   // Creates an outdated plugin infobar and delegate and adds the infobar to
@@ -68,14 +45,15 @@
                                 const base::string16& message);
   ~OutdatedPluginInfoBarDelegate() override;
 
-  // PluginInfoBarDelegate:
+  // ConfirmInfoBarDelegate:
   void InfoBarDismissed() override;
+  int GetIconId() const override;
   base::string16 GetMessageText() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
+  base::string16 GetLinkText() const override;
   bool LinkClicked(WindowOpenDisposition disposition) override;
-  std::string GetLearnMoreURL() const override;
 
   // PluginInstallerObserver:
   void DownloadStarted() override;
@@ -90,6 +68,8 @@
   // not have any buttons (and not call the callback).
   void ReplaceWithInfoBar(const base::string16& message);
 
+  std::string identifier_;
+
   scoped_ptr<PluginMetadata> plugin_metadata_;
 
   base::string16 message_;
diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc
index 21b5df70..1e68f6b 100644
--- a/chrome/browser/plugins/plugin_observer.cc
+++ b/chrome/browser/plugins/plugin_observer.cc
@@ -34,6 +34,7 @@
 #include "content/public/common/webplugininfo.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/vector_icons_public.h"
 
 #if defined(ENABLE_PLUGIN_INSTALLATION)
 #if defined(OS_WIN)
@@ -136,6 +137,7 @@
 
   // ConfirmInfobarDelegate:
   int GetIconId() const override;
+  gfx::VectorIconId GetVectorIconId() const override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
@@ -167,6 +169,14 @@
   return IDR_INFOBAR_PLUGIN_CRASHED;
 }
 
+gfx::VectorIconId ReloadPluginInfoBarDelegate::GetVectorIconId() const {
+#if !defined(OS_MACOSX) && !defined(OS_IOS) && !defined(OS_ANDROID)
+  return gfx::VectorIconId::EXTENSION_CRASHED;
+#else
+  return gfx::VectorIconId::VECTOR_ICON_NONE;
+#endif
+}
+
 base::string16 ReloadPluginInfoBarDelegate::GetMessageText() const {
   return message_;
 }
@@ -407,6 +417,11 @@
   SimpleAlertInfoBarDelegate::Create(
       InfoBarService::FromWebContents(web_contents()),
       IDR_INFOBAR_PLUGIN_CRASHED,
+#if !defined(OS_MACOSX)
+      gfx::VectorIconId::EXTENSION_CRASHED,
+#else
+      gfx::VectorIconId::VECTOR_ICON_NONE,
+#endif
       l10n_util::GetStringFUTF16(IDS_PLUGIN_INITIALIZATION_ERROR_PROMPT,
                                  plugin_name),
       true);
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 0a90e51..22680eb 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -119,7 +119,7 @@
     prefs::kPrintPreviewDisabled,
     base::Value::TYPE_BOOLEAN },
   { key::kMetricsReportingEnabled,
-    prefs::kMetricsReportingEnabled,
+    metrics::prefs::kMetricsReportingEnabled,
     base::Value::TYPE_BOOLEAN },
   { key::kApplicationLocaleValue,
     prefs::kApplicationLocale,
@@ -211,9 +211,6 @@
   { key::kSigninAllowed,
     prefs::kSigninAllowed,
     base::Value::TYPE_BOOLEAN },
-  { key::kDisableSSLRecordSplitting,
-    prefs::kDisableSSLRecordSplitting,
-    base::Value::TYPE_BOOLEAN },
   { key::kEnableOnlineRevocationChecks,
     prefs::kCertRevocationCheckingEnabled,
     base::Value::TYPE_BOOLEAN },
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 80f61293..d965602 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -85,6 +85,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/common/content_settings.h"
@@ -1016,7 +1017,7 @@
 
   TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
       browser()->profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(service);
   TemplateURL* default_search = service->GetDefaultSearchProvider();
   ASSERT_TRUE(default_search);
   EXPECT_NE(kKeyword, default_search->keyword());
@@ -1217,7 +1218,7 @@
 
   TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
       browser()->profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(service);
   TemplateURL* default_search = service->GetDefaultSearchProvider();
   ASSERT_TRUE(default_search);
   EXPECT_NE(kKeyword, default_search->keyword());
@@ -4004,6 +4005,6 @@
   UpdateProviderPolicy(policies);
   EXPECT_FALSE(display_manager->unified_desktop_enabled());
 }
-#endif // defined(OS_CHROMEOS)
+#endif  // defined(OS_CHROMEOS)
 
 }  // namespace policy
diff --git a/chrome/browser/policy/policy_prefs_browsertest.cc b/chrome/browser/policy/policy_prefs_browsertest.cc
index cfbd3c8..2a0cc030 100644
--- a/chrome/browser/policy/policy_prefs_browsertest.cc
+++ b/chrome/browser/policy/policy_prefs_browsertest.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/external_data_fetcher.h"
@@ -498,7 +499,7 @@
   }
 
   void SetUpOnMainThread() override {
-    ui_test_utils::WaitForTemplateURLServiceToLoad(
+    search_test_utils::WaitForTemplateURLServiceToLoad(
         TemplateURLServiceFactory::GetForProfile(browser()->profile()));
   }
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c8c7140..b1a35f3 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -62,7 +62,6 @@
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
 #include "chrome/browser/ui/startup/autolaunch_prompt.h"
-#include "chrome/browser/ui/startup/default_browser_prompt.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/webui/flags_ui.h"
 #include "chrome/browser/ui/webui/instant_ui.h"
@@ -221,6 +220,10 @@
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #endif
 
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#include "chrome/browser/ui/startup/default_browser_prompt.h"
+#endif
+
 namespace {
 
 #if !defined(OS_ANDROID)
@@ -237,7 +240,6 @@
 namespace chrome {
 
 void RegisterLocalState(PrefRegistrySimple* registry) {
-
   // Please keep this list alphabetized.
   AppListService::RegisterPrefs(registry);
   browser_shutdown::RegisterPrefs(registry);
diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
index d11ba30..6df10cf 100644
--- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
+++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <string>
 
+#include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -31,7 +32,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/search_engines/default_search_manager.h"
-#include "content/public/common/content_switches.h"
 #include "extensions/browser/pref_names.h"
 #include "extensions/common/extension.h"
 
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 94c2381..441d931 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -57,7 +57,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.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/location_bar/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -946,6 +945,7 @@
 
     EXPECT_EQ(expected_count, count_);
   }
+
  private:
   int count_;
   int expected_count_;
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index e5b76b7..bd9b2535 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -34,7 +34,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc
index 3ec3df1..37058430 100644
--- a/chrome/browser/printing/print_preview_dialog_controller.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/task_management/web_contents_tags.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 3ad6bba2..1d7f32f 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -25,9 +25,10 @@
 #include "chrome/browser/web_data_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "components/content_settings/core/browser/content_settings_info.h"
+#include "components/content_settings/core/browser/content_settings_registry.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/browser/website_settings_info.h"
-#include "components/content_settings/core/browser/website_settings_registry.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/search_engines/template_url_service_client.h"
 #include "content/public/browser/web_contents.h"
@@ -491,12 +492,11 @@
 
   // TODO(raymes): Clean up this test so that we don't have such ugly iteration
   // over the content settings.
-  content_settings::WebsiteSettingsRegistry* registry =
-      content_settings::WebsiteSettingsRegistry::GetInstance();
-  for (const content_settings::WebsiteSettingsInfo* info : *registry) {
-    ContentSettingsType content_type = info->type();
-    if (content_type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
-        content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
+  content_settings::ContentSettingsRegistry* registry =
+      content_settings::ContentSettingsRegistry::GetInstance();
+  for (const content_settings::ContentSettingsInfo* info : *registry) {
+    ContentSettingsType content_type = info->website_settings_info()->type();
+    if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
         content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
       // These types are excluded because one can't call
       // GetDefaultContentSetting() for them.
@@ -520,8 +520,7 @@
       host_content_settings_map->SetDefaultContentSetting(content_type,
                                                           wildcard_setting);
     }
-    if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) &&
-        HostContentSettingsMap::IsSettingAllowedForType(
+    if (HostContentSettingsMap::IsSettingAllowedForType(
             profile()->GetPrefs(), site_setting, content_type)) {
       host_content_settings_map->SetContentSetting(
           pattern, ContentSettingsPattern::Wildcard(), content_type,
@@ -535,11 +534,9 @@
 
   ResetAndWait(ProfileResetter::CONTENT_SETTINGS);
 
-  for (const content_settings::WebsiteSettingsInfo* info : *registry) {
-    ContentSettingsType content_type = info->type();
-    if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type) ||
-        content_type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
-        content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
+  for (const content_settings::ContentSettingsInfo* info : *registry) {
+    ContentSettingsType content_type = info->website_settings_info()->type();
+    if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT ||
         content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
         content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS)
       continue;
@@ -548,15 +545,9 @@
                                                               NULL);
     EXPECT_TRUE(default_settings.count(content_type));
     EXPECT_EQ(default_settings[content_type], default_setting);
-    if (!HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
-      ContentSetting site_setting =
-          host_content_settings_map->GetContentSetting(
-              GURL("example.org"),
-              GURL(),
-              content_type,
-              std::string());
-      EXPECT_EQ(default_setting, site_setting);
-    }
+    ContentSetting site_setting = host_content_settings_map->GetContentSetting(
+        GURL("example.org"), GURL(), content_type, std::string());
+    EXPECT_EQ(default_setting, site_setting);
 
     ContentSettingsForOneType host_settings;
     host_content_settings_map->GetSettingsForOneType(
diff --git a/chrome/browser/profiles/gaia_info_update_service_unittest.cc b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
index 531fe730..2a69f28 100644
--- a/chrome/browser/profiles/gaia_info_update_service_unittest.cc
+++ b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
@@ -177,7 +177,7 @@
   size_t index = GetCache()->GetIndexOfProfileWithPath(profile()->GetPath());
   EXPECT_EQ(name, GetCache()->GetGAIANameOfProfileAtIndex(index));
   EXPECT_EQ(given_name, GetCache()->GetGAIAGivenNameOfProfileAtIndex(index));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       image, *GetCache()->GetGAIAPictureOfProfileAtIndex(index)));
   EXPECT_EQ(url, service()->GetCachedPictureURL());
   EXPECT_EQ(Profile::kNoHostedDomainFound, profile()->GetPrefs()->
@@ -199,7 +199,7 @@
   EXPECT_EQ(base::string16(), GetCache()->GetGAIANameOfProfileAtIndex(index));
   EXPECT_EQ(base::string16(),
             GetCache()->GetGAIAGivenNameOfProfileAtIndex(index));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       old_image, GetCache()->GetAvatarIconOfProfileAtIndex(index)));
   EXPECT_EQ(NULL, GetCache()->GetGAIAPictureOfProfileAtIndex(index));
   EXPECT_EQ(std::string(), service()->GetCachedPictureURL());
diff --git a/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc b/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc
index 66f1279..39b0b5d 100644
--- a/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc
+++ b/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc
@@ -40,7 +40,7 @@
       profiles::GetSizedAvatarIcon(profile_image, false, 50, 50);
 
   EXPECT_FALSE(gfx::test::IsEmpty(result));
-  EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(profile_image, result));
 
   // Test that a rectangular picture (e.g., GAIA image) is changed.
   gfx::Image rect_picture(gfx::test::CreateImage());
@@ -58,7 +58,7 @@
       ResourceBundle::GetSharedInstance().GetImageNamed(IDR_PROFILE_AVATAR_0));
   gfx::Image result = profiles::GetAvatarIconForMenu(profile_image, false);
   EXPECT_FALSE(gfx::test::IsEmpty(result));
-  EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(profile_image, result));
 
   // Test that a rectangular picture is changed.
   gfx::Image rect_picture(gfx::test::CreateImage());
@@ -74,7 +74,7 @@
       ResourceBundle::GetSharedInstance().GetImageNamed(IDR_PROFILE_AVATAR_0));
   gfx::Image result = profiles::GetAvatarIconForWebUI(profile_image, false);
   EXPECT_FALSE(gfx::test::IsEmpty(result));
-  EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(profile_image, result));
 
   // Test that a rectangular picture is changed.
   gfx::Image rect_picture(gfx::test::CreateImage());
@@ -94,7 +94,7 @@
   gfx::Image result = profiles::GetAvatarIconForTitleBar(
       profile_image, false, width, height);
   EXPECT_FALSE(gfx::test::IsEmpty(result));
-  EXPECT_TRUE(gfx::test::IsEqual(profile_image, result));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(profile_image, result));
 
   // Test that a rectangular picture is changed.
   gfx::Image rect_picture(gfx::test::CreateImage());
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc
index 9272f6e..5aa7fde 100644
--- a/chrome/browser/profiles/profile_info_cache_unittest.cc
+++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -372,7 +372,7 @@
       profiles::GetDefaultAvatarIconResourceIDAtIndex(kDefaultAvatarIndex);
   const gfx::Image& default_avatar_image(
       ResourceBundle::GetSharedInstance().GetImageNamed(default_avatar_id));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       default_avatar_image, GetCache()->GetAvatarIconOfProfileAtIndex(1)));
 
   // Set GAIA picture.
@@ -380,13 +380,13 @@
       kGaiaPictureSize, kGaiaPictureSize));
   GetCache()->SetGAIAPictureOfProfileAtIndex(1, &gaia_image);
   EXPECT_EQ(NULL, GetCache()->GetGAIAPictureOfProfileAtIndex(0));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(1)));
   // Since we're still using the default avatar, the GAIA image should be
   // preferred over the generic avatar image.
   EXPECT_TRUE(GetCache()->ProfileIsUsingDefaultAvatarAtIndex(1));
   EXPECT_TRUE(GetCache()->IsUsingGAIAPictureOfProfileAtIndex(1));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, GetCache()->GetAvatarIconOfProfileAtIndex(1)));
 
   // Set a non-default avatar. This should be preferred over the GAIA image.
@@ -398,24 +398,24 @@
       profiles::GetDefaultAvatarIconResourceIDAtIndex(kOtherAvatarIndex);
   const gfx::Image& other_avatar_image(
       ResourceBundle::GetSharedInstance().GetImageNamed(other_avatar_id));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       other_avatar_image, GetCache()->GetAvatarIconOfProfileAtIndex(1)));
 
   // Explicitly setting the GAIA picture should make it preferred again.
   GetCache()->SetIsUsingGAIAPictureOfProfileAtIndex(1, true);
   EXPECT_TRUE(GetCache()->IsUsingGAIAPictureOfProfileAtIndex(1));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(1)));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, GetCache()->GetAvatarIconOfProfileAtIndex(1)));
 
   // Clearing the IsUsingGAIAPicture flag should result in the generic image
   // being used again.
   GetCache()->SetIsUsingGAIAPictureOfProfileAtIndex(1, false);
   EXPECT_FALSE(GetCache()->IsUsingGAIAPictureOfProfileAtIndex(1));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(1)));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       other_avatar_image, GetCache()->GetAvatarIconOfProfileAtIndex(1)));
 }
 
@@ -430,7 +430,7 @@
   // Make sure everything has completed, and the file has been written to disk.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       gaia_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(0)));
 
   ResetCache();
@@ -439,7 +439,7 @@
   EXPECT_EQ(NULL, GetCache()->GetGAIAPictureOfProfileAtIndex(0));
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
     gaia_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(0)));
 }
 
@@ -478,7 +478,7 @@
 
   // Verify that the profile name and picture are not empty.
   EXPECT_EQ(profile_name, GetCache()->GetNameOfProfileAtIndex(0));
-  EXPECT_TRUE(gfx::test::IsEqual(
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
       profile_image, GetCache()->GetAvatarIconOfProfileAtIndex(0)));
 }
 
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index ffc1d5f..57ca56c6 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -887,7 +887,7 @@
 #else
   // Prep the PrefMember and send it to the IO thread, since this value will be
   // read from there.
-  enable_metrics_.Init(prefs::kMetricsReportingEnabled,
+  enable_metrics_.Init(metrics::prefs::kMetricsReportingEnabled,
                        g_browser_process->local_state());
   enable_metrics_.MoveToThread(
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index eb83cf1..1868752e 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/history/core/browser/history_db_task.h"
 #include "components/history/core/browser/history_service.h"
@@ -128,7 +129,7 @@
   // When |browser| closes a BrowsingDataRemover will be created and executed.
   // It needs a loaded TemplateUrlService or else it hangs on to a
   // CallbackList::Subscription forever.
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(guest));
 
   return browser;
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc
index 3e9cf2bf..6016ea1 100644
--- a/chrome/browser/push_messaging/push_messaging_browsertest.cc
+++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -1103,7 +1103,7 @@
   TryToSubscribeSuccessfully("1-0" /* expected_push_subscription_id */);
 
   std::string first_public_key;
-  ASSERT_TRUE(RunScript("getCurve25519dh()", &first_public_key));
+  ASSERT_TRUE(RunScript("GetP256dh()", &first_public_key));
   EXPECT_GE(first_public_key.size(), 32u);
 
   std::string script_result;
@@ -1114,7 +1114,7 @@
   TryToSubscribeSuccessfully("1-1" /* expected_push_subscription_id */);
 
   std::string second_public_key;
-  ASSERT_TRUE(RunScript("getCurve25519dh()", &second_public_key));
+  ASSERT_TRUE(RunScript("GetP256dh()", &second_public_key));
   EXPECT_GE(second_public_key.size(), 32u);
 
   EXPECT_NE(first_public_key, second_public_key);
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc
index d8a0ef3..d3f2b69a 100644
--- a/chrome/browser/push_messaging/push_messaging_service_impl.cc
+++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -455,16 +455,16 @@
 void PushMessagingServiceImpl::SubscribeEnd(
     const content::PushMessagingService::RegisterCallback& callback,
     const std::string& subscription_id,
-    const std::vector<uint8_t>& curve25519dh,
+    const std::vector<uint8_t>& p256dh,
     content::PushRegistrationStatus status) {
-  callback.Run(subscription_id, curve25519dh, status);
+  callback.Run(subscription_id, p256dh, status);
 }
 
 void PushMessagingServiceImpl::SubscribeEndWithError(
     const content::PushMessagingService::RegisterCallback& callback,
     content::PushRegistrationStatus status) {
   SubscribeEnd(callback, std::string() /* subscription_id */,
-               std::vector<uint8_t>() /* curve25519dh */, status);
+               std::vector<uint8_t>() /* p256dh */, status);
 }
 
 void PushMessagingServiceImpl::DidSubscribe(
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h
index 4958f90..f0b75fd 100644
--- a/chrome/browser/push_messaging/push_messaging_service_impl.h
+++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -137,7 +137,7 @@
   void SubscribeEnd(
       const content::PushMessagingService::RegisterCallback& callback,
       const std::string& subscription_id,
-      const std::vector<uint8_t>& curve25519dh,
+      const std::vector<uint8_t>& p256dh,
       content::PushRegistrationStatus status);
 
   void SubscribeEndWithError(
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 0e637d7..12d8b73 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/download/download_stats.h"
 #include "chrome/browser/extensions/devtools_util.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/media/router/media_router_dialog_controller.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
@@ -53,6 +54,7 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/content_restriction.h"
@@ -74,6 +76,7 @@
 #include "components/translate/core/browser/translate_prefs.h"
 #include "components/url_formatter/url_formatter.h"
 #include "components/user_prefs/user_prefs.h"
+#include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/download_save_info.h"
@@ -239,9 +242,10 @@
     {65, -1, IDC_WRITING_DIRECTION_RTL},
     {66, -1, IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE},
     {67, -1, IDC_CONTENT_CONTEXT_FORCESAVEPASSWORD},
+    {68, -1, IDC_ROUTE_MEDIA},
     // Add new items here and use |enum_id| from the next line.
     // Also, add new items to RenderViewContextMenuItem enum in histograms.xml.
-    {68, -1, 0},  // Must be the last. Increment |enum_id| when new IDC
+    {69, -1, 0},  // Must be the last. Increment |enum_id| when new IDC
                   // was added.
 };
 
@@ -863,6 +867,7 @@
                                   IDS_CONTENT_CONTEXT_SAVEAUDIOAS);
   menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION,
                                   IDS_CONTENT_CONTEXT_COPYAUDIOLOCATION);
+  AppendMediaRouterItem();
 }
 
 void RenderViewContextMenu::AppendCanvasItems() {
@@ -880,6 +885,7 @@
                                   IDS_CONTENT_CONTEXT_SAVEVIDEOAS);
   menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_COPYAVLOCATION,
                                   IDS_CONTENT_CONTEXT_COPYVIDEOLOCATION);
+  AppendMediaRouterItem();
 }
 
 void RenderViewContextMenu::AppendPluginItems() {
@@ -908,6 +914,7 @@
   menu_model_.AddItemWithStringId(IDC_SAVE_PAGE,
                                   IDS_CONTENT_CONTEXT_SAVEPAGEAS);
   menu_model_.AddItemWithStringId(IDC_PRINT, IDS_CONTENT_CONTEXT_PRINT);
+  AppendMediaRouterItem();
 
   if (TranslateService::IsTranslatableURL(params_.page_url)) {
     std::string locale = g_browser_process->GetApplicationLocale();
@@ -935,6 +942,12 @@
   }
 }
 
+void RenderViewContextMenu::AppendMediaRouterItem() {
+  if (switches::MediaRouterEnabled() && !browser_context_->IsOffTheRecord())
+    menu_model_.AddItemWithStringId(IDC_ROUTE_MEDIA,
+                                    IDS_MEDIA_ROUTER_MENU_ITEM_TITLE);
+}
+
 void RenderViewContextMenu::AppendRotationItems() {
   if (params_.media_flags & WebContextMenuData::MediaCanRotate) {
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
@@ -1387,6 +1400,26 @@
     case IDC_CONTENT_CONTEXT_FORCESAVEPASSWORD:
       return true;
 
+    case IDC_ROUTE_MEDIA: {
+      DCHECK(switches::MediaRouterEnabled());
+
+      // Disable the command if there is an active modal dialog.
+      Browser* browser =
+          chrome::FindBrowserWithWebContents(source_web_contents_);
+      if (!browser || browser->profile()->IsOffTheRecord())
+        return false;
+
+      WebContents* web_contents =
+          browser->tab_strip_model()->GetActiveWebContents();
+      if (!web_contents)
+        return false;
+
+      const web_modal::WebContentsModalDialogManager* manager =
+          web_modal::WebContentsModalDialogManager::FromWebContents(
+              web_contents);
+      return !manager || !manager->IsDialogActive();
+    }
+
     default:
       NOTREACHED();
       return false;
@@ -1661,6 +1694,24 @@
       break;
     }
 
+    case IDC_ROUTE_MEDIA: {
+      DCHECK(switches::MediaRouterEnabled());
+
+      Browser* browser =
+          chrome::FindBrowserWithWebContents(source_web_contents_);
+      DCHECK(browser && !browser->profile()->IsOffTheRecord());
+
+      media_router::MediaRouterDialogController* dialog_controller =
+          media_router::MediaRouterDialogController::GetOrCreateForWebContents(
+              source_web_contents_);
+
+      if (!dialog_controller)
+        return;
+
+      dialog_controller->ShowMediaRouterDialog();
+      break;
+    }
+
     case IDC_VIEW_SOURCE:
       embedder_web_contents_->ViewSource();
       break;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index adbb51594..e198d4ff 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -123,6 +123,7 @@
   void AppendPageItems();
   void AppendCopyItem();
   void AppendPrintItem();
+  void AppendMediaRouterItem();
   void AppendRotationItems();
   void AppendEditableItems();
   void AppendLanguageSettings();
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index ee2f6f7..ee0d4e58 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -21,6 +21,7 @@
 #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/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/search_engines/template_url_data.h"
@@ -478,7 +479,7 @@
     TemplateURLService* model =
         TemplateURLServiceFactory::GetForProfile(browser()->profile());
     ASSERT_TRUE(model);
-    ui_test_utils::WaitForTemplateURLServiceToLoad(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
     ASSERT_TRUE(model->loaded());
 
     TemplateURLData data;
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index aa4705e..b28332e 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -339,25 +339,8 @@
       resource_context);
 
 #if defined(OS_ANDROID)
-  // TODO(davidben): This is insufficient to integrate with prerender properly.
-  // https://crbug.com/370595
-  if (!is_prerendering) {
-    if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
-      throttles->push_back(
-          InterceptNavigationDelegate::CreateThrottleFor(request));
-    } else {
-      InterceptNavigationDelegate::UpdateUserGestureCarryoverInfo(request);
-    }
-  }
-#else
-  if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
-    // Redirect some navigations to apps that have registered matching URL
-    // handlers ('url_handlers' in the manifest).
-    content::ResourceThrottle* url_to_app_throttle =
-        AppUrlRedirector::MaybeCreateThrottleFor(request, io_data);
-    if (url_to_app_throttle)
-      throttles->push_back(url_to_app_throttle);
-  }
+  if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME)
+    InterceptNavigationDelegate::UpdateUserGestureCarryoverInfo(request);
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
index 4d26872..70d4c926 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -658,6 +658,7 @@
    */
   isWhitelistedForCompat_: function(url) {
     return url.indexOf('chrome://md-settings') != -1 ||
+          url.indexOf('chrome://downloads') != -1 ||
           url.indexOf('chrome://oobe/login') != -1 ||
           url.indexOf(
               'https://accounts.google.com/embedded/setup/chromeos') === 0 ||
diff --git a/chrome/browser/resources/chromeos/login/header_bar.js b/chrome/browser/resources/chromeos/login/header_bar.js
index 306f99ef0..44a5e1c 100644
--- a/chrome/browser/resources/chromeos/login/header_bar.js
+++ b/chrome/browser/resources/chromeos/login/header_bar.js
@@ -21,9 +21,6 @@
     // Whether guest button should be shown when header bar is in normal mode.
     showGuest_: false,
 
-    // Whether new Gaia flow is active.
-    isNewGaiaFlow_: false,
-
     // Whether the reboot button should be shown the when header bar is in
     // normal mode.
     showReboot_: false,
@@ -238,11 +235,6 @@
       this.updateUI_();
     },
 
-    set newGaiaFlow(value) {
-      this.isNewGaiaFlow_ = value;
-      this.updateUI_();
-    },
-
     set showCreateSupervisedButton(value) {
       this.showCreateSupervised_ = value;
       this.updateUI_();
@@ -313,8 +305,12 @@
      */
     updateUI_: function() {
       var gaiaIsActive = (this.signinUIState_ == SIGNIN_UI_STATE.GAIA_SIGNIN);
+      var gaiaIsActiveWithBackButton =
+          gaiaIsActive && !$('back-button-item').hidden;
       var enrollmentIsActive =
           (this.signinUIState_ == SIGNIN_UI_STATE.ENROLLMENT);
+      var enrollmentIsActiveWithBackButton =
+          enrollmentIsActive && !$('oauth-enroll-back-button').hidden;
       var accountPickerIsActive =
           (this.signinUIState_ == SIGNIN_UI_STATE.ACCOUNT_PICKER);
       var supervisedUserCreationDialogIsActive =
@@ -332,45 +328,39 @@
           (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING);
       var isLockScreen =
           (Oobe.getInstance().displayType == DISPLAY_TYPE.LOCK);
-      var isNewGaiaScreenWithBackButton =
-           gaiaIsActive &&
-           this.isNewGaiaFlow_ &&
-           !($('back-button-item').hidden);
-      var supervisedUserCreationDialogIsActiveAndNotIntro =
-          supervisedUserCreationDialogIsActive &&
-          $('supervised-user-creation').currentPage_ != 'intro';
       var errorScreenIsActive =
           (this.signinUIState_ == SIGNIN_UI_STATE.ERROR);
 
       $('add-user-button').hidden =
-          (!this.isNewGaiaFlow_ && !accountPickerIsActive) ||
-          (this.isNewGaiaFlow_ && gaiaIsActive) ||
+          gaiaIsActive ||
           enrollmentIsActive ||
           isMultiProfilesUI ||
           isLockScreen ||
-          supervisedUserCreationDialogIsActiveAndNotIntro ||
+          supervisedUserCreationDialogIsActive ||
           errorScreenIsActive;
       $('more-settings-header-bar-item').hidden =
           !this.showCreateSupervised_ ||
-          isNewGaiaScreenWithBackButton ||
+          gaiaIsActive ||
           supervisedUserCreationDialogIsActive;
       $('cancel-add-user-button').hidden =
-          ((gaiaIsActive || isPasswordChangedUI || isSamlPasswordConfirm ||
-            errorScreenIsActive) &&
-           this.isNewGaiaFlow_) ||
-          accountPickerIsActive ||
           !this.allowCancel_ ||
+          gaiaIsActive ||
+          isPasswordChangedUI ||
+          isSamlPasswordConfirm ||
+          errorScreenIsActive ||
+          accountPickerIsActive ||
           wrongHWIDWarningIsActive ||
           isMultiProfilesUI ||
           supervisedUserCreationDialogIsActive;
       $('guest-user-header-bar-item').hidden =
-          (gaiaIsActive && !this.isNewGaiaFlow_) ||
-          supervisedUserCreationDialogIsActiveAndNotIntro ||
           !this.showGuest_ ||
+          supervisedUserCreationDialogIsActive ||
           wrongHWIDWarningIsActive ||
           isSamlPasswordConfirm ||
           isMultiProfilesUI ||
-          isNewGaiaScreenWithBackButton;
+          (this.allowCancel_ && gaiaIsActive) ||
+          enrollmentIsActiveWithBackButton ||
+          gaiaIsActiveWithBackButton;
       $('restart-header-bar-item').hidden = !this.showReboot_;
       $('shutdown-header-bar-item').hidden = !this.showShutdown_;
       $('sign-out-user-item').hidden = !isLockScreen;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
index 902e026..8b33b6cb 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
@@ -91,6 +91,7 @@
           (function(e) {
             $('oauth-enroll-back-button').hidden = !e.detail;
             $('oauth-enroll-auth-view').focus();
+            $('login-header-bar').updateUI_();
           }).bind(this));
 
       this.authenticator_.insecureContentBlockedCallback =
diff --git a/chrome/browser/resources/feedback/js/take_screenshot.js b/chrome/browser/resources/feedback/js/take_screenshot.js
index aa3921f..53e4170 100644
--- a/chrome/browser/resources/feedback/js/take_screenshot.js
+++ b/chrome/browser/resources/feedback/js/take_screenshot.js
@@ -22,7 +22,7 @@
       video.pause();
       video.src = '';
 
-      screenshotStream.stop();
+      screenshotStream.getVideoTracks()[0].stop();
       screenshotStream = null;
 
       callback(canvas);
diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js
index 43739f5..6462740 100644
--- a/chrome/browser/resources/gaia_auth_host/authenticator.js
+++ b/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -208,6 +208,7 @@
     this.gapsCookie_ = data.gapsCookie;
     this.gapsCookieSent_ = false;
     this.newGapsCookie_ = null;
+    this.dontResizeNonEmbeddedPages = data.dontResizeNonEmbeddedPages;
 
     this.initialFrameUrl_ = this.constructInitialFrameUrl_(data);
     this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_;
@@ -315,7 +316,12 @@
           }
         }
       }
-      if (!isEmbeddedPage) {
+
+      // In some cases, non-embedded pages should not be resized.  For
+      // example, on desktop when reauthenticating for purposes of unlocking
+      // a profile, resizing would cause a browser window to open in the
+      // system profile, which is not allowed.
+      if (!isEmbeddedPage && !this.dontResizeNonEmbeddedPages) {
         this.dispatchEvent(new CustomEvent('resize', {detail: currentUrl}));
         return;
       }
diff --git a/chrome/browser/resources/md_downloads/item.css b/chrome/browser/resources/md_downloads/item.css
index 89cf64fb..2ce80d8 100644
--- a/chrome/browser/resources/md_downloads/item.css
+++ b/chrome/browser/resources/md_downloads/item.css
@@ -18,7 +18,7 @@
 
 #content {
   background: white;
-  border-radius: 2px;  /* TODO(dbeam): change to paper-card instead. */
+  border-radius: 2px;
   display: flex;
   flex: none;
   margin: 0 auto;
@@ -26,7 +26,7 @@
   width: var(--downloads-item-width);
 }
 
-#content[elevation='1'] {
+#content.is-active {
   box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .05), 0 1px 4px 0 rgba(0, 0, 0, .08),
               0 3px 1px -2px rgba(0, 0, 0, .2);
 }
@@ -139,7 +139,7 @@
 }
 
 .controls {
-  -webkit-margin-start: -8px;
+  -webkit-margin-start: -.57em;
 }
 
 #cancel,
@@ -149,6 +149,10 @@
   color: #5a5a5a;
 }
 
+#show {
+  margin: .7em .57em;
+}
+
 #controlled-by {
   -webkit-margin-start: 8px;
 }
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html
index 73d8db3..f051cfd 100644
--- a/chrome/browser/resources/md_downloads/item.html
+++ b/chrome/browser/resources/md_downloads/item.html
@@ -15,41 +15,38 @@
       <h3 id="date">[[computeDate_(data_.since_string, data_.date_string)]]</h3>
     </template>
 
-    <paper-material id="content" on-dragstart="onDragStart_"
-        elevation$="[[computeElevation_(isActive_)]]"
+    <div id="content" on-dragstart="onDragStart_"
         class$="[[computeClass_(isActive_, isDangerous_, showProgress_)]]">
       <div id="file-icon-wrapper" class="icon-wrapper">
-        <img class="icon" id="file-icon" alt="" hidden$="[[isDangerous_]]">
-        <div class="icon" id="warning" hidden$="[[!isDangerous_]]"></div>
+        <img class="icon" id="file-icon" alt="" hidden="[[isDangerous_]]">
+        <div class="icon" id="warning" hidden="[[!isDangerous_]]"></div>
       </div>
 
       <div id="details">
         <div id="title-area"><!--
           Can't have any line breaks.
-          --><a is="action-link" id="file-link" href$="[[data_.url]]"
+          --><a is="action-link" id="file-link" href="[[data_.url]]"
               on-click="onFileLinkClick_"
-              hidden$="[[!completelyOnDisk_]]">[[data_.file_name]]</a><!--
+              hidden="[[!completelyOnDisk_]]">[[data_.file_name]]</a><!--
           Before #name.
           --><span id="name"
-              hidden$="[[completelyOnDisk_]]">[[data_.file_name]]</span>
+              hidden="[[completelyOnDisk_]]">[[data_.file_name]]</span>
           <span id="tag">[[computeTag_(data_.state, data_.last_reason_text, data_.file_externally_removed)]]</span>
         </div>
 
-        <a id="url" target="_blank" href$="[[data_.url]]">[[data_.url]]</a>
+        <a id="url" target="_blank" href="[[data_.url]]">[[data_.url]]</a>
 
         <div id="description">[[computeDescription_(data_.state, data_.danger_type, data_.file_name, data_.progress_status_text)]]</div>
 
         <template is="dom-if" if="[[showProgress_]]">
           <paper-progress id="progress"
-              indeterminate$="[[isIndeterminate_(data_.percent)]]"
-              value$="[[data_.percent]]"></paper-progress>
+              indeterminate="[[isIndeterminate_(data_.percent)]]"
+              value="[[data_.percent]]"></paper-progress>
         </template>
 
-        <div id="safe" class="controls" hidden$="[[isDangerous_]]">
-          <template is="dom-if" if="[[completelyOnDisk_]]">
-            <paper-button id="show" on-click="onShowClick_"
-                lowercase noink>[[i18n_.show]]</paper-button>
-          </template>
+        <div id="safe" class="controls" hidden="[[isDangerous_]]">
+          <a is="action-link" id="show" i18n-content="controlShowInFolder"
+              on-click="onShowClick_" hidden="[[!completelyOnDisk_]]"></a>
           <template is="dom-if" if="[[data_.retry]]">
             <paper-button id="retry"
                 on-click="onRetryClick_">[[i18n_.retry]]</paper-button>
@@ -98,8 +95,8 @@
       </div>
 
       <div id="incognito" i18n-values="title:inIncognito"
-          hidden$="[[!data_.otr]]"></div>
-    </paper-material>
+          hidden="[[!data_.otr]]"></div>
+    </div>
 
   </template>
   <link rel="import" type="css" href="chrome://resources/css/action_link.css">
diff --git a/chrome/browser/resources/md_downloads/item.js b/chrome/browser/resources/md_downloads/item.js
index 8685478..200dab9 100644
--- a/chrome/browser/resources/md_downloads/item.js
+++ b/chrome/browser/resources/md_downloads/item.js
@@ -59,7 +59,6 @@
             restore: loadTimeData.getString('dangerRestore'),
             retry: loadTimeData.getString('controlRetry'),
             save: loadTimeData.getString('dangerSave'),
-            show: loadTimeData.getString('controlShowInFolder'),
           };
         },
       },
@@ -197,11 +196,6 @@
     },
 
     /** @private */
-    computeElevation_: function() {
-      return this.isActive_ ? 1 : 0;
-    },
-
-    /** @private */
     computeIsActive_: function() {
       return this.data_.state != downloads.States.CANCELLED &&
              this.data_.state != downloads.States.INTERRUPTED &&
diff --git a/chrome/browser/resources/md_downloads/shared_style.css b/chrome/browser/resources/md_downloads/shared_style.css
index 95de687..171fdf1f 100644
--- a/chrome/browser/resources/md_downloads/shared_style.css
+++ b/chrome/browser/resources/md_downloads/shared_style.css
@@ -7,14 +7,7 @@
 }
 
 paper-button {
+  font-weight: 500;
   margin: 0;
   min-width: auto;
 }
-
-paper-button[lowercase] {
-  text-transform: none;
-}
-
-paper-button:not([lowercase]) {
-  font-weight: 500;
-}
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 0aebe71..01c30dc 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -804,7 +804,8 @@
     <p id="accessibility-explanation" class="settings-row">
       <span i18n-content="accessibilityExplanation"></span>
       <a id="accessibility-learn-more" target="_blank"
-         i18n-content="learnMore"></a>
+          i18n-values="href:accessibilityLearnMoreURL"
+          i18n-content="learnMore"></a>
     </p>
     <div class="option-name">
       <div class="checkbox controlled-setting-with-label">
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 34ede62a..1cb1fe3 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -674,7 +674,6 @@
             'settings.accessibility',
             updateAccessibilitySettingsButton);
         $('accessibility-learn-more').onclick = function(unused_event) {
-          window.open(loadTimeData.getString('accessibilityLearnMoreURL'));
           chrome.send('coreOptionsUserMetricsAction',
                       ['Options_AccessibilityLearnMore']);
         };
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css
index 401d4453..e62d706 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css
@@ -65,3 +65,27 @@
 .invisible {
   visibility: hidden;
 }
+
+@media(max-width: 675px) {
+  #bookmarks,
+  #rotate-left {
+    display: none;
+  }
+
+  #pageselector-container {
+    flex: 2;
+  }
+}
+
+@media(max-width: 450px) {
+  #rotate-right {
+    display: none;
+  }
+}
+
+@media(max-width: 400px) {
+  #buttons,
+  #pageselector-container {
+    display: none;
+  }
+}
diff --git a/chrome/browser/resources/pdf/index-material.css b/chrome/browser/resources/pdf/index-material.css
index 1e9df5e..a443bac5 100644
--- a/chrome/browser/resources/pdf/index-material.css
+++ b/chrome/browser/resources/pdf/index-material.css
@@ -30,3 +30,21 @@
   position: absolute;
   z-index: 0;
 }
+
+@media(max-height: 250px) {
+  viewer-pdf-toolbar {
+    display: none;
+  }
+}
+
+@media(max-height: 200px) {
+  viewer-zoom-toolbar {
+    display: none;
+  }
+}
+
+@media(max-width: 300px) {
+  viewer-zoom-toolbar {
+    display: none;
+  }
+}
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js
index f426068f..9e2002c 100644
--- a/chrome/browser/resources/pdf/pdf.js
+++ b/chrome/browser/resources/pdf/pdf.js
@@ -41,12 +41,13 @@
 
 /**
  * Called when navigation happens in the current tab.
+ * @param {boolean} isInTab Indicates if the PDF viewer is displayed in a tab.
  * @param {string} url The url to be opened in the current tab.
  */
-function onNavigateInCurrentTab(url) {
-  // Prefer the tabs API because it can navigate from one file:// URL to
-  // another.
-  if (chrome.tabs)
+function onNavigateInCurrentTab(isInTab, url) {
+  // When the PDFviewer is inside a browser tab, prefer the tabs API because
+  // it can navigate from one file:// URL to another.
+  if (chrome.tabs && isInTab)
     chrome.tabs.update({url: url});
   else
     window.location.href = url;
@@ -95,6 +96,13 @@
 PDFViewer.MATERIAL_TOOLBAR_HEIGHT = 56;
 
 /**
+ * Minimum height for the material toolbar to show (px). Should match the media
+ * query in index-material.css. If the window is smaller than this at load,
+ * leave no space for the toolbar.
+ */
+PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT = 250;
+
+/**
  * The light-gray background color used for print preview.
  */
 PDFViewer.LIGHT_BACKGROUND_COLOR = '0xFFCCCCCC';
@@ -143,8 +151,9 @@
   }
 
   // Create the viewport.
+  var shortWindow = window.innerHeight < PDFViewer.TOOLBAR_WINDOW_MIN_HEIGHT;
   var topToolbarHeight =
-      (this.isMaterial_ && !this.isPrintPreview_) ?
+      (this.isMaterial_ && !this.isPrintPreview_ && !shortWindow) ?
       PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0;
   this.viewport_ = new Viewport(window,
                                 this.sizer_,
@@ -257,9 +266,12 @@
   // Parse open pdf parameters.
   this.paramsParser_ =
       new OpenPDFParamsParser(this.getNamedDestination_.bind(this));
+  var isInTab = this.browserApi_.getStreamInfo().tabId != -1;
   this.navigator_ = new Navigator(this.browserApi_.getStreamInfo().originalUrl,
                                   this.viewport_, this.paramsParser_,
-                                  onNavigateInCurrentTab, onNavigateInNewTab);
+                                  onNavigateInCurrentTab.bind(undefined,
+                                                              isInTab),
+                                  onNavigateInNewTab);
   this.viewportScroller_ =
       new ViewportScroller(this.viewport_, this.plugin_, window);
 
diff --git a/chrome/browser/resources/print_preview/data/app_state.js b/chrome/browser/resources/print_preview/data/app_state.js
index a221f7a..100d848 100644
--- a/chrome/browser/resources/print_preview/data/app_state.js
+++ b/chrome/browser/resources/print_preview/data/app_state.js
@@ -51,6 +51,7 @@
     IS_HEADER_FOOTER_ENABLED: 'isHeaderFooterEnabled',
     IS_LANDSCAPE_ENABLED: 'isLandscapeEnabled',
     IS_COLLATE_ENABLED: 'isCollateEnabled',
+    IS_FIT_TO_PAGE_ENABLED: 'isFitToPageEnabled',
     IS_CSS_BACKGROUND_ENABLED: 'isCssBackgroundEnabled',
     VENDOR_OPTIONS: 'vendorOptions'
   };
diff --git a/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chrome/browser/resources/print_preview/data/print_ticket_store.js
index e063bda..08073585 100644
--- a/chrome/browser/resources/print_preview/data/print_ticket_store.js
+++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js
@@ -166,7 +166,7 @@
      * @private
      */
     this.fitToPage_ = new print_preview.ticket_items.FitToPage(
-        this.documentInfo_, this.destinationStore_);
+        this.appState_, this.documentInfo_, this.destinationStore_);
 
     /**
      * Print CSS backgrounds ticket item.
@@ -380,6 +380,12 @@
             print_preview.AppState.Field.IS_COLLATE_ENABLED)));
       }
       if (this.appState_.hasField(
+          print_preview.AppState.Field.IS_FIT_TO_PAGE_ENABLED)) {
+        this.fitToPage_.updateValue(
+            /** @type {!Object} */(this.appState_.getField(
+            print_preview.AppState.Field.IS_FIT_TO_PAGE_ENABLED)));
+      }
+      if (this.appState_.hasField(
           print_preview.AppState.Field.IS_CSS_BACKGROUND_ENABLED)) {
         this.cssBackground_.updateValue(
             /** @type {!Object} */(this.appState_.getField(
diff --git a/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js b/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
index 1023ce1..fbfe4f2 100644
--- a/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
+++ b/chrome/browser/resources/print_preview/data/ticket_items/fit_to_page.js
@@ -8,6 +8,7 @@
   /**
    * Fit-to-page ticket item whose value is a {@code boolean} that indicates
    * whether to scale the document to fit the page.
+   * @param {!print_preview.AppState} appState App state to persist item value.
    * @param {!print_preview.DocumentInfo} documentInfo Information about the
    *     document to print.
    * @param {!print_preview.DestinationStore} destinationStore Used to determine
@@ -15,11 +16,11 @@
    * @constructor
    * @extends {print_preview.ticket_items.TicketItem}
    */
-  function FitToPage(documentInfo, destinationStore) {
+  function FitToPage(appState, documentInfo, destinationStore) {
     print_preview.ticket_items.TicketItem.call(
         this,
-        null /*appState*/,
-        null /*field*/,
+        appState,
+        print_preview.AppState.Field.IS_FIT_TO_PAGE_ENABLED,
         destinationStore,
         documentInfo);
   };
@@ -42,7 +43,10 @@
 
     /** @override */
     getDefaultValueInternal: function() {
-      return !this.getDocumentInfoInternal().isScalingDisabled;
+      // It's on by default since it is not a document feature, it is rather
+      // a property of the printer, hardware margins limitations. User can
+      // always override it.
+      return true;
     },
 
     /** @override */
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index cac3475..81ff818 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -988,10 +988,8 @@
      * @private
      */
     onPrintPresetOptionsFromDocument_: function(event) {
-      if (event.optionsFromDocument.disableScaling) {
-        this.printTicketStore_.fitToPage.updateValue(null);
+      if (event.optionsFromDocument.disableScaling)
         this.documentInfo_.updateIsScalingDisabled(true);
-      }
 
       if (event.optionsFromDocument.copies > 0 &&
           this.printTicketStore_.copies.isCapabilityAvailable()) {
diff --git a/chrome/browser/resources/print_preview/settings/other_options_settings.js b/chrome/browser/resources/print_preview/settings/other_options_settings.js
index cf77a58..c6b3ad47 100644
--- a/chrome/browser/resources/print_preview/settings/other_options_settings.js
+++ b/chrome/browser/resources/print_preview/settings/other_options_settings.js
@@ -169,7 +169,6 @@
     /** @override */
     hasCollapsibleContent: function() {
       return this.headerFooterTicketItem_.isCapabilityAvailable() ||
-             this.fitToPageTicketItem_.isCapabilityAvailable() ||
              this.cssBackgroundTicketItem_.isCapabilityAvailable() ||
              this.selectionOnlyTicketItem_.isCapabilityAvailable();
     },
@@ -290,8 +289,7 @@
                      this.headerFooterTicketItem_.isCapabilityAvailable() &&
                      !this.collapseContent);
         setIsVisible(this.fitToPageContainer_,
-                     this.fitToPageTicketItem_.isCapabilityAvailable() &&
-                     !this.collapseContent);
+                     this.fitToPageTicketItem_.isCapabilityAvailable());
         setIsVisible(this.duplexContainer_,
                      this.duplexTicketItem_.isCapabilityAvailable());
         setIsVisible(this.cssBackgroundContainer_,
@@ -308,6 +306,7 @@
     isSectionVisibleInternal: function() {
       if (this.collapseContent) {
         return this.distillPageTicketItem_.isCapabilityAvailable() ||
+               this.fitToPageTicketItem_.isCapabilityAvailable() ||
                this.duplexTicketItem_.isCapabilityAvailable();
       }
 
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html
index 8f70553..9f8d894 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -1,17 +1,15 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://md-settings/checkbox/checkbox.html">
 
 <dom-module id="cr-settings-a11y-page">
-  <link rel="import" type="css"
-      href="chrome://md-settings/settings_page/settings_page.css">
+  <link rel="import" type="css" href="chrome://md-settings/settings_page/settings_page.css">
   <link rel="import" type="css" href="a11y_page.css">
   <template>
-    <div class="more-a11y-link">
-      <a href="https://chrome.google.com/webstore/category/collection/accessibility"
-          target="_blank" i18n-content="moreFeaturesLink"></a>
-    </div>
+    <span i18n-content="a11yExplanation"></span>
+    <a i18n-values="href:a11yLearnMoreUrl" i18n-content="learnMore"
+        target="_blank"></a>
 
-<if expr="chromeos">
     <cr-settings-checkbox i18n-values="label:optionsInMenuLabel"
         pref="{{prefs.settings.a11y.enable_menu}}">
     </cr-settings-checkbox>
@@ -59,7 +57,11 @@
     <cr-settings-checkbox pref="{{prefs.settings.a11y.virtual_keyboard}}"
         i18n-values="label:onScreenKeyboardLabel">
     </cr-settings-checkbox>
-</if>
+
+    <div class="button-strip">
+      <paper-button i18n-content="moreFeaturesLink"
+          on-tap="onMoreFeaturesTap_"></paper-button>
+    </div>
   </template>
   <script src="a11y_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.js b/chrome/browser/resources/settings/a11y_page/a11y_page.js
index 7696f47..f7286ad 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.js
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.js
@@ -29,4 +29,10 @@
       notify: true,
     },
   },
+
+  /** @private */
+  onMoreFeaturesTap_: function() {
+    window.open(
+        'https://chrome.google.com/webstore/category/collection/accessibility');
+  },
 });
diff --git a/chrome/browser/resources/settings/advanced_page/advanced_page.html b/chrome/browser/resources/settings/advanced_page/advanced_page.html
index 76e6cb20..f5df256 100644
--- a/chrome/browser/resources/settings/advanced_page/advanced_page.html
+++ b/chrome/browser/resources/settings/advanced_page/advanced_page.html
@@ -1,5 +1,4 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
-<link rel="import" href="chrome://md-settings/a11y_page/a11y_page.html">
 <link rel="import" href="chrome://md-settings/downloads_page/downloads_page.html">
 <link rel="import" href="chrome://md-settings/languages_page/languages_page.html">
 <link rel="import" href="chrome://md-settings/location_page/location_page.html">
@@ -8,6 +7,7 @@
 <link rel="import" href="chrome://md-settings/sync_page/sync_page.html">
 
 <if expr="chromeos">
+<link rel="import" href="chrome://md-settings/a11y_page/a11y_page.html">
 <link rel="import" href="chrome://md-settings/date_time_page/date_time_page.html">
 </if>
 
@@ -15,54 +15,51 @@
   <link rel="import" type="css" href="advanced_page.css">
   <template>
 <if expr="chromeos">
-    <cr-settings-section i18n-values="page-title:dateTimePageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:dateTimePageTitle"
         current-route="[[currentRoute]]" section="dateTime">
       <cr-settings-date-time-page prefs="{{prefs}}">
       </cr-settings-date-time-page>
-    </cr-settings-section>
+    </settings-section>
 </if>
-    <cr-settings-section i18n-values="page-title:siteSettingsLocation"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:siteSettingsLocation"
         current-route="[[currentRoute]]" section="location">
       <cr-settings-location-page prefs="{{prefs}}">
       </cr-settings-location-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:privacyPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:privacyPageTitle"
         current-route="[[currentRoute]]" section="privacy">
       <cr-settings-privacy-page prefs="{{prefs}}"
         current-route="{{currentRoute}}">
       </cr-settings-privacy-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:languagesPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:languagesPageTitle"
         current-route="[[currentRoute]]" section="languages">
       <cr-settings-languages-page prefs="{{prefs}}"
           current-route="{{currentRoute}}">
       </cr-settings-languages-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:downloadsPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:downloadsPageTitle"
         current-route="[[currentRoute]]" section="downloads">
       <cr-settings-downloads-page prefs="{{prefs}}">
       </cr-settings-downloads-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:a11yPageTitle"
-        expand-container="[[expandContainer]]"
+<if expr="chromeos">
+    <!-- TODO(dbeam): find somewhere to stuff "Add more accessibility features"
+         on desktop. -->
+    <settings-section i18n-values="page-title:a11yPageTitle"
         current-route="[[currentRoute]]" section="a11y">
       <cr-settings-a11y-page prefs="{{prefs}}"></cr-settings-a11y-page>
-    </cr-settings-section>
+    </settings-section>
+</if>
 
-    <cr-settings-section i18n-values="page-title:syncPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:syncPageTitle"
         current-route="[[currentRoute]]" section="sync">
       <cr-settings-sync-page></cr-settings-sync-page>
-    </cr-settings-section>
+    </settings-section>
   </template>
   <script src="advanced_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index 0bf2219..d104122 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -14,41 +14,36 @@
   <link rel="import" type="css" href="basic_page.css">
   <template>
 <if expr="chromeos">
-    <cr-settings-section i18n-values="page-title:internetPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:internetPageTitle"
         current-route="[[currentRoute]]" section="internet">
       <cr-settings-internet-page current-route="{{currentRoute}}">
       </cr-settings-internet-page>
-    </cr-settings-section>
+    </settings-section>
 </if>
-    <cr-settings-section i18n-values="page-title:appearancePageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:appearancePageTitle"
         current-route="[[currentRoute]]" section="appearance">
       <cr-settings-appearance-page prefs="{{prefs}}">
       </cr-settings-appearance-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:onStartup"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:onStartup"
         current-route="[[currentRoute]]" section="on-startup">
       <cr-settings-on-startup-page
           prefs="{{prefs}}" current-route="{{currentRoute}}">
       </cr-settings-on-startup-page>
-    </cr-settings-section>
+    </settings-section>
 
-    <cr-settings-section i18n-values="page-title:searchPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:searchPageTitle"
         current-route="[[currentRoute]]" section="search">
       <cr-settings-search-page current-route="{{currentRoute}}">
       </cr-settings-search-page>
-    </cr-settings-section>
+    </settings-section>
 
 <if expr="chromeos">
-    <cr-settings-section i18n-values="page-title:usersPageTitle"
-        expand-container="[[expandContainer]]"
+    <settings-section i18n-values="page-title:usersPageTitle"
         current-route="[[currentRoute]]" section="users">
       <cr-settings-users-page prefs="{{prefs}}"></cr-settings-users-page>
-    </cr-settings-section>
+    </settings-section>
 </if>
   </template>
   <script src="basic_page.js"></script>
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index bc7d19a..21e95a57 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -22,20 +22,20 @@
     <div class="layout vertical">
       <!-- Title section: Icon + name + connection state. -->
       <div id="titleDiv" class="layout horizontal center">
-        <cr-network-icon id="networkIcon" network-state="[[networkState]]">
+        <cr-network-icon id="networkIcon" network-state="[[networkProperties]]">
         </cr-network-icon>
-        <span id="networkName">[[getStateName_(networkState)]]</span>
+        <span id="networkName">[[getStateName_(networkProperties)]]</span>
         <span id="networkState"
-            connected$="[[isConnectedState_(networkState)]]"
-            >[[getStateText_(networkState)]]</span>
+            connected$="[[isConnectedState_(networkProperties)]]"
+            >[[getStateText_(networkProperties)]]</span>
       </div>
 
       <div id="outerDiv" class="layout vertical">
         <!-- For Cellular, show SIM info first. -->
         <div id="simInfoDiv" class="layout vertical">
           <network-siminfo editable
-              hidden$="[[!showCellularSim_(networkState)]]"
-              network-state="[[networkState]]"
+              hidden$="[[!showCellularSim_(networkProperties)]]"
+              network-properties="[[networkProperties]]"
               on-siminfo-change="onNetworkPropertyChange_">
           </network-siminfo>
         </div>
@@ -46,11 +46,11 @@
             <span>IP Address:</span>
             <span>[[IPAddress]]</span>
           </div>
-          <span hidden$="[[!showShared_(networkState)]]">
+          <span hidden$="[[!showShared_(networkProperties)]]">
             This network is shared with other users.
           </span>
           <div class="layout horizontal center"
-              hidden$="[[!showPreferNetwork_(networkState)]]">
+              hidden$="[[!showPreferNetwork_(networkProperties)]]">
             <paper-icon-button id="preferButton"
                 toggles active="{{preferNetwork}}"
                 icon="[[getPreferredIcon_(preferNetwork)]]">
@@ -58,38 +58,38 @@
             <span>Prefer this network</span>
           </div>
           <paper-checkbox checked="{{autoConnect}}"
-              hidden$="[[!showAutoConnect_(networkState)]]">
+              hidden$="[[!showAutoConnect_(networkProperties)]]">
             Automatically connect to this network
           </paper-checkbox>
 
           <!-- Properties to always show if present. -->
           <network-property-list
-              fields="[[getInfoFields_(networkState)]]"
-              network-state="[[networkState]]">
+              fields="[[getInfoFields_(networkProperties)]]"
+              property-dict="[[networkProperties]]">
           </network-property-list>
         </div>
 
         <!-- Button row: Advanced + Disconnect | Connect. -->
         <div class="layout horizontal center">
           <paper-button toggles noink active="{{advancedExpanded}}"
-              hidden$="[[!hasAdvancedOrDeviceFields_(networkState)]]">
+              hidden$="[[!hasAdvancedOrDeviceFields_(networkProperties)]]">
             Advanced
           </paper-button>
           <span class="flex"></span>
-          <paper-button hidden$="[[!showViewAccount_(networkState)]]"
+          <paper-button hidden$="[[!showViewAccount_(networkProperties)]]"
               on-tap="onViewAccountClicked_">
             View Account
           </paper-button>
-          <paper-button hidden$="[[!showActivate_(networkState)]]"
+          <paper-button hidden$="[[!showActivate_(networkProperties)]]"
               on-tap="onActivateClicked_">
             Activate
           </paper-button>
-          <paper-button hidden$="[[!showConnect_(networkState)]]"
-              disabled="[[!enableConnect_(networkState)]]"
+          <paper-button hidden$="[[!showConnect_(networkProperties)]]"
+              disabled="[[!enableConnect_(networkProperties)]]"
               on-tap="onConnectClicked_">
             Connect
           </paper-button>
-          <paper-button hidden$="[[!showDisconnect_(networkState)]]"
+          <paper-button hidden$="[[!showDisconnect_(networkProperties)]]"
               on-tap="onDisconnectClicked_">
             Disconnect
           </paper-button>
@@ -97,36 +97,36 @@
 
         <!-- Advanced section -->
         <div id="advancedDiv" class="layout vertical"
-            hidden$="[[!hasAdvancedOrDeviceFields_(networkState)]]">
+            hidden$="[[!hasAdvancedOrDeviceFields_(networkProperties)]]">
           <cr-collapse opened="[[advancedExpanded]]">
             <!-- Advanced properties -->
             <div id="advancedInfoDiv" class="layout vertical">
               <network-property-list
-                  fields="[[getAdvancedFields_(networkState)]]"
-                  network-state="[[networkState]]">
+                  fields="[[getAdvancedFields_(networkProperties)]]"
+                  property-dict="[[networkProperties]]">
               </network-property-list>
             </div>
 
             <!-- Network (APN, address, nameservers) -->
             <div id="addressDiv" class="layout vertical"
-                hidden$="[[!hasNetworkSection_(networkState)]]">
+                hidden$="[[!hasNetworkSection_(networkProperties)]]">
               <paper-button toggles noink active="{{addressExpanded}}">
                 Network
               </paper-button>
               <cr-collapse opened="[[addressExpanded]]">
                 <div class="layout vertical flex">
                   <network-apnlist editable
-                      hidden$="[[!isType_(networkState, NetworkType.CELLULAR)]]"
-                      network-state="[[networkState]]"
-                      apnlist="[[networkState.Cellular.APNList]]"
+                      hidden$="[[!isType_(networkProperties, NetworkType.CELLULAR)]]"
+                      network-properties="[[networkProperties]]"
+                      apnlist="[[networkProperties.Cellular.APNList]]"
                       on-apn-change="onNetworkPropertyChange_">
                   </network-apnlist>
                   <network-ip-config editable
-                      network-state="[[networkState]]"
+                      network-properties="[[networkProperties]]"
                       on-ip-change="onIPConfigChange_">
                   </network-ip-config>
                   <network-nameservers editable
-                      network-state="[[networkState]]"
+                      network-properties="[[networkProperties]]"
                       on-nameservers-change="onIPConfigChange_">
                   </network-nameservers>
                 </div>
@@ -135,14 +135,14 @@
 
             <!-- Proxy -->
             <div class="layout vertical"
-                hidden$="[[!hasNetworkSection_(networkState)]]">
+                hidden$="[[!hasNetworkSection_(networkProperties)]]">
               <paper-button toggles noink active="{{proxyExpanded}}">
                 Proxy
               </paper-button>
               <cr-collapse opened="[[proxyExpanded]]">
                 <div id="proxyDiv" class="layout vertical flex">
                   <network-proxy editable
-                      network-state="[[networkState]]"
+                      network-properties="[[networkProperties]]"
                       on-proxy-change="onProxyChange_">
                   </network-proxy>
                 </div>
@@ -151,14 +151,14 @@
 
             <!-- Device properties -->
             <div class="layout vertical"
-                hidden$="[[!hasDeviceFields_(networkState)]]">
+                hidden$="[[!hasDeviceFields_(networkProperties)]]">
               <paper-button toggles noink active="{{deviceExpanded}}">
                 Device
               </paper-button>
               <cr-collapse opened="[[deviceExpanded]]">
                 <network-property-list
-                    fields="[[getDeviceFields_(networkState)]]"
-                    network-state="[[networkState]]">
+                    fields="[[getDeviceFields_(networkProperties)]]"
+                    property-dict="[[networkProperties]]">
                 </network-property-list>
                 <!-- TODO(stevenjb): Cellular SIM -->
               </cr-collapse>
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index a59a4d7..f2bb1bb16 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -29,17 +29,12 @@
     },
 
     /**
-     * The current state for the network matching |guid|. TODO(stevenjb): Use
-     * chrome.networkingProperties.NetworkPoperties once it is defined. This
-     * will be a super-set of NetworkStateProperties. Currently properties that
-     * are not defined in NetworkStateProperties are accessed through
-     * CrOnc.getActive* which uses [] to access the property, which avoids any
-     * type checking (see CrOnc.getProperty for more info).
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The current properties for the network matching |guid|.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /**
@@ -115,25 +110,27 @@
   },
 
   /**
-   * Polymer networkState changed method.
+   * Polymer networkProperties changed method.
    */
-  networkStateChanged_: function() {
-    if (!this.networkState)
+  networkPropertiesChanged_: function() {
+    if (!this.networkProperties)
       return;
 
     // Update autoConnect if it has changed. Default value is false.
     var autoConnect = /** @type {boolean} */(
-        CrOnc.getActiveTypeValue(this.networkState, 'AutoConnect')) || false;
+        CrOnc.getActiveTypeValue(this.networkProperties, 'AutoConnect')) ||
+            false;
     if (autoConnect != this.autoConnect)
       this.autoConnect = autoConnect;
 
     // Update preferNetwork if it has changed. Default value is false.
-    var preferNetwork = this.networkState.Priority > 0;
+    var preferNetwork = this.networkProperties.Priority > 0;
     if (preferNetwork != this.preferNetwork)
       this.preferNetwork = preferNetwork;
 
     // Set the IPAddress property to the IPV4 Address.
-    var ipv4 = CrOnc.getIPConfigForType(this.networkState, CrOnc.IPType.IPV4);
+    var ipv4 =
+        CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
     this.IPAddress = (ipv4 && ipv4.IPAddress) || '';
   },
 
@@ -141,7 +138,7 @@
    * Polymer autoConnect changed method.
    */
   autoConnectChanged_: function() {
-    if (!this.networkState || !this.guid)
+    if (!this.networkProperties || !this.guid)
       return;
     var onc = this.getEmptyNetworkProperties_();
     CrOnc.setTypeProperty(onc, 'AutoConnect', this.autoConnect);
@@ -152,7 +149,7 @@
    * Polymer preferNetwork changed method.
    */
   preferNetworkChanged_: function() {
-    if (!this.networkState || !this.guid)
+    if (!this.networkProperties || !this.guid)
       return;
     var onc = this.getEmptyNetworkProperties_();
     onc.Priority = this.preferNetwork ? 1 : 0;
@@ -182,14 +179,14 @@
 
   /**
    * networkingPrivate.getProperties callback.
-   * @param {Object} properties The network properties.
+   * @param {CrOnc.NetworkProperties} properties The network properties.
    * @private
    */
   getPropertiesCallback_: function(properties) {
-    this.networkState = /** @type {CrOnc.NetworkStateProperties}*/(properties);
+    this.networkProperties = properties;
     if (!properties) {
-      // If state becomes null (i.e. the network is no longer visible), close
-      // the page.
+      // If |properties| becomes null (i.e. the network is no longer visible),
+      // close the page.
       this.fire('close');
     }
   },
@@ -218,91 +215,93 @@
    * @private
    */
   getEmptyNetworkProperties_: function() {
-    return {Type: this.networkState.Type};
+    return {Type: this.networkProperties.Type};
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {string} The text to display for the network name.
    * @private
    */
-  getStateName_: function(state) {
-    return (state && state.Name) || '';
+  getStateName_: function(properties) {
+    return (properties && properties.Name) || '';
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {string} The text to display for the network connection state.
    * @private
    */
-  getStateText_: function(state) {
+  getStateText_: function(properties) {
     // TODO(stevenjb): Localize.
-    return (state && state.ConnectionState) || '';
+    return (properties && properties.ConnectionState) || '';
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
-   * @return {boolean} True if the state is connected.
+   * @param {!CrOnc.NetworkProperties} properties
+   * @return {boolean} True if the network is connected.
    * @private
    */
-  isConnectedState_: function(state) {
-    return !!state && state.ConnectionState == CrOnc.ConnectionState.CONNECTED;
+  isConnectedState_: function(properties) {
+    return !!properties && properties.ConnectionState ==
+        CrOnc.ConnectionState.CONNECTED;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} Whether or not to show the 'Connect' button.
    * @private
    */
-  showConnect_: function(state) {
-    return !!state && state.Type != CrOnc.Type.ETHERNET &&
-           state.ConnectionState == CrOnc.ConnectionState.NOT_CONNECTED;
+  showConnect_: function(properties) {
+    return !!properties && properties.Type != CrOnc.Type.ETHERNET &&
+           properties.ConnectionState == CrOnc.ConnectionState.NOT_CONNECTED;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} Whether or not to show the 'Activate' button.
    * @private
    */
-  showActivate_: function(state) {
-    if (!state || state.Type != CrOnc.Type.CELLULAR)
+  showActivate_: function(properties) {
+    if (!properties || properties.Type != CrOnc.Type.CELLULAR)
       return false;
-    var activation = state.Cellular.ActivationState;
+    var activation = properties.Cellular.ActivationState;
     return activation == CrOnc.ActivationState.NOT_ACTIVATED ||
            activation == CrOnc.ActivationState.PARTIALLY_ACTIVATED;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} Whether or not to show the 'View Account' button.
    * @private
    */
-  showViewAccount_: function(state) {
+  showViewAccount_: function(properties) {
     // Show either the 'Activate' or the 'View Account' button.
-    if (this.showActivate_(state))
+    if (this.showActivate_(properties))
       return false;
 
-    if (!state || state.Type != CrOnc.Type.CELLULAR || !state.Cellular)
+    if (!properties || properties.Type != CrOnc.Type.CELLULAR ||
+        !properties.Cellular) {
       return false;
+    }
 
     // Only show if online payment URL is provided or the carrier is Verizon.
-    var carrier = CrOnc.getActiveValue(state, 'Cellular.Carrier');
+    var carrier = CrOnc.getActiveValue(properties.Cellular.Carrier);
     if (carrier != CARRIER_VERIZON) {
-      var paymentPortal = /** @type {CrOnc.PaymentPortal|undefined} */(
-          this.get('state.Cellular.PaymentPortal'));
+      var paymentPortal = properties.Cellular.PaymentPortal;
       if (!paymentPortal || !paymentPortal.Url)
         return false;
     }
 
     // Only show for connected networks or LTE networks with a valid MDN.
-    if (!this.isConnectedState_(state)) {
+    if (!this.isConnectedState_(properties)) {
       var technology = /** @type {CrOnc.NetworkTechnology|undefined} */(
-          CrOnc.getActiveValue(state, 'Cellular.NetworkTechnology'));
+          CrOnc.getActiveValue(properties.Cellular.NetworkTechnology));
       if (technology != CrOnc.NetworkTechnology.LTE &&
           technology != CrOnc.NetworkTechnology.LTE_ADVANCED) {
         return false;
       }
-      if (!CrOnc.getActiveValue(state, 'Cellular.MDN'))
+      if (!CrOnc.getActiveValue(properties.Cellular.MDN))
         return false;
     }
 
@@ -313,23 +312,23 @@
    * @return {boolean} Whether or not to enable the network connect button.
    * @private
    */
-  enableConnect_: function(state) {
-    if (!state || !this.showConnect_(state))
+  enableConnect_: function(properties) {
+    if (!properties || !this.showConnect_(properties))
       return false;
-    if (state.Type == CrOnc.Type.CELLULAR && CrOnc.isSimLocked(state))
+    if (properties.Type == CrOnc.Type.CELLULAR && CrOnc.isSimLocked(properties))
       return false;
     // TODO(stevenjb): For VPN, check connected state of any network.
     return true;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} Whether or not to show the 'Disconnect' button.
    * @private
    */
-  showDisconnect_: function(state) {
-    return !!state && state.Type != CrOnc.Type.ETHERNET &&
-           state.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED;
+  showDisconnect_: function(properties) {
+    return !!properties && properties.Type != CrOnc.Type.ETHERNET &&
+           properties.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED;
   },
 
   /**
@@ -371,7 +370,7 @@
    * @private
    */
   onNetworkPropertyChange_: function(event) {
-    if (!this.networkState)
+    if (!this.networkProperties)
       return;
     var field = event.detail.field;
     var value = event.detail.value;
@@ -396,7 +395,7 @@
    * @private
    */
   onIPConfigChange_: function(event) {
-    if (!this.networkState)
+    if (!this.networkProperties)
       return;
     var field = event.detail.field;
     var value = event.detail.value;
@@ -405,7 +404,7 @@
     var onc = this.getEmptyNetworkProperties_();
     var ipConfigType =
         /** @type {chrome.networkingPrivate.IPConfigType|undefined} */(
-            CrOnc.getActiveValue(this.networkState, 'IPAddressConfigType'));
+            CrOnc.getActiveValue(this.networkProperties.IPAddressConfigType));
     if (field == 'IPAddressConfigType') {
       var newIpConfigType =
           /** @type {chrome.networkingPrivate.IPConfigType} */(value);
@@ -415,7 +414,8 @@
     } else if (field == 'NameServersConfigType') {
       var nsConfigType =
           /** @type {chrome.networkingPrivate.IPConfigType|undefined} */(
-              CrOnc.getActiveValue(this.networkState, 'NameServersConfigType'));
+              CrOnc.getActiveValue(
+                  this.networkProperties.NameServersConfigType));
       var newNsConfigType =
           /** @type {chrome.networkingPrivate.IPConfigType} */(value);
       if (newNsConfigType == nsConfigType)
@@ -423,8 +423,7 @@
       onc.NameServersConfigType = newNsConfigType;
     } else if (field == 'StaticIPConfig') {
       if (ipConfigType == CrOnc.IPConfigType.STATIC) {
-        var staticIpConfig = /** @type {CrOnc.IPConfigProperties|undefined} */(
-            this.get('networkState.StaticIPConfig'));
+        var staticIpConfig = this.networkProperties.StaticIPConfig;
         if (staticIpConfig &&
             this.allPropertiesMatch_(staticIpConfig,
                                      /** @type {!Object} */(value))) {
@@ -458,9 +457,9 @@
       return;
     }
     // setValidStaticIPConfig will fill in any other properties from
-    // networkState. This is necessary since we update IP Address and
+    // networkProperties. This is necessary since we update IP Address and
     // NameServers independently.
-    CrOnc.setValidStaticIPConfig(onc, this.networkState);
+    CrOnc.setValidStaticIPConfig(onc, this.networkProperties);
     this.setNetworkProperties_(onc);
   },
 
@@ -471,7 +470,7 @@
    * @private
    */
   onProxyChange_: function(event) {
-    if (!this.networkState)
+    if (!this.networkProperties)
       return;
     var field = event.detail.field;
     var value = event.detail.value;
@@ -483,34 +482,34 @@
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if the shared message should be shown.
    * @private
    */
-  showShared_: function(state) {
-    return !!state &&
-           (state.Source == 'Device' || state.Source == 'DevicePolicy');
+  showShared_: function(properties) {
+    return !!properties && (properties.Source == 'Device' ||
+                            properties.Source == 'DevicePolicy');
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if the AutoConnect checkbox should be shown.
    * @private
    */
-  showAutoConnect_: function(state) {
-    return !!state && state.Type != CrOnc.Type.ETHERNET &&
-           state.Source != CrOnc.Source.NONE;
+  showAutoConnect_: function(properties) {
+    return !!properties && properties.Type != CrOnc.Type.ETHERNET &&
+           properties.Source != CrOnc.Source.NONE;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if the prefer network checkbox should be shown.
    * @private
    */
-  showPreferNetwork_: function(state) {
+  showPreferNetwork_: function(properties) {
     // TODO(stevenjb): Resolve whether or not we want to allow "preferred" for
-    // state.Type == CrOnc.Type.ETHERNET.
-    return !!state && state.Source != CrOnc.Source.NONE;
+    // properties.Type == CrOnc.Type.ETHERNET.
+    return !!properties && properties.Source != CrOnc.Source.NONE;
   },
 
   /**
@@ -523,76 +522,76 @@
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {!Array<string>} The fields to display in the info section.
    * @private
    */
-  getInfoFields_: function(state) {
+  getInfoFields_: function(properties) {
     /** @type {!Array<string>} */ var fields = [];
-    if (!state)
+    if (!properties)
       return fields;
 
-    if (state.Type == CrOnc.Type.CELLULAR) {
+    if (properties.Type == CrOnc.Type.CELLULAR) {
       fields.push('Cellular.ActivationState',
                   'Cellular.RoamingState',
                   'RestrictedConnectivity',
                   'Cellular.ServingOperator.Name');
     }
-    if (state.Type == CrOnc.Type.VPN) {
+    if (properties.Type == CrOnc.Type.VPN) {
       fields.push('VPN.Host', 'VPN.Type');
-      if (state.VPN.Type == 'OpenVPN')
+      if (properties.VPN.Type == 'OpenVPN')
         fields.push('VPN.OpenVPN.Username');
-      else if (state.VPN.Type == 'L2TP-IPsec')
+      else if (properties.VPN.Type == 'L2TP-IPsec')
         fields.push('VPN.L2TP.Username');
-      else if (state.VPN.Type == 'ThirdPartyVPN')
+      else if (properties.VPN.Type == 'ThirdPartyVPN')
         fields.push('VPN.ThirdPartyVPN.ProviderName');
     }
-    if (state.Type == CrOnc.Type.WI_FI)
+    if (properties.Type == CrOnc.Type.WI_FI)
       fields.push('RestrictedConnectivity');
-    if (state.Type == CrOnc.Type.WI_MAX) {
+    if (properties.Type == CrOnc.Type.WI_MAX) {
       fields.push('RestrictedConnectivity', 'WiMAX.EAP.Identity');
     }
     return fields;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {!Array<string>} The fields to display in the Advanced section.
    * @private
    */
-  getAdvancedFields_: function(state) {
+  getAdvancedFields_: function(properties) {
     /** @type {!Array<string>} */ var fields = [];
-    if (!state)
+    if (!properties)
       return fields;
     fields.push('MacAddress');
-    if (state.Type == CrOnc.Type.CELLULAR) {
+    if (properties.Type == CrOnc.Type.CELLULAR) {
       fields.push('Cellular.Carrier',
                   'Cellular.Family',
                   'Cellular.NetworkTechnology',
                   'Cellular.ServingOperator.Code');
     }
-    if (state.Type == CrOnc.Type.WI_FI) {
+    if (properties.Type == CrOnc.Type.WI_FI) {
       fields.push('WiFi.SSID',
                   'WiFi.BSSID',
                   'WiFi.Security',
                   'WiFi.SignalStrength',
                   'WiFi.Frequency');
     }
-    if (state.Type == CrOnc.Type.WI_MAX)
+    if (properties.Type == CrOnc.Type.WI_MAX)
       fields.push('WiFi.SignalStrength');
     return fields;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {!Array<string>} The fields to display in the device section.
    * @private
    */
-  getDeviceFields_: function(state) {
+  getDeviceFields_: function(properties) {
     /** @type {!Array<string>} */ var fields = [];
-    if (!state)
+    if (!properties)
       return fields;
-    if (state.Type == CrOnc.Type.CELLULAR) {
+    if (properties.Type == CrOnc.Type.CELLULAR) {
       fields.push('Cellular.HomeProvider.Name',
                   'Cellular.HomeProvider.Country',
                   'Cellular.HomeProvider.Code',
@@ -613,53 +612,53 @@
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if there are any advanced fields to display.
    * @private
    */
-  hasAdvancedOrDeviceFields_: function(state) {
-    return this.getAdvancedFields_(state).length > 0 ||
-           this.hasDeviceFields_(state);
+  hasAdvancedOrDeviceFields_: function(properties) {
+    return this.getAdvancedFields_(properties).length > 0 ||
+           this.hasDeviceFields_(properties);
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if there are any device fields to display.
    * @private
    */
-  hasDeviceFields_: function(state) {
-    var fields = this.getDeviceFields_(state);
+  hasDeviceFields_: function(properties) {
+    var fields = this.getDeviceFields_(properties);
     return fields.length > 0;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if the network section should be shown.
    * @private
    */
-  hasNetworkSection_: function(state) {
-    return !!state && state.Type != CrOnc.Type.VPN;
+  hasNetworkSection_: function(properties) {
+    return !!properties && properties.Type != CrOnc.Type.VPN;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @param {string} type The network type.
    * @return {boolean} True if the network type matches 'type'.
    * @private
    */
-  isType_: function(state, type) {
-    return !!state && state.Type == type;
+  isType_: function(properties, type) {
+    return !!properties && properties.Type == type;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!CrOnc.NetworkProperties} properties
    * @return {boolean} True if the Cellular SIM section should be shown.
    * @private
    */
-  showCellularSim_: function(state) {
-    if (!state || state.Type != 'Cellular')
+  showCellularSim_: function(properties) {
+    if (!properties || properties.Type != 'Cellular' || !properties.Cellular)
       return false;
-    return CrOnc.getActiveValue(state, 'Cellular.Family') == 'GSM';
+    return CrOnc.getActiveValue(properties.Cellular.Family) == 'GSM';
   },
 
   /**
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.html b/chrome/browser/resources/settings/internet_page/internet_page.html
index b6b2213..f23d503 100644
--- a/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -11,7 +11,7 @@
   <link rel="import" type="css"
       href="chrome://md-settings/settings_page/settings_page.css">
   <template>
-    <cr-settings-animated-pages id="pages" current-route="{{currentRoute}}"
+    <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="internet">
       <neon-animatable id="">
         <network-summary on-show-detail="onShowDetail_"
@@ -34,7 +34,7 @@
             on-show-detail="onShowDetail_">
         </cr-settings-internet-known-networks-page>
       </neon-animatable>
-    </cr-settings-animated-pages>
+    </settings-animated-pages>
   </template>
   <script src="internet_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/internet_page/network_apnlist.html b/chrome/browser/resources/settings/internet_page/network_apnlist.html
index 332db298..2d53bbe 100644
--- a/chrome/browser/resources/settings/internet_page/network_apnlist.html
+++ b/chrome/browser/resources/settings/internet_page/network_apnlist.html
@@ -19,9 +19,9 @@
         </select>
       </div>
       <div id="otherDiv" class="layout vertical"
-          hidden$="[[!isOtherSelected_(networkState, selectedApn)]]">
+          hidden$="[[!isOtherSelected_(networkProperties, selectedApn)]]">
         <network-property-list
-            fields="[[otherApnFields_]]" network-state="[[otherApn]]"
+            fields="[[otherApnFields_]]" property-dict="[[otherApn]]"
             edit-field-types="[[otherApnEditTypes_]]"
             on-property-change="onOtherApnChange_">
         </network-property-list>
diff --git a/chrome/browser/resources/settings/internet_page/network_apnlist.js b/chrome/browser/resources/settings/internet_page/network_apnlist.js
index 02cdf8e..71a2adf0 100644
--- a/chrome/browser/resources/settings/internet_page/network_apnlist.js
+++ b/chrome/browser/resources/settings/internet_page/network_apnlist.js
@@ -14,12 +14,12 @@
 
   properties: {
     /**
-     * The current state for the network matching |guid|.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The current set of properties for the network matching |guid|.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /**
@@ -81,14 +81,14 @@
   /** @const */ DefaultAccessPointName: 'none',
 
   /**
-   * Polymer networkState changed method.
+   * Polymer networkProperties changed method.
    */
-  networkStateChanged_: function() {
-    if (!this.networkState || !this.networkState.Cellular)
+  networkPropertiesChanged_: function() {
+    if (!this.networkProperties || !this.networkProperties.Cellular)
       return;
 
-    var activeApn = null;
-    var cellular = this.networkState.Cellular;
+    var activeApn;
+    var cellular = this.networkProperties.Cellular;
     if (cellular.APN && cellular.APN.AccessPointName)
       activeApn = cellular.APN;
     else if (cellular.LastGoodAPN && cellular.LastGoodAPN.AccessPointName)
@@ -99,14 +99,15 @@
   /**
    * Sets the list of selectable APNs for the UI. Appends an 'Other' entry
    * (see comments for |otherApn| above).
-   * @param {?CrOnc.APNProperties} activeApn The currently active APN value.
+   * @param {CrOnc.APNProperties|undefined} activeApn The currently active APN
+   *     properties.
    * @private
    */
   setApnSelectList_: function(activeApn) {
-    // Copy the list of APNs from this.networkState.
+    // Copy the list of APNs from this.networkProperties.
     var result = this.getApnList_().slice();
 
-    // Test whether |activeApn| is in the current APN list in this.networkState.
+    // Test whether |activeApn| is in the current APN list in networkProperties.
     var activeApnInList = activeApn && result.some(
         function(a) { return a.AccessPointName == activeApn.AccessPointName; });
 
@@ -137,7 +138,7 @@
   },
 
   /**
-   * @param {?CrOnc.APNProperties=} apnProperties
+   * @param {!CrOnc.APNProperties|undefined=} apnProperties
    * @return {!CrOnc.APNProperties} A new APN object with properties from
    *     |apnProperties| if provided.
    * @private
@@ -151,13 +152,13 @@
 
   /**
    * @return {!Array<!CrOnc.APNProperties>} The list of APN properties in
-   *     |networkState| or an empty list if the property is not set.
+   *     |networkProperties| or an empty list if the property is not set.
    * @private
    */
   getApnList_: function() {
-    var apnList = /** @type {Array<!CrOnc.APNProperties>|undefined} */(
-        this.get('networkState.Cellular.APNList'));
-    return apnList || [];
+    if (!this.networkProperties || !this.networkProperties.Cellular)
+      return [];
+    return this.networkProperties.Cellular.APNList || [];
   },
 
   /**
@@ -181,7 +182,7 @@
     var selectedApn = event.target.value;
     // When selecting 'Other', don't set a change event unless a valid
     // non-default value has been set for Other.
-    if (this.isOtherSelected_(this.networkState, selectedApn) &&
+    if (this.isOtherSelected_(this.networkProperties, selectedApn) &&
         (!this.otherApn || !this.otherApn.AccessPointName ||
          this.otherApn.AccessPointName == this.DefaultAccessPointName)) {
       return;
@@ -228,13 +229,13 @@
   },
 
   /**
-   * @param {CrOnc.NetworkStateProperties|undefined} networkState
+   * @param {!CrOnc.NetworkProperties|undefined} networkProperties
    * @param {string} selectedApn
    * @return {boolean} True if the 'other' APN is currently selected.
    * @private
    */
-  isOtherSelected_: function(networkState, selectedApn) {
-    if (!networkState || !networkState.Cellular)
+  isOtherSelected_: function(networkProperties, selectedApn) {
+    if (!networkProperties || !networkProperties.Cellular)
       return false;
     var apnList = this.getApnList_();
     var apn = this.findApnInList(apnList, selectedApn);
diff --git a/chrome/browser/resources/settings/internet_page/network_ip_config.html b/chrome/browser/resources/settings/internet_page/network_ip_config.html
index 9d4a239..0245787f 100644
--- a/chrome/browser/resources/settings/internet_page/network_ip_config.html
+++ b/chrome/browser/resources/settings/internet_page/network_ip_config.html
@@ -11,7 +11,7 @@
           Configure IP Address Automatically
       </paper-checkbox>
       <network-property-list
-          fields="[[ipConfigFields_]]" network-state="[[ipConfig]]"
+          fields="[[ipConfigFields_]]" property-dict="[[ipConfig]]"
           edit-field-types="[[getIPEditFields_(ipConfig, editable, automatic)]]"
           on-property-change="onIPChange_">
       </network-property-list>
diff --git a/chrome/browser/resources/settings/internet_page/network_ip_config.js b/chrome/browser/resources/settings/internet_page/network_ip_config.js
index f883266b..a1d10e0 100644
--- a/chrome/browser/resources/settings/internet_page/network_ip_config.js
+++ b/chrome/browser/resources/settings/internet_page/network_ip_config.js
@@ -15,13 +15,13 @@
 
   properties: {
     /**
-     * The current state containing the IP Config properties to display and
-     * modify.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The network properties dictionary containing the IP Config properties to
+     * display and modify.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /**
@@ -45,13 +45,13 @@
     /**
      * The currently visible IP Config property dictionary. The 'RoutingPrefix'
      * property is a human-readable mask instead of a prefix length.
-     * @type {{
+     * @type {!{
      *   ipv4: !CrOnc.IPConfigUIProperties,
      *   ipv6: !CrOnc.IPConfigUIProperties
      * }|undefined}
      */
     ipConfig: {
-      type: Object,
+      type: Object
     },
 
     /**
@@ -74,28 +74,30 @@
 
   /**
    * Saved static IP configuration properties when switching to 'automatic'.
-   * @type {?CrOnc.IPConfigUIProperties}
+   * @type {!CrOnc.IPConfigUIProperties|undefined}
    */
-  savedStaticIp_: null,
+  savedStaticIp_: undefined,
 
   /**
-   * Polymer networkState changed method.
+   * Polymer networkProperties changed method.
    */
-  networkStateChanged_: function(newValue, oldValue) {
-    if (!this.networkState)
+  networkPropertiesChanged_: function(newValue, oldValue) {
+    if (!this.networkProperties)
       return;
 
     if (newValue.GUID != (oldValue && oldValue.GUID))
-      this.savedStaticIp_ = null;
+      this.savedStaticIp_ = undefined;
 
     // Update the 'automatic' property.
     var ipConfigType =
-        CrOnc.getActiveValue(this.networkState, 'IPAddressConfigType');
+        CrOnc.getActiveValue(this.networkProperties.IPAddressConfigType);
     this.automatic = (ipConfigType != CrOnc.IPConfigType.STATIC);
 
     // Update the 'ipConfig' property.
-    var ipv4 = CrOnc.getIPConfigForType(this.networkState, CrOnc.IPType.IPV4);
-    var ipv6 = CrOnc.getIPConfigForType(this.networkState, CrOnc.IPType.IPV6);
+    var ipv4 =
+        CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
+    var ipv6 =
+        CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV6);
     this.ipConfig = {
       ipv4: this.getIPConfigUIProperties_(ipv4),
       ipv6: this.getIPConfigUIProperties_(ipv6)
@@ -133,7 +135,7 @@
   },
 
   /**
-   * @param {?CrOnc.IPConfigProperties} ipconfig The IP Config properties.
+   * @param {!CrOnc.IPConfigProperties|undefined} ipconfig
    * @return {!CrOnc.IPConfigUIProperties} A new IPConfigUIProperties object
    *     with RoutingPrefix expressed as a string mask instead of a prefix
    *     length. Returns an empty object if |ipconfig| is undefined.
@@ -172,7 +174,7 @@
   },
 
   /**
-   * @param {!CrOnc.IPConfigUIProperties} ipConfig The IP Config properties.
+   * @param {!CrOnc.IPConfigUIProperties} ipConfig The IP Config UI properties.
    * @param {boolean} editable The editable property.
    * @param {boolean} automatic The automatic property.
    * @return {Object} An object with the edit type for each editable field.
diff --git a/chrome/browser/resources/settings/internet_page/network_nameservers.js b/chrome/browser/resources/settings/internet_page/network_nameservers.js
index 9dc4478..983c45b 100644
--- a/chrome/browser/resources/settings/internet_page/network_nameservers.js
+++ b/chrome/browser/resources/settings/internet_page/network_nameservers.js
@@ -13,13 +13,13 @@
 
   properties: {
     /**
-     * The current state containing the IP Config properties to display and
-     * modify.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The network properties dictionary containing the nameserver properties to
+     * display and modify.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /**
@@ -66,10 +66,10 @@
   savedNameservers_: [],
 
   /**
-   * Polymer networkState changed method.
+   * Polymer networkProperties changed method.
    */
-  networkStateChanged_: function(newValue, oldValue) {
-    if (!this.networkState)
+  networkPropertiesChanged_: function(newValue, oldValue) {
+    if (!this.networkProperties)
       return;
 
     if (!oldValue || newValue.GUID != oldValue.GUID)
@@ -77,13 +77,14 @@
 
     // Update the 'nameservers' property.
     var nameservers = [];
-    var ipv4 = CrOnc.getIPConfigForType(this.networkState, CrOnc.IPType.IPV4);
+    var ipv4 =
+        CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
     if (ipv4 && ipv4.NameServers)
       nameservers = ipv4.NameServers;
 
     // Update the 'nameserversType' property.
     var configType =
-        CrOnc.getActiveValue(this.networkState, 'NameServersConfigType');
+        CrOnc.getActiveValue(this.networkProperties.NameServersConfigType);
     var type;
     if (configType == CrOnc.IPConfigType.STATIC) {
       if (nameservers.join(',') == this.GoogleNameservers.join(','))
diff --git a/chrome/browser/resources/settings/internet_page/network_property_list.html b/chrome/browser/resources/settings/internet_page/network_property_list.html
index 345441bf..79db6d9 100644
--- a/chrome/browser/resources/settings/internet_page/network_property_list.html
+++ b/chrome/browser/resources/settings/internet_page/network_property_list.html
@@ -10,7 +10,7 @@
       <div class="layout vertical">
         <template is="dom-repeat" items="[[fields]]">
           <div class="layout horizontal"
-              hidden$="[[!showProperty_(networkState, editFieldTypes, item)]]">
+              hidden$="[[!showProperty_(propertyDict, editFieldTypes, item)]]">
             <span>[[getPropertyLabel_(item)]]</span>
             <span class="flex fill"></span>
           </div>
@@ -19,14 +19,14 @@
       <div class="layout vertical">
         <template is="dom-repeat" items="[[fields]]">
           <div class="layout horizontal"
-              hidden$="[[!showNoEdit_(networkState, editFieldTypes, item)]]">
-            <span>[[getPropertyValue_(networkState, item)]]</span>
+              hidden$="[[!showNoEdit_(propertyDict, editFieldTypes, item)]]">
+            <span>[[getPropertyValue_(propertyDict, item)]]</span>
           </div>
           <div class="layout horizontal" hidden$=
-               "[[!showEdit_(networkState, editFieldTypes, item, 'String')]]">
+               "[[!showEdit_(propertyDict, editFieldTypes, item, 'String')]]">
             <paper-input-container no-label-float>
               <input id="[[item]]" is="iron-input"
-                  value="[[getPropertyValue_(networkState, item)]]"
+                  value="[[getPropertyValue_(propertyDict, item)]]"
                   on-blur="onValueChange_">
             </paper-input-container>
           </div>
diff --git a/chrome/browser/resources/settings/internet_page/network_property_list.js b/chrome/browser/resources/settings/internet_page/network_property_list.js
index bc943e52..1483895 100644
--- a/chrome/browser/resources/settings/internet_page/network_property_list.js
+++ b/chrome/browser/resources/settings/internet_page/network_property_list.js
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 /**
- * @fileoverview Polymer element for displaying a list of network state
- * properties in a list in the format:
+ * @fileoverview Polymer element for displaying a list of network properties
+ * in a list in the format:
  *    Key1.........Value1
  *    KeyTwo.......ValueTwo
  * This also supports editing fields inline for fields listed in editFieldTypes:
@@ -16,10 +16,9 @@
 
   properties: {
     /**
-     * The network state containing the properties to display.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The dictionary containing the properties to display.
      */
-    networkState: {
+    propertyDict: {
       type: Object
     },
 
@@ -55,10 +54,14 @@
    * @private
    */
   onValueChange_: function(event) {
-    if (!this.networkState)
+    if (!this.propertyDict)
       return;
     var field = event.target.id;
-    var curValue = CrOnc.getActiveValue(this.networkState, field);
+    var curValue = this.get(field, this.propertyDict);
+    if (typeof curValue == 'object') {
+      // Extract the property from an ONC managed dictionary.
+      curValue = CrOnc.getActiveValue(/** @type {!Object} */(curValue));
+    }
     var newValue = event.target.value;
     if (newValue == curValue)
       return;
@@ -76,70 +79,77 @@
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!Object|undefined} propertyDict
    * @param {string} key The property key.
-   * @return {boolean} Whether or not the property exists in |state|.
+   * @return {boolean} Whether or not the property exists in |propertyDict|.
    * @private
    */
-  hasPropertyValue_: function(state, key) {
-    var value = (state && this.get(key, state)) || undefined;
+  hasPropertyValue_: function(propertyDict, key) {
+    var value = (propertyDict && this.get(key, propertyDict)) || undefined;
     return (value !== undefined && value !== '');
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
-   * @param {Object} editFieldTypes The editFieldTypes object.
+   * @param {!Object|undefined} propertyDict
+   * @param {!Object} editFieldTypes The editFieldTypes object.
    * @param {string} key The property key.
    * @return {boolean} Whether or not to show the property. Editable properties
    *     are always shown.
    * @private
    */
-  showProperty_: function(state, editFieldTypes, key) {
+  showProperty_: function(propertyDict, editFieldTypes, key) {
     if (editFieldTypes.hasOwnProperty(key))
       return true;
-    return this.hasPropertyValue_(state, key);
+    return this.hasPropertyValue_(propertyDict, key);
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
-   * @param {Object} editFieldTypes The editFieldTypes object.
+   * @param {!Object|undefined} propertyDict
+   * @param {!Object} editFieldTypes The editFieldTypes object.
    * @param {string} key The property key.
-   * @return {boolean} True if |key| exists in |state| and is not editable.
+   * @return {boolean} True if |key| exists in |propertiesDict| and is not
+   *     editable.
    * @private
    */
-  showNoEdit_: function(state, editFieldTypes, key) {
-    if (!this.hasPropertyValue_(state, key))
+  showNoEdit_: function(propertyDict, editFieldTypes, key) {
+    if (!this.hasPropertyValue_(propertyDict, key))
       return false;
     var editType = editFieldTypes[key];
     return !editType;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
-   * @param {Object} editFieldTypes The editFieldTypes object.
+   * @param {!Object|undefined} propertyDict
+   * @param {!Object} editFieldTypes The editFieldTypes object.
    * @param {string} key The property key.
    * @param {string} type The field type.
-   * @return {boolean} True if |key| exists in |state| and is of editable
+   * @return {boolean} True if |key| exists in |propertyDict| and is of editable
    *     type |type|.
    * @private
    */
-  showEdit_: function(state, editFieldTypes, key, type) {
+  showEdit_: function(propertyDict, editFieldTypes, key, type) {
     return editFieldTypes[key] == type;
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state The network state properties.
+   * @param {!Object|undefined} propertyDict
    * @param {string} key The property key.
    * @return {string} The text to display for the property value.
    * @private
    */
-  getPropertyValue_: function(state, key) {
-    if (!state)
+  getPropertyValue_: function(propertyDict, key) {
+    if (!propertyDict)
       return '';
-    var value = CrOnc.getActiveValue(state, key);
+    var value = this.get(key, propertyDict);
     if (value === undefined)
       return '';
+    if (typeof value == 'object') {
+      // Extract the property from an ONC managed dictionary
+      value = CrOnc.getActiveValue(/** @type {!Object} */(value));
+    }
     // TODO(stevenjb): Localize.
+    if (typeof value == 'number' || typeof value == 'boolean')
+      return value.toString();
     return /** @type {string} */(value);
   },
 });
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy.js b/chrome/browser/resources/settings/internet_page/network_proxy.js
index 995ef3e9a..fc6ff4c 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy.js
+++ b/chrome/browser/resources/settings/internet_page/network_proxy.js
@@ -11,13 +11,13 @@
 
   properties: {
     /**
-     * The current state containing the IP Config properties to display and
-     * modify.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The network properties dictionary containing the proxy properties to
+     * display and modify.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /**
@@ -38,7 +38,7 @@
     },
 
     /**
-     * The Web Proxy Auto Discovery URL extracted from networkState.
+     * The Web Proxy Auto Discovery URL extracted from networkProperties.
      */
     WPAD: {
       type: String,
@@ -102,15 +102,14 @@
   savedExcludeDomains_: undefined,
 
   /**
-   * Polymer networkState changed method.
+   * Polymer networkProperties changed method.
    */
-  networkStateChanged_: function() {
-    if (!this.networkState)
+  networkPropertiesChanged_: function() {
+    if (!this.networkProperties)
       return;
 
     var defaultProxy = this.createDefaultProxySettings_();
-    var proxy = /** @type {CrOnc.ProxySettings} */(
-        this.get('networkState.ProxySettings') || {});
+    var proxy = this.networkProperties.ProxySettings || {};
 
     // Ensure that all proxy settings object properties are specified.
     proxy.ExcludeDomains = proxy.ExcludeDomains || this.savedExcludeDomains_ ||
@@ -131,7 +130,8 @@
     this.$.selectType.value = proxy.Type;
 
     // Set the Web Proxy Auto Discovery URL.
-    var ipv4 = CrOnc.getIPConfigForType(this.networkState, CrOnc.IPType.IPV4);
+    var ipv4 =
+        CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
     this.WPAD = (ipv4 && ipv4.WebProxyAutoDiscoveryUrl) || '';
   },
 
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy_input.js b/chrome/browser/resources/settings/internet_page/network_proxy_input.js
index 480fbba..6093bd4 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy_input.js
+++ b/chrome/browser/resources/settings/internet_page/network_proxy_input.js
@@ -30,7 +30,7 @@
 
     /**
      * The proxy object.
-     * @type {?CrOnc.ProxyLocation}
+     * @type {!CrOnc.ProxyLocation}
      */
     value: {
       type: Object,
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.html b/chrome/browser/resources/settings/internet_page/network_siminfo.html
index dd5477c..03450ad 100644
--- a/chrome/browser/resources/settings/internet_page/network_siminfo.html
+++ b/chrome/browser/resources/settings/internet_page/network_siminfo.html
@@ -20,22 +20,22 @@
       <div class="layout vertical"
           hidden$="[[!state.Cellular.SIMPresent]]">
         <div id="lockedDiv" class="layout horizontal center"
-            hidden$="[[!isSimLocked_(networkState)]]">
+            hidden$="[[!isSimLocked_(networkProperties)]]">
           <!-- SIM locked -->
           <iron-icon icon="lock"></iron-icon>
           <span>SIM card is locked.</span>
           <paper-button on-tap="unlockPin_">Unlock</paper-button>
         </div>
         <div class="layout vertical"
-            hidden$="[[isSimLocked_(networkState)]]">
+            hidden$="[[isSimLocked_(networkProperties)]]">
           <!-- SIM unlocked -->
           <paper-checkbox
-              checked="[[networkState.Cellular.SIMLockStatus.LockEnabled]]"
+              checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]"
               on-change="onSimLockEnabledChange_">
             Enable SIM card locking (require PIN to use mobile data)
           </paper-checkbox>
           <div class="layout horizontal center"
-               hidden$="[[!networkState.Cellular.SIMLockStatus.LockEnabled]]">
+               hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
             <!-- SIM lock enabled -->
             <paper-button on-tap="onChangePin_">Change PIN</paper-button>
           </div>
@@ -60,7 +60,7 @@
           <span class="error" hidden$="[[!showError_(error)]]"
               >[[getErrorMsg_(error)]]
           </span>
-          <span>[[getRetriesLeftMsg_(networkState)]]</span>
+          <span>[[getRetriesLeftMsg_(networkProperties)]]</span>
         </div>
       </div>
     </paper-dialog>
@@ -88,7 +88,7 @@
           <span class="error" hidden$="[[!showError_(error)]]"
               >[[getErrorMsg_(error)]]
           </span>
-          <span>[[getRetriesLeftMsg_(networkState)]]</span>
+          <span>[[getRetriesLeftMsg_(networkProperties)]]</span>
         </div>
       </div>
     </paper-dialog>
@@ -108,7 +108,7 @@
           <span class="error" hidden$="[[!showError_(error)]]"
               >[[getErrorMsg_(error)]]
           </span>
-          <span>[[getRetriesLeftMsg_(networkState)]]</span>
+          <span>[[getRetriesLeftMsg_(networkProperties)]]</span>
         </div>
       </div>
     </paper-dialog>
@@ -148,7 +148,7 @@
           <span class="error" hidden$="[[!showError_(error)]]"
               >[[getErrorMsg_(error)]]
           </span>
-          <span>[[getRetriesLeftMsg_(networkState)]]</span>
+          <span>[[getRetriesLeftMsg_(networkProperties)]]</span>
         </div>
       </div>
     </paper-dialog>
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.js b/chrome/browser/resources/settings/internet_page/network_siminfo.js
index 69ab211..d93268c 100644
--- a/chrome/browser/resources/settings/internet_page/network_siminfo.js
+++ b/chrome/browser/resources/settings/internet_page/network_siminfo.js
@@ -26,12 +26,12 @@
 
   properties: {
     /**
-     * The network state associated with the element.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * The network properties associated with the element.
+     * @type {!CrOnc.NetworkProperties|undefined}
      */
-    networkState: {
+    networkProperties: {
       type: Object,
-      observer: 'networkStateChanged_'
+      observer: 'networkPropertiesChanged_'
     },
 
     /** Set to true when a PUK is required to unlock the SIM. */
@@ -53,17 +53,16 @@
 
   sendSimLockEnabled_: false,
 
-  /** Polymer networkState changed method. */
-  networkStateChanged_: function() {
-    if (!this.networkState || !this.networkState.Cellular)
+  /** Polymer networkProperties changed method. */
+  networkPropertiesChanged_: function() {
+    if (!this.networkProperties || !this.networkProperties.Cellular)
       return;
-    var simLockStatus = /** @type {CrOnc.SIMLockStatus|undefined} */(
-        this.get('networkState.Cellular.SIMLockStatus'));
+    var simLockStatus = this.networkProperties.Cellular.SIMLockStatus;
     this.pukRequired =
         !!simLockStatus && simLockStatus.LockType == CrOnc.LockType.PUK;
   },
 
-  /** Polymer networkState changed method. */
+  /** Polymer networkProperties changed method. */
   pukRequiredChanged_: function() {
     if (this.$.unlockPukDialog.opened) {
       if (this.pukRequired)
@@ -99,9 +98,9 @@
     this.$.unlockPuk.focus();
   },
 
-  /** Polymer networkState changed method. */
+  /** Polymer networkProperties changed method. */
   onSimLockEnabledChange_: function(event) {
-    if (!this.networkState || !this.networkState.Cellular)
+    if (!this.networkProperties || !this.networkProperties.Cellular)
       return;
     this.sendSimLockEnabled_ = event.target.checked;
     this.error = ErrorType.NONE;
@@ -124,7 +123,7 @@
    * @private
    */
   sendEnterPin_: function(event) {
-    var guid = this.networkState && this.networkState.GUID;
+    var guid = this.networkProperties && this.networkProperties.GUID;
     if (!guid)
       return;
 
@@ -152,7 +151,7 @@
    * @private
    */
   onChangePin_: function(event) {
-    if (!this.networkState || !this.networkState.Cellular)
+    if (!this.networkProperties || !this.networkProperties.Cellular)
       return;
     this.error = ErrorType.NONE;
     this.$.changePinDialog.open();
@@ -176,7 +175,7 @@
    * @private
    */
   sendChangePin_: function(event) {
-    var guid = this.networkState && this.networkState.GUID;
+    var guid = this.networkProperties && this.networkProperties.GUID;
     if (!guid)
       return;
 
@@ -225,7 +224,7 @@
    * @private
    */
   sendUnlockPin_: function(event) {
-    var guid = this.networkState && this.networkState.GUID;
+    var guid = this.networkProperties && this.networkProperties.GUID;
     if (!guid)
       return;
     var pin = this.$.unlockPin.value;
@@ -270,7 +269,7 @@
    * @private
    */
   sendUnlockPuk_: function(event) {
-    var guid = this.networkState && this.networkState.GUID;
+    var guid = this.networkProperties && this.networkProperties.GUID;
     if (!guid)
       return;
 
@@ -292,22 +291,22 @@
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state
+   * @param {!CrOnc.NetworkProperties|undefined} networkProperties
    * @return {boolean} True if the Cellular SIM is locked.
    * @private
    */
-  isSimLocked_: function(state) {
-    return !!state && CrOnc.isSimLocked(state);
+  isSimLocked_: function(networkProperties) {
+    return !!networkProperties && CrOnc.isSimLocked(networkProperties);
   },
 
   /**
-   * @param {?CrOnc.NetworkStateProperties} state
+   * @param {!CrOnc.NetworkProperties|undefined} networkProperties
    * @return {string} The message for the number of retries left.
    * @private
    */
-  getRetriesLeftMsg_: function(state) {
+  getRetriesLeftMsg_: function(networkProperties) {
     var retriesLeft =
-        this.get('Cellular.SIMLockStatus.RetriesLeft', state) || 0;
+        this.get('Cellular.SIMLockStatus.RetriesLeft', networkProperties) || 0;
     // TODO(stevenjb): Localize
     return 'Retries left: ' + retriesLeft.toString();
   },
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js
index f0dc33a..3086221 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -23,11 +23,11 @@
 
 /**
  * @typedef {{
- *   Ethernet: (?CrOnc.NetworkStateProperties|undefined),
- *   WiFi: (?CrOnc.NetworkStateProperties|undefined),
- *   Cellular: (?CrOnc.NetworkStateProperties|undefined),
- *   WiMAX: (?CrOnc.NetworkStateProperties|undefined),
- *   VPN: (?CrOnc.NetworkStateProperties|undefined)
+ *   Ethernet: (!CrOnc.NetworkStateProperties|undefined),
+ *   WiFi: (!CrOnc.NetworkStateProperties|undefined),
+ *   Cellular: (!CrOnc.NetworkStateProperties|undefined),
+ *   WiMAX: (!CrOnc.NetworkStateProperties|undefined),
+ *   VPN: (!CrOnc.NetworkStateProperties|undefined)
  * }}
  */
 var NetworkStateObject;
@@ -322,10 +322,10 @@
     }, this);
 
     // Set any types with a deviceState and no network to a default state,
-    // and any types not found to null.
+    // and any types not found to undefined.
     NETWORK_TYPES.forEach(function(type) {
       if (!foundTypes[type]) {
-        var defaultState = /** @type {?CrOnc.NetworkStateProperties} */(null);
+        var defaultState = undefined;
         if (this.deviceStates[type])
           defaultState = {GUID: '', Type: type};
         this.updateNetworkState_(type, defaultState);
@@ -345,9 +345,9 @@
    * Sets 'networkStates[type]' which will update the cr-network-list-item
    * associated with 'type'.
    * @param {string} type The network type.
-   * @param {?CrOnc.NetworkStateProperties} state The state properties for the
-   *     network to associate with |type|. May be null if there are no networks
-   *     matching |type|.
+   * @param {!CrOnc.NetworkStateProperties|undefined} state The state properties
+   *     for the network to associate with |type|. May be undefined if there are
+   *     no networks matching |type|.
    * @private
    */
   updateNetworkState_: function(type, state) {
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js
index 426f8117..67e7a1b0 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -53,7 +53,7 @@
 
     /**
      * Network state for the active network.
-     * @type {CrOnc.NetworkStateProperties|undefined}
+     * @type {!CrOnc.NetworkStateProperties|undefined}
      */
     networkState: {
       type: Object,
@@ -158,7 +158,7 @@
   },
 
   /**
-   * @param {CrOnc.NetworkStateProperties} state
+   * @param {!CrOnc.NetworkStateProperties} state
    * @param {boolean} expanded The expanded state.
    * @return {boolean} True if the 'Known networks' button should be shown.
    * @private
diff --git a/chrome/browser/resources/settings/languages_page/compiled_resources.gyp b/chrome/browser/resources/settings/languages_page/compiled_resources.gyp
index e566a442..ea0bdf4 100644
--- a/chrome/browser/resources/settings/languages_page/compiled_resources.gyp
+++ b/chrome/browser/resources/settings/languages_page/compiled_resources.gyp
@@ -14,7 +14,23 @@
         ],
         'externs': [
           '<(EXTERNS_DIR)/chrome_send.js',
-          '../../../../../third_party/closure_compiler/externs/language_settings_private.js'
+          '<(EXTERNS_DIR)/language_settings_private.js',
+        ],
+      },
+      'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+    },
+    {
+      'target_name': 'language_detail_page',
+      'variables': {
+        'depends': [
+          '../../../../../ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.js',
+          '../../../../../ui/webui/resources/js/chromeos/compiled_resources.gyp:ui_account_tweaks',
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
+          '../prefs/compiled_resources.gyp:prefs',
+          'languages.js',
+        ],
+        'externs': [
+          '<(EXTERNS_DIR)/language_settings_private.js',
         ],
       },
       'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
@@ -32,6 +48,20 @@
           'languages.js',
         ],
         'externs': [
+          '<(EXTERNS_DIR)/language_settings_private.js',
+        ],
+      },
+      'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+    },
+    {
+      'target_name': 'manage_languages_page',
+      'variables': {
+        'depends': [
+          '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
+          '../prefs/compiled_resources.gyp:prefs',
+          'languages.js',
+        ],
+        'externs': [
           '../../../../../third_party/closure_compiler/externs/language_settings_private.js',
         ],
       },
diff --git a/chrome/browser/resources/settings/languages_page/language_detail_page.css b/chrome/browser/resources/settings/languages_page/language_detail_page.css
new file mode 100644
index 0000000..1da7422
--- /dev/null
+++ b/chrome/browser/resources/settings/languages_page/language_detail_page.css
@@ -0,0 +1,20 @@
+/* Copyright 2015 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+label {
+  align-items: center;
+  display: flex;
+}
+
+label > *:not(:first-child) {
+  margin-left: 5px;
+}
+
+label > span {
+  line-height: 42px;
+}
+
+label paper-button {
+  line-height: initial;
+}
diff --git a/chrome/browser/resources/settings/languages_page/language_detail_page.html b/chrome/browser/resources/settings/languages_page/language_detail_page.html
new file mode 100644
index 0000000..51b1767
--- /dev/null
+++ b/chrome/browser/resources/settings/languages_page/language_detail_page.html
@@ -0,0 +1,54 @@
+<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="chrome://resources/cr_elements/v1_0/policy/cr_policy_indicator.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="languages.html">
+
+<if expr="chromeos">
+<link rel="import" href="chrome://resources/html/chromeos/ui_account_tweaks.html">
+</if>
+
+<dom-module id="settings-language-detail-page">
+  <link rel="import" type="css" href="chrome://md-settings/settings_page/settings_page.css">
+  <link rel="import" type="css" href="language_detail_page.css">
+  <template>
+    <cr-settings-languages id="languages" languages="{{languages}}">
+    </cr-settings-languages>
+<if expr="chromeos or is_win">
+    <div id="languageSettings">
+      <label hidden$="[[!detail.language.supportsUI]]">
+        <paper-toggle-button
+            checked="[[isProspectiveUILanguage_(detail.language.code, prefs.intl.app_locale.value)]]"
+            on-change="onUILanguageChange_"
+            disabled$="[[isUILanguageChangeDisabled_(detail.language.code, prefs.intl.app_locale.value)]]">
+        </paper-toggle-button>
+        <span i18n-content="isDisplayedInThisLanguage"
+            hidden$="[[!isCurrentUILanguage_(detail.language.code, prefs.intl.app_locale.value)]]">
+        </span>
+        <span hidden$="[[isCurrentUILanguage_(detail.language.code, prefs.intl.app_locale.value)]]">
+          <span i18n-content="displayInThisLanguage"></span>
+          <paper-button i18n-content="restart" on-tap="onRestartTap_"
+              hidden$="[[!isRestartRequired_(detail.language.code, prefs.intl.app_locale.value)]]">
+          </paper-button>
+        </span>
+        <cr-policy-indicator id="policyIndicator"></cr-policy-indicator>
+      </label>
+      <span i18n-content="cannotBeDisplayedInThisLanguage"
+          hidden$="[[detail.language.supportsUI]]"></span>
+    </div>
+</if>
+    <div hidden$="[[shouldHideTranslate_(detail.language.code, prefs.translate.enabled.value)]]">
+      <paper-checkbox checked="[[detail.state.translateEnabled]]"
+          on-change="onTranslateEnabledChange_"
+          i18n-content="offerToTranslateInThisLanguage"
+          hidden$="[[!detail.language.supportsTranslate]]"
+          disabled="[[isTranslateDisabled_(detail.language.code, languages.translateTarget)]]">
+      </paper-checkbox>
+      <div i18n-content="cannotTranslateInThisLanguage"
+          hidden$="[[detail.language.supportsTranslate]]"></div>
+    </div>
+  </template>
+  <script src="language_detail_page.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/languages_page/language_detail_page.js b/chrome/browser/resources/settings/languages_page/language_detail_page.js
new file mode 100644
index 0000000..aadcc60
--- /dev/null
+++ b/chrome/browser/resources/settings/languages_page/language_detail_page.js
@@ -0,0 +1,169 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-language-detail-page' is a sub-page for editing
+ * an individual language's settings.
+ *
+ * @group Chrome Settings Elements
+ * @element settings-language-detail-page
+ */
+Polymer({
+  is: 'settings-language-detail-page',
+
+  properties: {
+    /**
+     * Preferences state.
+     */
+    prefs: {
+      type: Object,
+      notify: true,
+    },
+
+    /**
+     * Read-only reference to the languages model provided by the
+     * 'cr-settings-languages' instance.
+     * @type {LanguagesModel|undefined}
+     */
+    languages: Object,
+
+    /**
+     * The language to display the details for.
+     * @type {LanguageInfo|undefined}
+     */
+    detail: Object,
+  },
+
+  ready: function() {
+    // In a CrOS multi-user session, the primary user controls the UI language.
+    if (this.isSecondaryUser_()) {
+      var indicator = this.$.policyIndicator;
+      indicator.indicatorType = CrPolicyIndicator.Type.PRIMARY_USER;
+      indicator.controllingUser = loadTimeData.getString('primaryUserEmail');
+    }
+
+    // The UI language choice doesn't persist for guests.
+    if (cr.isChromeOS &&
+        (uiAccountTweaks.UIAccountTweaks.loggedInAsGuest() ||
+         uiAccountTweaks.UIAccountTweaks.loggedInAsPublicAccount())) {
+      this.$.languageSettings.hidden = true;
+    }
+  },
+
+  /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} prospectiveUILanguage The chosen UI language.
+   * @return {boolean} True if the given language matches the chosen UI language
+   *     (which may be different from the actual UI language).
+   * @private
+   */
+  isProspectiveUILanguage_: function(languageCode, prospectiveUILanguage) {
+    return languageCode == this.$.languages.getProspectiveUILanguage();
+  },
+
+  /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} prospectiveUILanguage The prospective UI language.
+   * @return {boolean} True if the the given language, the prospective UI
+   *     language and the actual language all the same.
+   * @private
+   */
+  isCurrentUILanguage_: function(languageCode, prospectiveUILanguage) {
+    return languageCode == prospectiveUILanguage &&
+           languageCode == navigator.language;
+  },
+
+   /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} targetLanguageCode The default translate target language.
+   * @return {boolean} True if the language code matches the target language.
+   * @private
+   */
+  isTranslateDisabled_: function(languageCode, targetLanguageCode) {
+    return this.$.languages.convertLanguageCodeForTranslate(languageCode) ==
+        targetLanguageCode;
+  },
+
+   /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} prospectiveUILanguage The prospective UI language.
+   * @return {boolean} True if the prospective UI language is set to
+   *     |languageCode| but requires a restart to take effect.
+   * @private
+   */
+  isRestartRequired_: function(languageCode, prospectiveUILanguage) {
+    return prospectiveUILanguage == languageCode &&
+           navigator.language != languageCode;
+  },
+
+  /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} prospectiveUILanguage The chosen UI language.
+   * @return {boolean} True if the chosen language cannot currently be changed.
+   * @private
+   */
+  isUILanguageChangeDisabled_: function(languageCode, prospectiveUILanguage) {
+    // UI language setting belongs to the primary user.
+    if (this.isSecondaryUser_())
+      return true;
+    // If this is both the actual and the prospective language, flipping the
+    // toggle button to "off" makes no sense.
+    return this.isCurrentUILanguage_(languageCode, prospectiveUILanguage);
+  },
+
+  /**
+   * @return {boolean} True for a secondary user in a multi-profile session.
+   * @private
+   */
+  isSecondaryUser_: function() {
+    return cr.isChromeOS && loadTimeData.getBoolean('isSecondaryUser');
+  },
+
+  /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {boolean} translateEnabled Whether translate is enabled.
+   * @return {boolean} True if the translate section should be hidden.
+   * @private
+   */
+  shouldHideTranslate_: function(languageCode, translateEnabled) {
+    // Translate server supports Chinese (Traditional) and Chinese (Simplified)
+    // but not 'general' Chinese. To avoid ambiguity, hide the translate
+    // checkbox when general Chinese is selected.
+    return !translateEnabled || languageCode == 'zh';
+  },
+
+  /**
+   * Handler for changes to the translate checkbox.
+   * @param {!{target: !{checked: boolean}}} e
+   * @private
+   */
+  onTranslateEnabledChange_: function(e) {
+    if (e.target.checked)
+      this.$.languages.enableTranslateLanguage(this.detail.language.code);
+    else
+      this.$.languages.disableTranslateLanguage(this.detail.language.code);
+  },
+
+  /**
+   * Handler for changes to the UI language toggle button.
+   * @param {!{target: !{checked: boolean}}} e
+   * @private
+   */
+  onUILanguageChange_: function(e) {
+    if (e.target.checked) {
+      this.$.languages.setUILanguage(this.detail.language.code);
+    } else {
+      // Reset the chosen UI language to the actual UI language.
+      this.$.languages.resetUILanguage();
+    }
+  },
+
+  /**
+   * Handler for the restart button.
+   * @private
+   */
+  onRestartTap_: function() {
+    chrome.send('restart');
+  },
+});
diff --git a/chrome/browser/resources/settings/languages_page/languages.js b/chrome/browser/resources/settings/languages_page/languages.js
index 3359c02..c65c0e74 100644
--- a/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chrome/browser/resources/settings/languages_page/languages.js
@@ -24,7 +24,7 @@
  * @element cr-settings-languages
  */
 
-/** @typedef {{spellCheckEnabled: boolean}} */
+/** @typedef {{spellCheckEnabled: boolean, translateEnabled: boolean}} */
 var LanguageState;
 
 /**
@@ -39,7 +39,8 @@
  *     preference.
  * @typedef {{
  *      supportedLanguages: !Array<!chrome.languageSettingsPrivate.Language>,
- *      enabledLanguages: !Array<!LanguageInfo>
+ *      enabledLanguages: !Array<!LanguageInfo>,
+ *      translateTarget: string
  *  }}
  */
 var LanguagesModel;
@@ -47,6 +48,24 @@
 (function() {
 'use strict';
 
+// Translate server treats some language codes the same.
+// See also: components/translate/core/common/translate_util.cc.
+var kLanguageCodeToTranslateCode = {
+  'nb': 'no',
+  'fil': 'tl',
+  'zh-HK': 'zh-TW',
+  'zh-MO': 'zh-TW',
+  'zh-SG': 'zh-CN',
+};
+
+// Some ISO 639 language codes have been renamed, e.g. "he" to "iw", but
+// Translate still uses the old versions. TODO(michaelpg): Chrome does too.
+// Follow up with Translate owners to understand the right thing to do.
+var kTranslateLanguageSynonyms = {
+  'he': 'iw',
+  'jv': 'jw',
+};
+
 /**
  * This element has a reference to the singleton, exposing the singleton's
  * language model to the host of this element as the 'languages' property.
@@ -105,6 +124,16 @@
       this.singleton_.setUILanguage(languageCode);
   },
 
+  resetUILanguage: function() {
+    if (cr.isWindows || cr.isChromeOS)
+      this.singleton_.resetUILanguage();
+  },
+
+  /** @return {string} */
+  getProspectiveUILanguage: function() {
+    return this.singleton_.getProspectiveUILanguage();
+  },
+
   /** @param {string} languageCode */
   enableLanguage: function(languageCode) {
     this.singleton_.enableLanguage(languageCode);
@@ -115,6 +144,16 @@
     this.singleton_.disableLanguage(languageCode);
   },
 
+  /** @param {string} languageCode */
+  enableTranslateLanguage: function(languageCode) {
+    this.singleton_.enableTranslateLanguage(languageCode);
+  },
+
+  /** @param {string} languageCode */
+  disableTranslateLanguage: function(languageCode) {
+    this.singleton_.disableTranslateLanguage(languageCode);
+  },
+
   /**
    * @param {string} languageCode
    * @return {boolean}
@@ -130,6 +169,14 @@
   toggleSpellCheck: function(languageCode, enable) {
     this.singleton_.toggleSpellCheck(languageCode, enable);
   },
+
+  /**
+   * @param {string} languageCode
+   * @return {string}
+   */
+  convertLanguageCodeForTranslate: function(languageCode) {
+    return this.singleton_.convertLanguageCodeForTranslate(languageCode);
+  },
 });
 
 var preferredLanguagesPrefName = cr.isChromeOS ?
@@ -181,34 +228,61 @@
     'preferredLanguagesPrefChanged_(prefs.' +
         preferredLanguagesPrefName + '.value)',
     'spellCheckDictionariesPrefChanged_(prefs.spellcheck.dictionaries.value.*)',
+    'translateLanguagesPrefChanged_(prefs.translate_blocked_languages.value.*)',
   ],
 
   /** @override */
   created: function() {
-    chrome.languageSettingsPrivate.getLanguageList(function(languageList) {
+    var languageList;
+    var translateTarget;
+
+    // Request language information to populate the model.
+    Promise.all([
       // Wait until prefs are initialized before creating the model, so we can
       // include information about enabled languages.
-      CrSettingsPrefs.initialized.then(function() {
-        this.createModel_(languageList);
-        this.initialized_ = true;
-      }.bind(this));
+      CrSettingsPrefs.initialized,
+
+      // Get the language list.
+      new Promise(function(resolve) {
+        chrome.languageSettingsPrivate.getLanguageList(function(list) {
+          languageList = list;
+          resolve();
+        });
+      }),
+
+      // Get the translate target language.
+      new Promise(function(resolve) {
+        chrome.languageSettingsPrivate.getTranslateTargetLanguage(
+            function(targetLanguageCode) {
+              translateTarget = targetLanguageCode;
+              resolve();
+            });
+      }),
+    ]).then(function() {
+      this.createModel_(languageList, translateTarget);
+      this.initialized_ = true;
     }.bind(this));
   },
 
   /**
-   * Constructs the languages model from the given language list.
+   * Constructs the languages model.
    * @param {!Array<!chrome.languageSettingsPrivate.Language>}
    *     supportedLanguages
+   * @param {string} translateTarget Language code of the default translate
+   *     target language.
    */
-  createModel_: function(supportedLanguages) {
+  createModel_: function(supportedLanguages, translateTarget) {
     // Populate the hash map of supported languages.
     for (var i = 0; i < supportedLanguages.length; i++) {
-      this.supportedLanguageMap_[supportedLanguages[i].code] =
-          supportedLanguages[i];
+      var language = supportedLanguages[i];
+      language.supportsUI = !!language.supportsUI;
+      language.supportsTranslate = !!language.supportsTranslate;
+      language.supportsSpellcheck = !!language.supportsSpellcheck;
+      this.supportedLanguageMap_[language.code] = language;
     }
 
     // Create a list of enabled language info from the supported languages.
-    var enabledLanguages = this.getEnabledLanguages_();
+    var enabledLanguages = this.getEnabledLanguages_(translateTarget);
     // Populate the hash map of enabled languages.
     for (var i = 0; i < enabledLanguages.length; i++) {
       var languageInfo = enabledLanguages[i];
@@ -216,48 +290,64 @@
     }
 
     // Initialize the Polymer languages model.
-    this.languages = {
+    this.languages = /** @type {!LanguagesModel} */({
       supportedLanguages: supportedLanguages,
       enabledLanguages: enabledLanguages,
-    };
+      translateTarget: translateTarget,
+    });
   },
 
   /**
    * Returns a list of LanguageInfos for each enabled language in the supported
    * languages list.
+   * @param {string} translateTarget Language code of the default translate
+   *     target language.
    * @return {!Array<!LanguageInfo>}
    * @private
    */
-  getEnabledLanguages_: function() {
+  getEnabledLanguages_: function(translateTarget) {
     assert(CrSettingsPrefs.isInitialized);
 
     var pref = this.getPref_(preferredLanguagesPrefName);
     var enabledLanguageCodes = pref.value.split(',');
-    var enabledLanguages = [];
-    var spellCheckMap = this.getSpellCheckMap_();
+    var enabledLanguages = /** @type {!Array<!LanguageInfo>} */ [];
+
+    var spellCheckPref = this.getPref_('spellcheck.dictionaries');
+    var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
+        spellCheckPref.value));
+
+    var translateBlockedPref = this.getPref_('translate_blocked_languages');
+    var translateBlockedMap = this.makeMapFromArray_(
+        /** @type {!Array<string>} */(translateBlockedPref.value));
+
     for (var i = 0; i < enabledLanguageCodes.length; i++) {
       var code = enabledLanguageCodes[i];
       var language = this.supportedLanguageMap_[code];
       if (!language)
         continue;
-      var state = {spellCheckEnabled: !!spellCheckMap[code]};
+      var state = {};
+      state.spellCheckEnabled = !!spellCheckMap[code];
+      // Translate is considered disabled if this language maps to any translate
+      // language that is blocked.
+      var translateCode = this.convertLanguageCodeForTranslate(code);
+      state.translateEnabled = language.supportsTranslate &&
+          !translateBlockedMap[translateCode] &&
+          translateCode != translateTarget;
       enabledLanguages.push({language: language, state: state});
     }
     return enabledLanguages;
   },
 
   /**
-   * Creates a map whose keys are languages enabled for spell check.
+   * Creates an object whose keys are the elements of the list.
+   * @param {!Array<string>} list
    * @return {!Object<boolean>}
    */
-  getSpellCheckMap_: function() {
-    assert(CrSettingsPrefs.isInitialized);
-
-    var spellCheckCodes = this.getPref_('spellcheck.dictionaries').value;
-    var spellCheckMap = {};
-    for (var i = 0; i < spellCheckCodes.length; i++)
-      spellCheckMap[spellCheckCodes[i]] = true;
-    return spellCheckMap;
+  makeMapFromArray_: function(list) {
+    var map = {};
+    for (var i = 0; i < list.length; i++)
+      map[list[i]] = true;
+    return map;
   },
 
   /**
@@ -268,7 +358,8 @@
     if (!this.initialized_)
       return;
 
-    var enabledLanguages = this.getEnabledLanguages_();
+    var enabledLanguages =
+        this.getEnabledLanguages_(this.languages.translateTarget);
     // Reset the enabled language map. Do this before notifying of the change
     // via languages.enabledLanguages.
     this.enabledLanguageMap_ = {};
@@ -287,7 +378,8 @@
     if (!this.initialized_)
       return;
 
-    var spellCheckMap = this.getSpellCheckMap_();
+    var spellCheckMap = this.makeMapFromArray_(/** @type {!Array<string>} */(
+        this.getPref_('spellcheck.dictionaries').value));
     for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
       var languageCode = this.languages.enabledLanguages[i].language.code;
       this.set('languages.enabledLanguages.' + i + '.state.spellCheckEnabled',
@@ -295,6 +387,23 @@
     }
   },
 
+  translateLanguagesPrefChanged_: function() {
+    if (!this.initialized_)
+      return;
+
+    var translateBlockedPref = this.getPref_('translate_blocked_languages');
+    var translateBlockedMap = this.makeMapFromArray_(
+        /** @type {!Array<string>} */(translateBlockedPref.value));
+
+    for (var i = 0; i < this.languages.enabledLanguages.length; i++) {
+      var translateCode = this.convertLanguageCodeForTranslate(
+          this.languages.enabledLanguages[i].language.code);
+      this.set(
+          'languages.enabledLanguages.' + i + '.state.translateEnabled',
+          !translateBlockedMap[translateCode]);
+    }
+  },
+
   /**
    * Gets the pref at the given key. Asserts if the pref is not found.
    * @param {string} key
@@ -319,6 +428,17 @@
   },
 
   /**
+   * Deletes the given item from the pref at the given key if the item is found.
+   * Asserts if the pref itself is not found or is not an Array type.
+   * @param {string} key
+   * @param {*} item
+   */
+  deletePrefItem_: function(key, item) {
+    assert(this.getPref_(key).type == chrome.settingsPrivate.PrefType.LIST);
+    this.arrayDelete('prefs.' + key + '.value', item);
+  },
+
+  /**
    * Windows and Chrome OS only: Sets the prospective UI language to the chosen
    * language. This dosen't affect the actual UI language until a restart.
    * @param {string} languageCode
@@ -328,6 +448,26 @@
   },
 
   /**
+   * Windows and Chrome OS only: Resets the prospective UI language back to the
+   * actual UI language.
+   */
+  resetUILanguage: function() {
+    chrome.send('setUILanguage', [navigator.language]);
+  },
+
+  /**
+   * Returns the "prospective" UI language, i.e. the one to be used on next
+   * restart. If the pref is not set, the current UI language is also the
+   * "prospective" language.
+   * @return {string} Language code of the prospective UI language.
+   * @private
+   */
+  getProspectiveUILanguage: function() {
+    return /** @type {string} */(this.getPref_('intl.app_locale').value) ||
+        navigator.language;
+  },
+
+  /**
    * Enables the language, making it available for spell check and input.
    * @param {string} languageCode
    */
@@ -335,12 +475,13 @@
     if (!CrSettingsPrefs.isInitialized)
       return;
 
-    var languageCodes = this.getPref_(preferredLanguagesPrefName).value;
-    var index = languageCodes.split(',').indexOf(languageCode);
-    if (index > -1)
+    var languageCodes =
+        this.getPref_(preferredLanguagesPrefName).value.split(',');
+    if (languageCodes.indexOf(languageCode) > -1)
       return;
-    this.setPrefValue_(preferredLanguagesPrefName,
-                       languageCodes + ',' + languageCode);
+    languageCodes.push(languageCode);
+    chrome.languageSettingsPrivate.setLanguageList(languageCodes);
+    this.disableTranslateLanguage(languageCode);
   },
 
   /**
@@ -352,23 +493,22 @@
       return;
 
     // Cannot disable the UI language.
-    var appLocale = this.getPref_('intl.app_locale').value ||
-                    navigator.language;
-    assert(languageCode != appLocale);
+    assert(languageCode != this.getProspectiveUILanguage());
 
     // Cannot disable the only enabled language.
-    var pref = this.getPref_(preferredLanguagesPrefName);
-    var languageCodes = pref.value.split(',');
+    var languageCodes =
+        this.getPref_(preferredLanguagesPrefName).value.split(',');
     assert(languageCodes.length > 1);
 
     // Remove the language from spell check.
-    this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
+    this.deletePrefItem_('spellcheck.dictionaries', languageCode);
 
     var languageIndex = languageCodes.indexOf(languageCode);
     if (languageIndex == -1)
       return;
     languageCodes.splice(languageIndex, 1);
-    this.setPrefValue_(preferredLanguagesPrefName, languageCodes.join(','));
+    chrome.languageSettingsPrivate.setLanguageList(languageCodes);
+    this.enableTranslateLanguage(languageCode);
   },
 
   /**
@@ -380,6 +520,29 @@
   },
 
   /**
+   * Enables translate for the given language by removing the translate
+   * language from the blocked languages preference.
+   * @param {string} languageCode
+   */
+  enableTranslateLanguage: function(languageCode) {
+    languageCode = this.convertLanguageCodeForTranslate(languageCode);
+    this.arrayDelete('prefs.translate_blocked_languages.value', languageCode);
+  },
+
+  /**
+   * Disables translate for the given language by adding the translate
+   * language to the blocked languages preference.
+   * @param {string} languageCode
+   */
+  disableTranslateLanguage: function(languageCode) {
+    languageCode = this.convertLanguageCodeForTranslate(languageCode);
+    if (this.getPref_('translate_blocked_languages').value
+            .indexOf(languageCode) == -1) {
+      this.push('prefs.translate_blocked_languages.value', languageCode);
+    }
+  },
+
+  /**
    * Enables or disables spell check for the given language.
    * @param {string} languageCode
    * @param {boolean} enable
@@ -396,5 +559,29 @@
       this.arrayDelete('prefs.spellcheck.dictionaries.value', languageCode);
     }
   },
+
+  /**
+   * Converts the language code for translate. There are some differences
+   * between the language set the Translate server uses and that for
+   * Accept-Language.
+   * @param {string} languageCode
+   * @return {string} The converted language code.
+   * @private
+   */
+  convertLanguageCodeForTranslate: function(languageCode) {
+    if (languageCode in kLanguageCodeToTranslateCode)
+      return kLanguageCodeToTranslateCode[languageCode];
+
+    var main = languageCode.split('-')[0];
+    if (main == 'zh') {
+      // In Translate, general Chinese is not used, and the sub code is
+      // necessary as a language code for the Translate server.
+      return languageCode;
+    }
+    if (main in kTranslateLanguageSynonyms)
+      return kTranslateLanguageSynonyms[main];
+
+    return main;
+  },
 });
 })();
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.css b/chrome/browser/resources/settings/languages_page/languages_page.css
index 5bb2ab5..78a79f3 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.css
+++ b/chrome/browser/resources/settings/languages_page/languages_page.css
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 The Chromium Authors. All rights reserved.
+/* Copyright 2015 The Chromium Authors. All rights reserved.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index 0825bf67..a4e935e 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -10,6 +10,7 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
 <link rel="import" href="chrome://md-settings/settings_page/settings_subheader.html">
+<link rel="import" href="language_detail_page.html">
 <link rel="import" href="languages.html">
 <link rel="import" href="manage_languages_page.html">
 
@@ -20,18 +21,22 @@
   <template>
     <cr-settings-languages id="languages" languages="{{languages}}">
     </cr-settings-languages>
-    <cr-settings-animated-pages id="pages" current-route="{{currentRoute}}"
+    <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="languages">
       <neon-animatable id="">
         <h2 i18n-content="languagesListTitle"></h2>
         <div class="item-list">
+          <array-selector id="languageSelector" selected="{{detailLanguage}}"
+              items="{{languages.enabledLanguages}}"></array-selector>
           <template is="dom-repeat" items="{{languages.enabledLanguages}}">
             <paper-item on-tap="onLanguageTap_">
-              <div class="flex">[[item.language.displayName]]</div>
+              <div class="flex" title="[[item.language.nativeDisplayName]]"
+                  >[[item.language.displayName]]</div>
               <iron-icon icon="done"
                   hidden$="[[!isUILanguage_(item.language.code, prefs.intl.app_locale.value)]]">
               </iron-icon>
-              <paper-icon-button icon="settings"></paper-icon-button>
+              <paper-icon-button icon="settings"
+                  on-tap="onShowLanguageDetailTap_"></paper-icon-button>
             </paper-item>
           </template>
         </div>
@@ -57,6 +62,7 @@
           <paper-button i18n-content="manageInputMethods"></paper-button>
         </div>
 </if>
+<if expr="not is_macosx">
         <h2 i18n-content="spellCheckListTitle"></h2>
         <div class="layout vertical">
           <template is="dom-repeat" items="{{languages.enabledLanguages}}">
@@ -69,6 +75,7 @@
         <div class="manage">
           <paper-button i18n-content="manageSpellCheck"></paper-button>
         </div>
+</if>
       </neon-animatable>
       <neon-animatable id="manage-languages">
         <settings-subheader i18n-values="page-title:manageLanguagesPageTitle">
@@ -76,7 +83,15 @@
         <cr-settings-manage-languages-page id="manageLanguagesPage"
             prefs="{{prefs}}"></cr-settings-manage-languages-page>
       </neon-animatable>
-    </cr-settings-animated-pages>
+      <neon-animatable id="language-detail">
+        <settings-subheader id="language-detail-subheader"
+            page-title="[[detailLanguage.language.displayName]]">
+        </settings-subheader>
+        <settings-language-detail-page id="languageDetailPage"
+            prefs="{{prefs}}" detail="[[detailLanguage]]">
+        </settings-language-detail-page>
+      </neon-animatable>
+    </settings-animated-pages>
   </template>
   <script src="languages_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js
index 8aad5fd..427c9153 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.js
+++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -49,6 +49,10 @@
    * @param {!{model: !{item: !LanguageInfo}}} e
    */
   onLanguageTap_: function(e) {
+    // Taps on the paper-icon-button are handled in onShowLanguageDetailTap_.
+    if (e.target.tagName == 'PAPER-ICON-BUTTON')
+      return;
+
     // Set the prospective UI language. This won't take effect until a restart.
     if (e.model.item.language.supportsUI)
       this.$.languages.setUILanguage(e.model.item.language.code);
@@ -81,17 +85,24 @@
   },
 
   /**
-   * @param {string} languageCode The language code identifying a language.
-   * @param {string} appLocale The prospective UI language.
-   * @return {boolean} True if the given language matches the app locale pref
-   *     (which may be different from the actual app locale).
+   * Opens the Language Detail page for the language.
+   * @param {!{model: !{item}}} e
    * @private
    */
-  isUILanguage_: function(languageCode, appLocale) {
-    // Check the current language if the locale pref hasn't been set.
-    if (!appLocale)
-      appLocale = navigator.language;
-    return languageCode == appLocale;
+  onShowLanguageDetailTap_: function(e) {
+    this.$.languageSelector.select(e.model.item);
+    this.$.pages.setSubpageChain(['language-detail']);
+  },
+
+  /**
+   * @param {string} languageCode The language code identifying a language.
+   * @param {string} prospectiveUILanguage The prospective UI language.
+   * @return {boolean} True if the given language matches the prospective UI
+   *     pref (which may be different from the actual UI language).
+   * @private
+   */
+  isUILanguage_: function(languageCode, prospectiveUILanguage) {
+    return languageCode == this.$.languages.getProspectiveUILanguage();
   },
 
   /**
diff --git a/chrome/browser/resources/settings/languages_page/manage_languages_page.css b/chrome/browser/resources/settings/languages_page/manage_languages_page.css
index 388649d..ba789dc2 100644
--- a/chrome/browser/resources/settings/languages_page/manage_languages_page.css
+++ b/chrome/browser/resources/settings/languages_page/manage_languages_page.css
@@ -1,7 +1,15 @@
-/* Copyright (c) 2015 The Chromium Authors. All rights reserved.
+/* Copyright 2015 The Chromium Authors. All rights reserved.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
 iron-list {
   height: 300px;
 }
+
+paper-item {
+  display: flex;
+}
+
+paper-item .language-name {
+  flex: 1;
+}
diff --git a/chrome/browser/resources/settings/languages_page/manage_languages_page.html b/chrome/browser/resources/settings/languages_page/manage_languages_page.html
index 912a2ff..8fa80eb 100644
--- a/chrome/browser/resources/settings/languages_page/manage_languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/manage_languages_page.html
@@ -1,15 +1,12 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://md-settings/settings_page/settings_animated_pages.html">
 <link rel="import" href="languages.html">
 
 <dom-module id="cr-settings-manage-languages-page">
@@ -24,9 +21,11 @@
       <div class="item-list">
         <template is="dom-repeat" items="{{languages.enabledLanguages}}">
           <paper-item>
-            <div class="flex">[[item.language.displayName]]</div>
+            <div class="language-name"
+                title="[[item.language.nativeDisplayName]]"
+                >[[item.language.displayName]]</div>
             <paper-icon-button icon="clear" on-tap="onRemoveLanguageTap_"
-                hidden$="[[!canRemoveLanguage_(item.language.code, languages.enabledLanguages)]]">
+                hidden$="[[!canRemoveLanguage_(item.language.code, prefs.intl.app_locale.value)]]">
             </paper-icon-button>
           </paper-item>
         </template>
@@ -35,7 +34,10 @@
       <iron-list id="list" items="{{availableLanguages_}}" as="item">
         <template>
           <paper-item on-tap="onAddLanguageTap_">
-            <div class="flex">[[item.displayName]]</div>
+            <div class="language-name">
+              <span>[[item.displayName]]</span> -
+              <span>[[item.nativeDisplayName]]</span>
+            </div>
             <iron-icon icon="done" hidden$="[[!item.enabled]]">
             </iron-icon>
           </paper-item>
diff --git a/chrome/browser/resources/settings/languages_page/manage_languages_page.js b/chrome/browser/resources/settings/languages_page/manage_languages_page.js
index cf92005f..1fe8ba4 100644
--- a/chrome/browser/resources/settings/languages_page/manage_languages_page.js
+++ b/chrome/browser/resources/settings/languages_page/manage_languages_page.js
@@ -22,7 +22,7 @@
     },
 
     /**
-     * @type {LanguagesModel|undefined}
+     * @type {!LanguagesModel|undefined}
      */
     languages: {
       type: Object,
@@ -30,7 +30,8 @@
     },
 
     /**
-     * @private {Array<{code: string, displayName: string, enabled: boolean}>|
+     * @private {!Array<!{code: string, displayName: string,
+     *                    nativeDisplayName: string, enabled: boolean}>|
      *           undefined}
      */
     availableLanguages_: Array,
@@ -42,7 +43,7 @@
 
   /**
    * Handler for removing a language.
-   * @param {!{model: !{item: !Language}}} e
+   * @param {!{model: !{item: !LanguageInfo}}} e
    * @private
    */
   onRemoveLanguageTap_: function(e) {
@@ -59,38 +60,45 @@
   },
 
   /**
-   * True if a language is not the prospective UI language or the last remaining
-   * language.
+   * True if a language is not the current or prospective UI language.
    * @param {string} languageCode
-   * @param {!Array<!LanguageInfo>} enableLanguage
-   * @private
+   * @param {!Array<!LanguageInfo>} prospectiveUILanguage
    * @return {boolean}
+   * @private
    */
-  canRemoveLanguage_: function(languageCode, enabledLanguages) {
-    var appLocale = this.prefs.intl.app_locale.value || navigator.language;
-    if (languageCode == appLocale)
+  canRemoveLanguage_: function(languageCode, prospectiveUILanguage) {
+    if (languageCode == navigator.language ||
+        languageCode == prospectiveUILanguage) {
       return false;
-    if (enabledLanguages.length == 1)
-      return false;
+    }
+    assert(this.languages.enabledLanguages.length > 1);
     return true;
   },
 
   /**
-   * Updates the available languages to be bound to the iron-list.
-   * TODO(michaelpg): Update properties of individual items instead of
-   *     rebuilding entire list.
+   * Updates the available languages that are bound to the iron-list.
    * @private
    */
   enabledLanguagesChanged_: function() {
-    var availableLanguages = [];
-    for (var i = 0; i < this.languages.supportedLanguages.length; i++) {
-      var language = this.languages.supportedLanguages[i];
-      availableLanguages.push({
-        code: language.code,
-        displayName: language.displayName,
-        enabled: this.$.languages.isEnabled(language.code)
-      });
+    if (!this.availableLanguages_) {
+      var availableLanguages = [];
+      for (var i = 0; i < this.languages.supportedLanguages.length; i++) {
+        var language = this.languages.supportedLanguages[i];
+        availableLanguages.push({
+          code: language.code,
+          displayName: language.displayName,
+          nativeDisplayName: language.nativeDisplayName,
+          enabled: this.$.languages.isEnabled(language.code)
+        });
+      }
+      // Set the Polymer property after building the full array.
+      this.availableLanguages_ = availableLanguages;
+    } else {
+      // Update the available languages in place.
+      for (var i = 0; i < this.availableLanguages_.length; i++) {
+        this.set('availableLanguages_.' + i + '.enabled',
+                 this.$.languages.isEnabled(this.availableLanguages_[i].code));
+      }
     }
-    this.availableLanguages_ = availableLanguages;
   },
 });
diff --git a/chrome/browser/resources/settings/on_startup_page/on_startup_page.html b/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
index b48a0cbe..2ba1692 100644
--- a/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
+++ b/chrome/browser/resources/settings/on_startup_page/on_startup_page.html
@@ -12,7 +12,7 @@
       href="chrome://md-settings/settings_page/settings_page.css">
   <link rel="import" type="css" href="on_startup_shared.css">
   <template>
-    <cr-settings-animated-pages id="pages" current-route="{{currentRoute}}"
+    <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="on-startup">
       <neon-animatable id="">
         <div id="locationLabel" i18n-content="onStartup"></div>
@@ -39,7 +39,7 @@
         <cr-settings-startup-urls-page prefs="{{prefs}}">
         </cr-settings-startup-urls-page>
       </neon-animatable>
-    </cr-settings-animated-pages>
+    </settings-animated-pages>
   </template>
   <script src="on_startup_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 42abf47..b4d5fe0 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -15,7 +15,7 @@
       href="chrome://md-settings/settings_page/settings_page.css">
   <link rel="import" type="css" href="privacy_page.css">
   <template>
-    <cr-settings-animated-pages id="pages" current-route="{{currentRoute}}"
+    <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="privacy">
       <neon-animatable id="">
         <p class="privacy-explanation"
@@ -98,7 +98,7 @@
         <cr-settings-clear-browsing-data-page prefs="{{prefs}}">
         </cr-settings-clear-browsing-data-page>
       </neon-animatable>
-    </cr-settings-animated-pages>
+    </settings-animated-pages>
   </template>
   <script src="privacy_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html
index a7a85c7..ee412ac 100644
--- a/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -11,7 +11,7 @@
       href="chrome://md-settings/settings_page/settings_page.css">
   <link rel="import" type="css" href="search_page.css">
   <template>
-    <cr-settings-animated-pages id="pages" current-route="{{currentRoute}}"
+    <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="search">
       <neon-animatable id="">
         <p i18n-content="searchExplanation"></p>
@@ -44,7 +44,7 @@
         </settings-subheader>
         <p i18n-content="searchExplanation"></p>
       </neon-animatable>
-    </cr-settings-animated-pages>
+    </settings-animated-pages>
   </template>
   <script src="search_page.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html
index 88f930a6..231b3d9 100644
--- a/chrome/browser/resources/settings/settings.html
+++ b/chrome/browser/resources/settings/settings.html
@@ -3,6 +3,7 @@
 <head>
   <meta charset="utf-8">
   <title>Settings</title>
+  <base href="chrome://md-settings">
   <script src="chrome://resources/js/polymer_config.js"></script>
   <script src="chrome://resources/js/load_time_data.js"></script>
   <script src="chrome://md-settings/strings.js"></script>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html
index d90d351..cc17ba24 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.html
+++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -10,11 +10,9 @@
     <iron-pages id="pageContainer" attr-for-selected="data-route-page"
         selected="[[getSelectedPage_(currentRoute)]]">
       <cr-settings-basic-page data-route-page="basic" prefs="{{prefs}}"
-          expand-container="[[expandContainer]]"
           current-route="{{currentRoute}}">
       </cr-settings-basic-page>
       <cr-settings-advanced-page data-route-page="advanced" prefs="{{prefs}}"
-          expand-container="[[expandContainer]]"
           current-route="{{currentRoute}}">
       </cr-settings-advanced-page>
     </iron-pages>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js
index 401d14a..77bd76134 100644
--- a/chrome/browser/resources/settings/settings_main/settings_main.js
+++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -36,19 +36,38 @@
     currentRoute: {
       type: Object,
       notify: true,
-    },
-
-    /**
-     * Container that determines the sizing of expanded sections.
-     */
-    expandContainer: {
-      type: Object,
+      observer: 'currentRouteChanged_',
     },
   },
 
-  /** @override */
-  ready: function() {
-    this.expandContainer = this.$.pageContainer;
+  listeners: {
+    'expand-animation-complete': 'onExpandAnimationComplete_',
+  },
+
+  /** @private */
+  currentRouteChanged_: function(newRoute, oldRoute) {
+    var pageContainer = this.$.pageContainer;
+    if (!oldRoute) {
+      pageContainer.classList.toggle('expanded', newRoute.section);
+      return;
+    }
+
+    // For contraction only, apply new styling immediately.
+    if (!newRoute.section && oldRoute.section) {
+      pageContainer.classList.remove('expanded');
+
+      // TODO(tommycli): Save and restore scroll position. crbug.com/537359.
+      pageContainer.scrollTop = 0;
+    }
+  },
+
+  /** @private */
+  onExpandAnimationComplete_: function() {
+    if (this.currentRoute.section) {
+      var pageContainer = this.$.pageContainer;
+      pageContainer.classList.add('expanded');
+      pageContainer.scrollTop = 0;
+    }
   },
 
   /** @private */
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index e617937..9185c25 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -66,10 +66,12 @@
             <iron-icon icon="file-download" item-icon></iron-icon>
             <span i18n-content="downloadsPageTitle"></span>
           </paper-icon-item>
+<if expr="chromeos">
           <paper-icon-item>
             <iron-icon icon="accessibility" item-icon></iron-icon>
             <span i18n-content="a11yPageTitle"></span>
           </paper-icon-item>
+</if>
           <paper-icon-item>
             <iron-icon icon="notification:sync" item-icon></iron-icon>
             <span i18n-content="syncPageTitle"></span>
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.css b/chrome/browser/resources/settings/settings_page/settings_animated_pages.css
index b4794eb..6de1938 100644
--- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.css
+++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.css
@@ -6,10 +6,6 @@
  * @fileoverview
  * Styles used for animating settings subpages.
  */
-neon-animated-pages ::content > * {
+neon-animated-pages ::content > .iron-selected {
   position: static;
 }
-
-neon-animated-pages ::content > .neon-animating {
-  position: absolute;
-}
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
index 3915e8e..fcd6b9d 100644
--- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
+++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
@@ -10,11 +10,10 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html">
 
-<dom-module id="cr-settings-animated-pages">
+<dom-module id="settings-animated-pages">
   <link rel="import" type="css" href="settings_animated_pages.css">
   <template>
-    <neon-animated-pages id="animatedPages" attr-for-selected="id"
-        selected="main">
+    <neon-animated-pages id="animatedPages" attr-for-selected="id">
       <content select="*"></content>
     </neon-animated-pages>
   </template>
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
index 6df51fd..e4c6e96 100644
--- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
+++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -4,21 +4,21 @@
 
 /**
  * @fileoverview
- * 'cr-settings-animated-pages' is a container for a page and animated subpages.
+ * 'settings-animated-pages' is a container for a page and animated subpages.
  * It provides a set of common behaviors and animations.
  *
  * Example:
  *
- *    <cr-settings-animated-pages current-route="{{currentRoute}}"
+ *    <settings-animated-pages current-route="{{currentRoute}}"
           route-root="advanced/privacy" redirect-root-route-to="advanced">
  *      <!-- Insert your section controls here -->
- *    </cr-settings-animated-pages>
+ *    </settings-animated-pages>
  *
  * @group Chrome Settings Elements
- * @element cr-settings-animated-pages
+ * @element settings-animated-pages
  */
 Polymer({
-  is: 'cr-settings-animated-pages',
+  is: 'settings-animated-pages',
 
   properties: {
     /**
@@ -58,10 +58,10 @@
     var newRouteIsSubpage = newRoute && newRoute.section == this.section;
     var oldRouteIsSubpage = oldRoute && oldRoute.section == this.section;
 
-    // If two routes are at the same level, or if either the new or old route is
-    // not a subpage, fade in and out.
     if (!newRouteIsSubpage || !oldRouteIsSubpage ||
         newRoute.subpage.length == oldRoute.subpage.length) {
+      // If two routes are at the same level, or if either the new or old route
+      // is not a subpage, fade in and out.
       this.$.animatedPages.exitAnimation = 'fade-out-animation';
       this.$.animatedPages.entryAnimation = 'fade-in-animation';
     } else {
@@ -75,14 +75,8 @@
       }
     }
 
-    if (newRouteIsSubpage) {
-      // TODO(tommycli): Support paths where the final component carries
-      // data rather than referring to a specific subpage.
-      // E.g. internet > internet/known-networks > internet/detail/wifi1_guid
-      this.$.animatedPages.selected = newRoute.subpage.slice(-1)[0];
-    } else {
-      this.$.animatedPages.selected = '';
-    }
+    this.$.animatedPages.selected =
+        newRouteIsSubpage ? newRoute.subpage.slice(-1)[0] : '';
   },
 
   /**
diff --git a/chrome/browser/resources/settings/settings_page/settings_page.css b/chrome/browser/resources/settings/settings_page/settings_page.css
index d0aeb38..615b91d 100644
--- a/chrome/browser/resources/settings/settings_page/settings_page.css
+++ b/chrome/browser/resources/settings/settings_page/settings_page.css
@@ -64,3 +64,7 @@
   /* Same padding as paper-icon-button. */
   padding: 8px;
 }
+
+.button-strip {
+  text-align: end;
+}
diff --git a/chrome/browser/resources/settings/settings_page/settings_router.js b/chrome/browser/resources/settings/settings_page/settings_router.js
index 62f51b61..2c73b3e 100644
--- a/chrome/browser/resources/settings/settings_page/settings_router.js
+++ b/chrome/browser/resources/settings/settings_page/settings_router.js
@@ -153,6 +153,13 @@
       subpage: ['manage-languages'],
       subpageTitles: ['manageLanguagesPageTitle'],
     },
+    {
+      url: '/languages/edit',
+      page: 'advanced',
+      section: 'languages',
+      subpage: ['language-detail'],
+      subpageTitles: ['manageLanguagesPageTitle'],
+    },
   ],
 
   /**
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.html b/chrome/browser/resources/settings/settings_page/settings_section.html
index 6a1e32d..6204a07 100644
--- a/chrome/browser/resources/settings/settings_page/settings_section.html
+++ b/chrome/browser/resources/settings/settings_page/settings_section.html
@@ -2,7 +2,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-material/paper-material.html">
 
-<dom-module id="cr-settings-section">
+<dom-module id="settings-section">
   <link rel="import" type="css" href="settings_section.css">
   <template>
     <div id="header">
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js
index ee64994..974fb95 100644
--- a/chrome/browser/resources/settings/settings_page/settings_section.js
+++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -4,20 +4,20 @@
 
 /**
  * @fileoverview
- * 'cr-settings-section' shows a paper material themed section with a header
+ * 'settings-section' shows a paper material themed section with a header
  * which shows its page title.
  *
  * Example:
  *
- *    <cr-settings-section page-title="[[pageTitle]]">
+ *    <settings-section page-title="[[pageTitle]]">
  *      <!-- Insert your section controls here -->
- *    </cr-settings-section>
+ *    </settings-section>
  *
  * @group Chrome Settings Elements
- * @element cr-settings-section
+ * @element settings-section
  */
 Polymer({
-  is: 'cr-settings-section',
+  is: 'settings-section',
 
   behaviors: [
     Polymer.NeonAnimationRunnerBehavior,
@@ -45,13 +45,6 @@
      */
     pageTitle: String,
 
-    /**
-     * Container that determines the sizing of expanded sections.
-     */
-    expandContainer: {
-      type: Object,
-    },
-
     animationConfig: {
       value: function() {
         return {
@@ -73,18 +66,35 @@
   },
 
   /** @private */
-  expanded_: false,
+  currentRouteChanged_: function(newRoute, oldRoute) {
+    var newExpanded = newRoute.section == this.section;
+    var oldExpanded = oldRoute && oldRoute.section == this.section;
 
-  /** @private */
-  currentRouteChanged_: function() {
-    var expanded = this.currentRoute.section == this.section;
+    var visible = newExpanded || this.currentRoute.section == '';
 
-    if (expanded != this.expanded_) {
-      this.expanded_ = expanded;
-      this.playAnimation(expanded ? 'expand' : 'collapse');
+    // If the user navigates directly to a subpage, skip all the animations.
+    if (!oldRoute) {
+      if (newExpanded) {
+        // If we navigate directly to a subpage, skip animations.
+        this.classList.add('expanded');
+      } else if (!visible) {
+        this.hidden = true;
+        this.$.card.elevation = 0;
+      }
+
+      return;
     }
 
-    var visible = expanded || this.currentRoute.section == '';
+    if (newExpanded && !oldExpanded) {
+      this.playAnimation('expand');
+    } else if (oldExpanded && !newExpanded) {
+      // For contraction, we defer the animation to allow
+      // settings-animated-pages to reflow the new page correctly.
+      this.async(function() {
+        this.playAnimation('collapse');
+      }.bind(this));
+    }
+
     this.$.card.elevation = visible ? 1 : 0;
 
     // Remove 'hidden' class immediately, but defer adding it if we are invisble
@@ -97,7 +107,7 @@
   onExpandAnimationComplete_: function() {
     this.hidden = this.currentRoute.section != '' &&
                   this.currentRoute.section != this.section;
-  }
+  },
 });
 
 Polymer({
@@ -110,7 +120,7 @@
   configure: function(config) {
     var section = config.node;
     var card = section.$.card;
-    var containerRect = section.expandContainer.getBoundingClientRect();
+    var containerRect = section.offsetParent.getBoundingClientRect();
     var cardRect = card.getBoundingClientRect();
 
     // Set placeholder height so the page does not reflow during animation.
@@ -132,15 +142,12 @@
     var section = config.node;
     section.classList.remove('neon-animating');
     section.classList.add('expanded');
-    section.expandContainer.classList.add('expanded');
 
     // This event fires on itself as well, but that is benign.
-    var sections = section.parentNode.querySelectorAll('cr-settings-section');
+    var sections = section.parentNode.querySelectorAll('settings-section');
     for (var i = 0; i < sections.length; ++i) {
       sections[i].fire('expand-animation-complete');
     }
-
-    section.expandContainer.scrollTop = 0;
   }
 });
 
@@ -153,17 +160,16 @@
 
   configure: function(config) {
     var section = config.node;
-    var oldRect = section.expandContainer.getBoundingClientRect();
+    var oldRect = section.offsetParent.getBoundingClientRect();
 
     section.classList.remove('expanded');
-    section.expandContainer.classList.remove('expanded');
 
-    // Get the placeholder coordinates before reflowing.
-    var newRect = section.$.placeholder.getBoundingClientRect();
+    var card = section.$.card;
+    var newRect = card.getBoundingClientRect();
 
     section.classList.add('neon-animating');
 
-    this._effect = new KeyframeEffect(section.$.card, [
+    this._effect = new KeyframeEffect(card, [
       {'top': oldRect.top + 'px', 'height': oldRect.height + 'px'},
       {'top': newRect.top + 'px', 'height': newRect.height + 'px'},
     ], this.timingFromConfig(config));
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index d43f9df9..6dc9685 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -214,6 +214,17 @@
       <structure name="IDR_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_PAGE_JS"
                  file="languages_page/manage_languages_page.js"
                  type="chrome_html" />
+      <structure name="IDR_SETTINGS_LANGUAGES_LANGUAGE_DETAIL_PAGE_CSS"
+                 file="languages_page/language_detail_page.css"
+                 type="chrome_html" />
+      <structure name="IDR_SETTINGS_LANGUAGES_LANGUAGE_DETAIL_PAGE_HTML"
+                 file="languages_page/language_detail_page.html"
+                 type="chrome_html"
+                 flattenhtml="true"
+                 allowexternalscript="true" />
+      <structure name="IDR_SETTINGS_LANGUAGES_LANGUAGE_DETAIL_PAGE_JS"
+                 file="languages_page/language_detail_page.js"
+                 type="chrome_html" />
       <structure name="IDR_SETTINGS_POLICY_CONTROLLABLE_HTML"
                  file="policy_controllable/policy_controllable.html"
                  type="chrome_html" />
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc
index ee61140..fd461dbc 100644
--- a/chrome/browser/safe_browsing/local_database_manager.cc
+++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -862,6 +862,10 @@
 void LocalSafeBrowsingDatabaseManager::RequestFullHash(
     SafeBrowsingCheck* check) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!enabled_)
+    return;
+
   bool is_download = check->check_type == safe_browsing_util::BINURL;
   sb_service_->protocol_manager()->GetFullHash(
       check->prefix_hits,
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index c74fb7a2..342e59d 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -172,8 +172,11 @@
   reporting_info.extra_suffix = GetExtraMetricsSuffix();
   reporting_info.rappor_prefix = GetRapporPrefix();
   reporting_info.rappor_report_type = rappor::SAFEBROWSING_RAPPOR_TYPE;
-  set_metrics_helper(new ChromeMetricsHelper(
-      web_contents, request_url(), reporting_info, GetSamplingEventName()));
+  set_metrics_helper(
+      make_scoped_ptr(new ChromeMetricsHelper(web_contents, request_url(),
+                                              reporting_info,
+                                              GetSamplingEventName()))
+          .Pass());
   metrics_helper()->RecordUserDecision(
       security_interstitials::MetricsHelper::SHOW);
   metrics_helper()->RecordUserInteraction(
diff --git a/chrome/browser/search/instant_unittest_base.cc b/chrome/browser/search/instant_unittest_base.cc
index 93a8b24a..3ba7101 100644
--- a/chrome/browser/search/instant_unittest_base.cc
+++ b/chrome/browser/search/instant_unittest_base.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/google/core/browser/google_pref_names.h"
 #include "components/google/core/browser/google_url_tracker.h"
 #include "components/search/search.h"
@@ -93,7 +93,7 @@
   BrowserWithTestWindowTest::SetUp();
 
   template_url_service_ = TemplateURLServiceFactory::GetForProfile(profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service_);
+  search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service_);
 
   UIThreadSearchTermsData::SetGoogleBaseURL("https://www.google.com/");
   SetUserSelectedDefaultSearchProvider("{google:baseURL}");
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index c7ed494..8807c059 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -18,7 +18,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/google/core/browser/google_switches.h"
 #include "components/search/search.h"
 #include "components/search_engines/search_engines_switches.h"
@@ -50,7 +50,7 @@
         profile(), &TemplateURLServiceFactory::BuildInstanceFor);
     TemplateURLService* template_url_service =
         TemplateURLServiceFactory::GetForProfile(profile());
-    ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
+    search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
     SetSearchProvider(true, false);
   }
 
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.cc b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
index 8cd6fd6..ed1c1b4c 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.cc
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
@@ -21,7 +21,7 @@
 #endif
 
 #if !defined(OS_ANDROID)
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #endif
 
 namespace {
@@ -47,44 +47,43 @@
 
 ChromeTabRestoreServiceClient::~ChromeTabRestoreServiceClient() {}
 
-sessions::TabRestoreServiceDelegate*
-ChromeTabRestoreServiceClient::CreateTabRestoreServiceDelegate(
+sessions::LiveTabContext* ChromeTabRestoreServiceClient::CreateLiveTabContext(
     int host_desktop_type,
     const std::string& app_name) {
 #if defined(OS_ANDROID)
-  // Android does not support TabRestoreServiceDelegate, as tab persistence
+  // Android does not support LiveTabContext, as tab persistence
   // is implemented on the Java side.
   return nullptr;
 #else
-  return BrowserTabRestoreServiceDelegate::Create(
+  return BrowserLiveTabContext::Create(
       profile_, static_cast<chrome::HostDesktopType>(host_desktop_type),
       app_name);
 #endif
 }
 
-sessions::TabRestoreServiceDelegate*
-ChromeTabRestoreServiceClient::FindTabRestoreServiceDelegateForTab(
+sessions::LiveTabContext*
+ChromeTabRestoreServiceClient::FindLiveTabContextForTab(
     const sessions::LiveTab* tab) {
 #if defined(OS_ANDROID)
-  // Android does not support TabRestoreServiceDelegate, as tab persistence
+  // Android does not support LiveTabContext, as tab persistence
   // is implemented on the Java side.
   return nullptr;
 #else
-  return BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+  return BrowserLiveTabContext::FindContextForWebContents(
       static_cast<const sessions::ContentLiveTab*>(tab)->web_contents());
 #endif
 }
 
-sessions::TabRestoreServiceDelegate*
-ChromeTabRestoreServiceClient::FindTabRestoreServiceDelegateWithID(
+sessions::LiveTabContext*
+ChromeTabRestoreServiceClient::FindLiveTabContextWithID(
     SessionID::id_type desired_id,
     int host_desktop_type) {
 #if defined(OS_ANDROID)
-  // Android does not support TabRestoreServiceDelegate, as tab persistence
+  // Android does not support LiveTabContext, as tab persistence
   // is implemented on the Java side.
   return nullptr;
 #else
-  return BrowserTabRestoreServiceDelegate::FindDelegateWithID(
+  return BrowserLiveTabContext::FindContextWithID(
       desired_id, static_cast<chrome::HostDesktopType>(host_desktop_type));
 #endif
 }
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.h b/chrome/browser/sessions/chrome_tab_restore_service_client.h
index 27e97a0..ddc1d45 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.h
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.h
@@ -19,12 +19,12 @@
 
  private:
   // TabRestoreServiceClient:
-  sessions::TabRestoreServiceDelegate* CreateTabRestoreServiceDelegate(
+  sessions::LiveTabContext* CreateLiveTabContext(
       int host_desktop_type,
       const std::string& app_name) override;
-  sessions::TabRestoreServiceDelegate* FindTabRestoreServiceDelegateForTab(
+  sessions::LiveTabContext* FindLiveTabContextForTab(
       const sessions::LiveTab* tab) override;
-  sessions::TabRestoreServiceDelegate* FindTabRestoreServiceDelegateWithID(
+  sessions::LiveTabContext* FindLiveTabContextWithID(
       SessionID::id_type desired_id,
       int host_desktop_type) override;
   bool ShouldTrackURLForRestore(const GURL& url) override;
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index cf2254e7..a4ff024e 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabrestore.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -382,11 +383,15 @@
     // windows has the same id as specified in active_window_id.
     Browser* browser_to_activate = nullptr;
 
-    // Determine if there is a visible window.
+    // Determine if there is a visible window, or if the active window exists.
+    // Even if all windows are ui::SHOW_STATE_MINIMIZED, if one of them is the
+    // active window it will be made visible by the call to
+    // browser_to_activate->window()->Activate() later on in this method.
     bool has_visible_browser = false;
     for (std::vector<sessions::SessionWindow*>::iterator i = windows->begin();
          i != windows->end(); ++i) {
-      if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED)
+      if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED ||
+          (*i)->window_id.id() == active_window_id)
         has_visible_browser = true;
     }
 
@@ -775,7 +780,7 @@
 
 // static
 void SessionRestore::RestoreSessionAfterCrash(Browser* browser) {
-   uint32 behavior = 0;
+  uint32 behavior = 0;
   if (browser->tab_strip_model()->count() == 1) {
     const content::WebContents* active_tab =
         browser->tab_strip_model()->GetWebContentsAt(0);
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 44d726d..3ea6584 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sessions/session_restore.h"
@@ -24,6 +25,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
@@ -567,7 +569,14 @@
   EXPECT_EQ(http_status_code, entry->GetHttpStatusCode());
 }
 
-IN_PROC_BROWSER_TEST_F(SessionRestoreTest, WindowWithOneTab) {
+// Flaky on Linux. https://crbug.com/537592.
+#if defined (OS_LINUX)
+#define MAYBE_WindowWithOneTab DISABLED_WindowWithOneTab
+#else
+#define MAYBE_WindowWithOneTab WindowWithOneTab
+#endif
+
+IN_PROC_BROWSER_TEST_F(SessionRestoreTest, MAYBE_WindowWithOneTab) {
   GURL url(ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(FILE_PATH_LITERAL("title1.html"))));
diff --git a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
index 8cc59ccc..6209c432 100644
--- a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
+++ b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/defaults.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_iterator.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc
index 377e8ae..3e049c0 100644
--- a/chrome/browser/signin/easy_unlock_service.cc
+++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -36,6 +36,7 @@
 #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h"
 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
 #include "components/proximity_auth/screenlock_bridge.h"
 #include "components/proximity_auth/switches.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
@@ -283,6 +284,7 @@
   proximity_auth::CryptAuthGCMManager::RegisterPrefs(registry);
   proximity_auth::CryptAuthDeviceManager::RegisterPrefs(registry);
   proximity_auth::CryptAuthEnrollmentManager::RegisterPrefs(registry);
+  proximity_auth::ProximityAuthPrefManager::RegisterPrefs(registry);
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery))
diff --git a/chrome/browser/signin/easy_unlock_service.h b/chrome/browser/signin/easy_unlock_service.h
index d0ae1dd..518e316 100644
--- a/chrome/browser/signin/easy_unlock_service.h
+++ b/chrome/browser/signin/easy_unlock_service.h
@@ -108,6 +108,7 @@
   // Gets/Sets the remote devices list.
   virtual const base::ListValue* GetRemoteDevices() const = 0;
   virtual void SetRemoteDevices(const base::ListValue& devices) = 0;
+  virtual void SetRemoteBleDevices(const base::ListValue& devices) = 0;
 
   // Runs the flow for turning Easy unlock off.
   virtual void RunTurnOffFlow() = 0;
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc
index cd967d2..7f1ebabb 100644
--- a/chrome/browser/signin/easy_unlock_service_regular.cc
+++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -33,6 +33,7 @@
 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
 #include "components/proximity_auth/cryptauth_enroller_factory_impl.h"
 #include "components/proximity_auth/logging/logging.h"
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
 #include "components/proximity_auth/screenlock_bridge.h"
 #include "components/proximity_auth/switches.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
@@ -89,6 +90,11 @@
   return device_manager_.get();
 }
 
+proximity_auth::ProximityAuthPrefManager*
+EasyUnlockServiceRegular::GetProximityAuthPrefManager() {
+  return pref_manager_.get();
+}
+
 EasyUnlockService::Type EasyUnlockServiceRegular::GetType() const {
   return EasyUnlockService::TYPE_REGULAR;
 }
@@ -223,6 +229,23 @@
 #endif
 }
 
+// This method is called from easyUnlock.setRemoteDevice JS API. It's used
+// here to set the (public key, device address) pair for BLE devices.
+void EasyUnlockServiceRegular::SetRemoteBleDevices(
+    const base::ListValue& devices) {
+  DCHECK(devices.GetSize() == 1);
+  const base::DictionaryValue* dict = nullptr;
+  if (devices.GetDictionary(0, &dict)) {
+    std::string address, public_key;
+    if (dict->GetString("bluetoothAddress", &address) &&
+        dict->GetString("psk", &public_key)) {
+      GetProximityAuthPrefManager()->AddOrUpdateDevice(address, public_key);
+    } else {
+      PA_LOG(ERROR) << "Missing public key or device address";
+    }
+  }
+}
+
 void EasyUnlockServiceRegular::RunTurnOffFlow() {
   if (turn_off_flow_status_ == PENDING)
     return;
@@ -316,8 +339,11 @@
 
 #if defined(OS_CHROMEOS)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery))
+          proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery)) {
     InitializeCryptAuth();
+    pref_manager_.reset(
+        new proximity_auth::ProximityAuthPrefManager(profile()->GetPrefs()));
+  }
 #endif
 
   OnPrefsChanged();
diff --git a/chrome/browser/signin/easy_unlock_service_regular.h b/chrome/browser/signin/easy_unlock_service_regular.h
index d1febbd..fb46bc4 100644
--- a/chrome/browser/signin/easy_unlock_service_regular.h
+++ b/chrome/browser/signin/easy_unlock_service_regular.h
@@ -34,6 +34,7 @@
 class CryptAuthGCMManager;
 class CryptAuthEnrollmentManager;
 class CryptAuthDeviceManager;
+class ProximityAuthPrefManager;
 }
 
 class EasyUnlockAppManager;
@@ -58,6 +59,10 @@
   // synced devices from CryptAuth.
   proximity_auth::CryptAuthDeviceManager* GetCryptAuthDeviceManager();
 
+  // Returns the ProximityAuthPrefManager, which manages the profile's
+  // prefs for proximity_auth classes.
+  proximity_auth::ProximityAuthPrefManager* GetProximityAuthPrefManager();
+
  private:
   // EasyUnlockService implementation:
   EasyUnlockService::Type GetType() const override;
@@ -68,6 +73,7 @@
   void ClearPermitAccess() override;
   const base::ListValue* GetRemoteDevices() const override;
   void SetRemoteDevices(const base::ListValue& devices) override;
+  void SetRemoteBleDevices(const base::ListValue& devices) override;
   void RunTurnOffFlow() override;
   void ResetTurnOffFlow() override;
   TurnOffFlowStatus GetTurnOffFlowStatus() const override;
@@ -156,6 +162,9 @@
   scoped_ptr<proximity_auth::CryptAuthEnrollmentManager> enrollment_manager_;
   scoped_ptr<proximity_auth::CryptAuthDeviceManager> device_manager_;
 
+  // Manager responsible for handling the prefs used by proximity_auth classes.
+  scoped_ptr<proximity_auth::ProximityAuthPrefManager> pref_manager_;
+
   base::WeakPtrFactory<EasyUnlockServiceRegular> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceRegular);
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
index e30ee92..61a3fd88 100644
--- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
+++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -144,6 +144,11 @@
   NOTREACHED();
 }
 
+void EasyUnlockServiceSignin::SetRemoteBleDevices(
+    const base::ListValue& devices) {
+  NOTREACHED();
+}
+
 void EasyUnlockServiceSignin::RunTurnOffFlow() {
   NOTREACHED();
 }
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
index 634de98d5..54514ba5 100644
--- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
+++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
@@ -70,6 +70,7 @@
   void ClearPermitAccess() override;
   const base::ListValue* GetRemoteDevices() const override;
   void SetRemoteDevices(const base::ListValue& devices) override;
+  void SetRemoteBleDevices(const base::ListValue& devices) override;
   void RunTurnOffFlow() override;
   void ResetTurnOffFlow() override;
   TurnOffFlowStatus GetTurnOffFlowStatus() const override;
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index 0c5f96c7..f7f8a21 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/sync/sync_global_error.h"
 #include "chrome/browser/sync/sync_global_error_factory.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.cc b/chrome/browser/ssl/bad_clock_blocking_page.cc
index 2d89b10..2d2f51d 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.cc
+++ b/chrome/browser/ssl/bad_clock_blocking_page.cc
@@ -23,6 +23,8 @@
 #include "chrome/browser/interstitials/chrome_metrics_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_preferences_util.h"
+#include "chrome/browser/ssl/cert_report_helper.h"
+#include "chrome/browser/ssl/ssl_cert_reporter.h"
 #include "chrome/browser/ssl/ssl_error_classification.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
@@ -175,6 +177,7 @@
     const net::SSLInfo& ssl_info,
     const GURL& request_url,
     const base::Time& time_triggered,
+    scoped_ptr<SSLCertReporter> ssl_cert_reporter,
     const base::Callback<void(bool)>& callback)
     : SecurityInterstitialPage(web_contents, request_url),
       callback_(callback),
@@ -183,16 +186,22 @@
       time_triggered_(time_triggered) {
   security_interstitials::MetricsHelper::ReportDetails reporting_info;
   reporting_info.metric_prefix = kMetricsName;
-  set_metrics_helper(new ChromeMetricsHelper(web_contents, request_url,
-                                             reporting_info, kMetricsName));
+  scoped_ptr<ChromeMetricsHelper> chrome_metrics_helper(new ChromeMetricsHelper(
+      web_contents, request_url, reporting_info, kMetricsName));
+  chrome_metrics_helper->StartRecordingCaptivePortalMetrics(false);
+  set_metrics_helper(chrome_metrics_helper.Pass());
   metrics_helper()->RecordUserInteraction(
       security_interstitials::MetricsHelper::TOTAL_VISITS);
 
+  cert_report_helper_.reset(new CertReportHelper(
+      ssl_cert_reporter.Pass(), web_contents, request_url, ssl_info,
+      certificate_reporting::ErrorReport::INTERSTITIAL_CLOCK,
+      false /* overridable */, metrics_helper()));
+
   // TODO(felt): Separate the clock statistics from the main ssl statistics.
-  scoped_ptr<SSLErrorClassification> classifier(
-      new SSLErrorClassification(web_contents, time_triggered_, request_url,
-                                 cert_error_, *ssl_info_.cert.get()));
-  classifier->RecordUMAStatistics(false);
+  SSLErrorClassification classifier(time_triggered_, request_url, cert_error_,
+                                    *ssl_info_.cert.get());
+  classifier.RecordUMAStatistics(false);
 }
 
 bool BadClockBlockingPage::ShouldCreateNewNavigation() const {
@@ -205,6 +214,7 @@
 }
 
 BadClockBlockingPage::~BadClockBlockingPage() {
+  metrics_helper()->RecordShutdownMetrics();
   if (!callback_.is_null()) {
     // Deny when the page is closed.
     NotifyDenyCertificate();
@@ -273,6 +283,8 @@
   ssl_info_.cert->GetPEMEncodedChain(&encoded_chain);
   load_time_data->SetString(
       "pem", base::JoinString(encoded_chain, base::StringPiece()));
+
+  cert_report_helper_->PopulateExtendedReportingOption(load_time_data);
 }
 
 void BadClockBlockingPage::OverrideEntry(NavigationEntry* entry) {
@@ -296,6 +308,11 @@
                          sct_ids, ssl_info_);
 }
 
+void BadClockBlockingPage::SetSSLCertReporterForTesting(
+    scoped_ptr<SSLCertReporter> ssl_cert_reporter) {
+  cert_report_helper_->SetSSLCertReporterForTesting(ssl_cert_reporter.Pass());
+}
+
 // This handles the commands sent from the interstitial JavaScript.
 // DO NOT reorder or change this logic without also changing the JavaScript!
 void BadClockBlockingPage::CommandReceived(const std::string& command) {
@@ -349,6 +366,8 @@
 }
 
 void BadClockBlockingPage::OnDontProceed() {
+  cert_report_helper_->FinishCertCollection(
+      certificate_reporting::ErrorReport::USER_DID_NOT_PROCEED);
   NotifyDenyCertificate();
 }
 
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.h b/chrome/browser/ssl/bad_clock_blocking_page.h
index b7e4a77..592dae86 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.h
+++ b/chrome/browser/ssl/bad_clock_blocking_page.h
@@ -10,8 +10,10 @@
 #include "base/callback.h"
 #include "base/time/time.h"
 #include "chrome/browser/interstitials/security_interstitial_page.h"
+#include "chrome/browser/ssl/ssl_cert_reporter.h"
 #include "net/ssl/ssl_info.h"
 
+class CertReportHelper;
 class GURL;
 
 // This class is responsible for showing/hiding the interstitial page that is
@@ -30,6 +32,7 @@
                        const net::SSLInfo& ssl_info,
                        const GURL& request_url,
                        const base::Time& time_triggered,
+                       scoped_ptr<SSLCertReporter> ssl_cert_reporter,
                        const base::Callback<void(bool)>& callback);
 
   ~BadClockBlockingPage() override;
@@ -37,6 +40,9 @@
   // InterstitialPageDelegate method:
   InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
 
+  void SetSSLCertReporterForTesting(
+      scoped_ptr<SSLCertReporter> ssl_cert_reporter);
+
  protected:
   // InterstitialPageDelegate implementation.
   void CommandReceived(const std::string& command) override;
@@ -53,7 +59,6 @@
   void NotifyDenyCertificate();
 
   base::Callback<void(bool)> callback_;
-
   const int cert_error_;
   const net::SSLInfo ssl_info_;
 
@@ -61,6 +66,8 @@
   // calculates all times relative to this.
   const base::Time time_triggered_;
 
+  scoped_ptr<CertReportHelper> cert_report_helper_;
+
   DISALLOW_COPY_AND_ASSIGN(BadClockBlockingPage);
 };
 
diff --git a/chrome/browser/ssl/captive_portal_metrics_recorder.cc b/chrome/browser/ssl/captive_portal_metrics_recorder.cc
new file mode 100644
index 0000000..4f8473f
--- /dev/null
+++ b/chrome/browser/ssl/captive_portal_metrics_recorder.cc
@@ -0,0 +1,120 @@
+// Copyright 2015 The Chromium Authors. 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/ssl/captive_portal_metrics_recorder.h"
+
+#include <vector>
+
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/web_contents.h"
+
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+#include "chrome/browser/captive_portal/captive_portal_service.h"
+#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
+#endif
+
+namespace {
+
+// Events for UMA. Do not reorder or change!
+enum SSLInterstitialCauseCaptivePortal {
+  CAPTIVE_PORTAL_ALL,
+  CAPTIVE_PORTAL_DETECTION_ENABLED,
+  CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
+  CAPTIVE_PORTAL_PROBE_COMPLETED,
+  CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
+  CAPTIVE_PORTAL_NO_RESPONSE,
+  CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
+  CAPTIVE_PORTAL_DETECTED,
+  CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
+  UNUSED_CAPTIVE_PORTAL_EVENT,
+};
+
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
+  UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal", event,
+                            UNUSED_CAPTIVE_PORTAL_EVENT);
+}
+#endif
+
+}  // namespace
+
+CaptivePortalMetricsRecorder::CaptivePortalMetricsRecorder(
+    content::WebContents* web_contents,
+    bool overridable)
+    : captive_portal_detection_enabled_(false),
+      captive_portal_probe_completed_(false),
+      captive_portal_no_response_(false),
+      captive_portal_detected_(false) {
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  overridable_ = overridable;
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  captive_portal_detection_enabled_ =
+      CaptivePortalServiceFactory::GetForProfile(profile)->enabled();
+  registrar_.Add(this, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
+                 content::Source<Profile>(profile));
+#endif
+}
+
+CaptivePortalMetricsRecorder::~CaptivePortalMetricsRecorder() {}
+
+void CaptivePortalMetricsRecorder::RecordCaptivePortalUMAStatistics() const {
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  RecordCaptivePortalEventStats(CAPTIVE_PORTAL_ALL);
+  if (captive_portal_detection_enabled_)
+    RecordCaptivePortalEventStats(
+        overridable_ ? CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE
+                     : CAPTIVE_PORTAL_DETECTION_ENABLED);
+  if (captive_portal_probe_completed_)
+    RecordCaptivePortalEventStats(
+        overridable_ ? CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE
+                     : CAPTIVE_PORTAL_PROBE_COMPLETED);
+  // Log only one of portal detected and no response results.
+  if (captive_portal_detected_)
+    RecordCaptivePortalEventStats(overridable_
+                                      ? CAPTIVE_PORTAL_DETECTED_OVERRIDABLE
+                                      : CAPTIVE_PORTAL_DETECTED);
+  else if (captive_portal_no_response_)
+    RecordCaptivePortalEventStats(overridable_
+                                      ? CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE
+                                      : CAPTIVE_PORTAL_NO_RESPONSE);
+#endif
+}
+
+void CaptivePortalMetricsRecorder::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  // When detection is disabled, captive portal service always sends
+  // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
+  if (!captive_portal_detection_enabled_)
+    return;
+  if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
+    captive_portal_probe_completed_ = true;
+    CaptivePortalService::Results* results =
+        content::Details<CaptivePortalService::Results>(details).ptr();
+    // If a captive portal was detected at any point when the interstitial was
+    // displayed, assume that the interstitial was caused by a captive portal.
+    // Example scenario:
+    // 1- Interstitial displayed and captive portal detected, setting the flag.
+    // 2- Captive portal detection automatically opens portal login page.
+    // 3- User logs in on the portal login page.
+    // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
+    // sure we don't clear the captive protal flag, since the interstitial was
+    // potentially caused by the captive portal.
+    captive_portal_detected_ =
+        captive_portal_detected_ ||
+        (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
+    // Also keep track of non-HTTP portals and error cases.
+    captive_portal_no_response_ =
+        captive_portal_no_response_ ||
+        (results->result == captive_portal::RESULT_NO_RESPONSE);
+  }
+#endif
+}
diff --git a/chrome/browser/ssl/captive_portal_metrics_recorder.h b/chrome/browser/ssl/captive_portal_metrics_recorder.h
new file mode 100644
index 0000000..46932cbb
--- /dev/null
+++ b/chrome/browser/ssl/captive_portal_metrics_recorder.h
@@ -0,0 +1,55 @@
+// Copyright 2015 The Chromium Authors. 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_SSL_CAPTIVE_PORTAL_METRICS_RECORDER_H_
+#define CHROME_BROWSER_SSL_CAPTIVE_PORTAL_METRICS_RECORDER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "net/cert/x509_certificate.h"
+#include "url/gurl.h"
+
+namespace content {
+class WebContents;
+}
+
+// This class helps the SSL interstitial record captive portal-specific
+// metrics. It should only be used on the UI thread because its implementation
+// uses captive_portal::CaptivePortalService which can only be accessed on the
+// UI thread.
+class CaptivePortalMetricsRecorder : public content::NotificationObserver {
+ public:
+  CaptivePortalMetricsRecorder(content::WebContents* web_contents,
+                               bool overridable);
+  ~CaptivePortalMetricsRecorder() override;
+
+  // Should be called when the interstitial is closing.
+  void RecordCaptivePortalUMAStatistics() const;
+
+ private:
+  typedef std::vector<std::string> Tokens;
+
+  // content::NotificationObserver:
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
+
+#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  bool overridable_;
+#endif
+  bool captive_portal_detection_enabled_;
+  // Did the probe complete before the interstitial was closed?
+  bool captive_portal_probe_completed_;
+  // Did the captive portal probe receive an error or get a non-HTTP response?
+  bool captive_portal_no_response_;
+  bool captive_portal_detected_;
+
+  content::NotificationRegistrar registrar_;
+};
+
+#endif  // CHROME_BROWSER_SSL_CAPTIVE_PORTAL_METRICS_RECORDER_H_
diff --git a/chrome/browser/ssl/security_state_model_browser_tests.cc b/chrome/browser/ssl/security_state_model_browser_tests.cc
index f14b4024..41e3bab 100644
--- a/chrome/browser/ssl/security_state_model_browser_tests.cc
+++ b/chrome/browser/ssl/security_state_model_browser_tests.cc
@@ -30,6 +30,7 @@
 #include "net/cert/cert_verify_result.h"
 #include "net/cert/mock_cert_verifier.h"
 #include "net/cert/x509_certificate.h"
+#include "net/dns/mock_host_resolver.h"
 #include "net/test/url_request/url_request_failed_job.h"
 #include "net/url_request/url_request_filter.h"
 
@@ -246,8 +247,39 @@
       browser()->tab_strip_model()->GetActiveWebContents(),
       SecurityStateModel::SECURITY_ERROR,
       SecurityStateModel::NO_DEPRECATED_SHA1,
+      SecurityStateModel::RAN_MIXED_CONTENT,
+      false /* expect cert status error */);
+
+  // Navigate to an HTTPS page that runs and displays mixed content.
+  ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+      "files/ssl/page_runs_and_displays_insecure_content.html",
+      test_server()->host_port_pair(), &replacement_path));
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_.GetURL(replacement_path));
+  CheckSecurityInfoForSecure(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      SecurityStateModel::SECURITY_ERROR,
+      SecurityStateModel::NO_DEPRECATED_SHA1,
       SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT,
       false /* expect cert status error */);
+
+  // Navigate to an HTTPS page that runs mixed content in an iframe.
+  net::HostPortPair host_port_pair =
+      net::HostPortPair::FromURL(https_server_.GetURL("/"));
+  host_port_pair.set_host("different-host.test");
+  host_resolver()->AddRule("different-host.test",
+                           https_server_.GetURL("/").host());
+  ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+      "files/ssl/page_runs_insecure_content_in_iframe.html", host_port_pair,
+      &replacement_path));
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_.GetURL(replacement_path));
+  CheckSecurityInfoForSecure(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      SecurityStateModel::SECURITY_ERROR,
+      SecurityStateModel::NO_DEPRECATED_SHA1,
+      SecurityStateModel::RAN_MIXED_CONTENT,
+      false /* expect cert status error */);
 }
 
 // Same as the test above but with a long-lived SHA1 cert.
@@ -309,6 +341,19 @@
       browser()->tab_strip_model()->GetActiveWebContents(),
       SecurityStateModel::SECURITY_ERROR,
       SecurityStateModel::DEPRECATED_SHA1_BROKEN,
+      SecurityStateModel::RAN_MIXED_CONTENT,
+      false /* expect cert status error */);
+
+  // Navigate to an HTTPS page that runs and displays mixed content.
+  ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+      "files/ssl/page_runs_and_displays_insecure_content.html",
+      test_server()->host_port_pair(), &replacement_path));
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_.GetURL(replacement_path));
+  CheckSecurityInfoForSecure(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      SecurityStateModel::SECURITY_ERROR,
+      SecurityStateModel::DEPRECATED_SHA1_BROKEN,
       SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT,
       false /* expect cert status error */);
 }
@@ -451,10 +496,4 @@
                              false /* expect cert status error */);
 }
 
-// TODO(estark): https://crbug.com/530359
-// Test the following cases:
-// - warning SHA1 (2016 expiration)
-// - active mixed content + warning SHA1
-// - broken HTTPS + warning SHA1
-
 }  // namespace
diff --git a/chrome/browser/ssl/security_state_model_unittest.cc b/chrome/browser/ssl/security_state_model_unittest.cc
new file mode 100644
index 0000000..7701a0b
--- /dev/null
+++ b/chrome/browser/ssl/security_state_model_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright 2015 The Chromium Authors. 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/ssl/security_state_model.h"
+
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/cert_store.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/x509_certificate.h"
+#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_certificate_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kUrl[] = "https://foo.test";
+
+void GetTestSSLStatus(int process_id, content::SSLStatus* ssl_status) {
+  content::CertStore* cert_store = content::CertStore::GetInstance();
+  const scoped_refptr<net::X509Certificate>& cert =
+      net::ImportCertFromFile(net::GetTestCertsDirectory(), "sha1_2016.pem");
+  ASSERT_TRUE(cert);
+  ssl_status->cert_id = cert_store->StoreCert(cert.get(), process_id);
+  EXPECT_GT(ssl_status->cert_id, 0);
+  ssl_status->cert_status = net::CERT_STATUS_SHA1_SIGNATURE_PRESENT;
+  ssl_status->security_bits = 256;
+  ssl_status->connection_status = net::SSL_CONNECTION_VERSION_TLS1_2
+                                  << net::SSL_CONNECTION_VERSION_SHIFT;
+}
+
+class SecurityStateModelTest : public ChromeRenderViewHostTestHarness {};
+
+// Tests that SHA1-signed certificates expiring in 2016 downgrade the
+// security state of the page.
+TEST_F(SecurityStateModelTest, SHA1Warning) {
+  GURL url(kUrl);
+  Profile* test_profile = profile();
+  SecurityStateModel::SecurityInfo security_info;
+  content::SSLStatus ssl_status;
+  ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status));
+  SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile,
+                                             &security_info);
+  EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_WARNING,
+            security_info.sha1_deprecation_status);
+  EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level);
+}
+
+// Tests that SHA1 warnings don't interfere with the handling of mixed
+// content.
+TEST_F(SecurityStateModelTest, SHA1WarningMixedContent) {
+  GURL url(kUrl);
+  Profile* test_profile = profile();
+  SecurityStateModel::SecurityInfo security_info;
+  content::SSLStatus ssl_status;
+  ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status));
+  ssl_status.content_status = content::SSLStatus::DISPLAYED_INSECURE_CONTENT;
+  SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile,
+                                             &security_info);
+  EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_WARNING,
+            security_info.sha1_deprecation_status);
+  EXPECT_EQ(SecurityStateModel::DISPLAYED_MIXED_CONTENT,
+            security_info.mixed_content_status);
+  EXPECT_EQ(SecurityStateModel::NONE, security_info.security_level);
+
+  ssl_status.security_style = content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
+  ssl_status.content_status = content::SSLStatus::RAN_INSECURE_CONTENT;
+  SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile,
+                                             &security_info);
+  EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_WARNING,
+            security_info.sha1_deprecation_status);
+  EXPECT_EQ(SecurityStateModel::RAN_MIXED_CONTENT,
+            security_info.mixed_content_status);
+  EXPECT_EQ(SecurityStateModel::SECURITY_ERROR, security_info.security_level);
+}
+
+// Tests that SHA1 warnings don't interfere with the handling of major
+// cert errors.
+TEST_F(SecurityStateModelTest, SHA1WarningBrokenHTTPS) {
+  GURL url(kUrl);
+  Profile* test_profile = profile();
+  SecurityStateModel::SecurityInfo security_info;
+  content::SSLStatus ssl_status;
+  ASSERT_NO_FATAL_FAILURE(GetTestSSLStatus(process()->GetID(), &ssl_status));
+  ssl_status.security_style = content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
+  ssl_status.cert_status |= net::CERT_STATUS_DATE_INVALID;
+  SecurityStateModel::SecurityInfoForRequest(url, ssl_status, test_profile,
+                                             &security_info);
+  EXPECT_EQ(SecurityStateModel::DEPRECATED_SHA1_WARNING,
+            security_info.sha1_deprecation_status);
+  EXPECT_EQ(SecurityStateModel::SECURITY_ERROR, security_info.security_level);
+}
+
+}  // namespace
diff --git a/chrome/browser/ssl/ssl_add_certificate.cc b/chrome/browser/ssl/ssl_add_certificate.cc
index 89cbe5f..7b8d51ea 100644
--- a/chrome/browser/ssl/ssl_add_certificate.cc
+++ b/chrome/browser/ssl/ssl_add_certificate.cc
@@ -21,6 +21,7 @@
 #include "net/cert/cert_database.h"
 #include "net/cert/x509_certificate.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/vector_icons_public.h"
 
 using content::BrowserThread;
 using content::RenderFrameHost;
@@ -44,6 +45,7 @@
   // ConfirmInfoBarDelegate:
   Type GetInfoBarType() const override;
   int GetIconId() const override;
+  gfx::VectorIconId GetVectorIconId() const override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
@@ -81,6 +83,14 @@
   return IDR_INFOBAR_SAVE_PASSWORD;
 }
 
+gfx::VectorIconId SSLAddCertificateInfoBarDelegate::GetVectorIconId() const {
+#if !defined(OS_MACOSX)
+  return gfx::VectorIconId::AUTOLOGIN;
+#else
+  return gfx::VectorIconId::VECTOR_ICON_NONE;
+#endif
+}
+
 base::string16 SSLAddCertificateInfoBarDelegate::GetMessageText() const {
   // TODO(evanm): GetDisplayName should return UTF-16.
   return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
@@ -120,12 +130,15 @@
   // TODO(davidben): Use a more appropriate icon.
   // TODO(davidben): Display a more user-friendly error string.
   SimpleAlertInfoBarDelegate::Create(
-      InfoBarService::FromWebContents(web_contents),
-      IDR_INFOBAR_SAVE_PASSWORD,
-      l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT,
-                                 base::IntToString16(-cert_error),
-                                 base::ASCIIToUTF16(
-                                     net::ErrorToString(cert_error))),
+      InfoBarService::FromWebContents(web_contents), IDR_INFOBAR_SAVE_PASSWORD,
+#if !defined(OS_MACOSX)
+      gfx::VectorIconId::AUTOLOGIN,
+#else
+      gfx::VectorIconId::VECTOR_ICON_NONE,
+#endif
+      l10n_util::GetStringFUTF16(
+          IDS_ADD_CERT_ERR_INVALID_CERT, base::IntToString16(-cert_error),
+          base::ASCIIToUTF16(net::ErrorToString(cert_error))),
       true);
 }
 
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 2147785..721df33 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -143,8 +143,10 @@
   reporting_info.metric_prefix = GetUmaHistogramPrefix();
   reporting_info.rappor_prefix = kSSLRapporPrefix;
   reporting_info.rappor_report_type = rappor::UMA_RAPPOR_TYPE;
-  set_metrics_helper(new ChromeMetricsHelper(
+  scoped_ptr<ChromeMetricsHelper> chrome_metrics_helper(new ChromeMetricsHelper(
       web_contents, request_url, reporting_info, GetSamplingEventName()));
+  chrome_metrics_helper->StartRecordingCaptivePortalMetrics(overridable_);
+  set_metrics_helper(chrome_metrics_helper.Pass());
   metrics_helper()->RecordUserDecision(
       security_interstitials::MetricsHelper::SHOW);
   metrics_helper()->RecordUserInteraction(
@@ -155,13 +157,9 @@
       certificate_reporting::ErrorReport::INTERSTITIAL_SSL, overridable_,
       metrics_helper()));
 
-  ssl_error_classification_.reset(new SSLErrorClassification(
-      web_contents,
-      time_triggered_,
-      request_url,
-      cert_error_,
-      *ssl_info_.cert.get()));
-  ssl_error_classification_->RecordUMAStatistics(overridable_);
+  SSLErrorClassification error_classification(
+      time_triggered_, request_url, cert_error_, *ssl_info_.cert.get());
+  error_classification.RecordUMAStatistics(overridable_);
 
   // Creating an interstitial without showing (e.g. from chrome://interstitials)
   // it leaks memory, so don't create it here.
@@ -176,11 +174,7 @@
 }
 
 SSLBlockingPage::~SSLBlockingPage() {
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  // Captive portal detection results can arrive anytime during the interstitial
-  // is being displayed, so record it when the interstitial is going away.
-  ssl_error_classification_->RecordCaptivePortalUMAStatistics(overridable_);
-#endif
+  metrics_helper()->RecordShutdownMetrics();
   if (!callback_.is_null()) {
     // The page is closed without the user having chosen what to do, default to
     // deny.
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index 0c45e31..5387c81 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -30,7 +30,6 @@
 }
 
 class CertReportHelper;
-class SSLErrorClassification;
 
 // This class is responsible for showing/hiding the interstitial page that is
 // shown when a certificate error happens.
@@ -121,7 +120,6 @@
   // Did the user previously allow a bad certificate but the decision has now
   // expired?
   const bool expired_but_previously_allowed_;
-  scoped_ptr<SSLErrorClassification> ssl_error_classification_;
 
   // The time at which the interstitial was triggered. The interstitial
   // calculates all times relative to this.
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index b841c87b..6d50c0b 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
@@ -488,6 +489,61 @@
       EXPECT_EQ(https_server_expired_.GetURL("/").host(),
                 GetLatestHostnameReported());
     } else {
+      base::RunLoop().RunUntilIdle();
+      EXPECT_EQ(std::string(), GetLatestHostnameReported());
+    }
+  }
+
+  // Helper function for testing invalid certificate chain reporting with the
+  // bad clock interstitial.
+  void TestBadClockReporting(
+      certificate_reporting_test_utils::OptIn opt_in,
+      certificate_reporting_test_utils::ExpectReport expect_report,
+      Browser* browser) {
+    base::RunLoop run_loop;
+    ASSERT_TRUE(https_server_expired_.Start());
+    ASSERT_NO_FATAL_FAILURE(SetUpMockReporter());
+
+    // Set up the build and current clock times to be more than a year apart.
+    scoped_ptr<base::SimpleTestClock> mock_clock(new base::SimpleTestClock());
+    mock_clock->SetNow(base::Time::NowFromSystemTime());
+    mock_clock->Advance(base::TimeDelta::FromDays(367));
+    SSLErrorHandler::SetClockForTest(mock_clock.get());
+    SSLErrorClassification::SetBuildTimeForTesting(
+        base::Time::NowFromSystemTime());
+
+    // Opt in to sending reports for invalid certificate chains.
+    certificate_reporting_test_utils::SetCertReportingOptIn(browser, opt_in);
+
+    ui_test_utils::NavigateToURL(browser, https_server_expired_.GetURL("/"));
+
+    WebContents* tab = browser->tab_strip_model()->GetActiveWebContents();
+    CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID,
+                                   AuthState::SHOWING_INTERSTITIAL);
+
+    scoped_ptr<SSLCertReporter> ssl_cert_reporter =
+        certificate_reporting_test_utils::SetUpMockSSLCertReporter(
+            &run_loop, expect_report);
+
+    InterstitialPage* interstitial_page = tab->GetInterstitialPage();
+    ASSERT_EQ(BadClockBlockingPage::kTypeForTesting,
+              interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+    BadClockBlockingPage* clock_page = static_cast<BadClockBlockingPage*>(
+        tab->GetInterstitialPage()->GetDelegateForTesting());
+    clock_page->SetSSLCertReporterForTesting(ssl_cert_reporter.Pass());
+
+    EXPECT_EQ(std::string(), GetLatestHostnameReported());
+
+    interstitial_page->DontProceed();
+
+    if (expect_report ==
+        certificate_reporting_test_utils::CERT_REPORT_EXPECTED) {
+      // Check that the mock reporter received a request to send a report.
+      run_loop.Run();
+      EXPECT_EQ(https_server_expired_.GetURL("/").host(),
+                GetLatestHostnameReported());
+    } else {
+      base::RunLoop().RunUntilIdle();
       EXPECT_EQ(std::string(), GetLatestHostnameReported());
     }
   }
@@ -1049,28 +1105,28 @@
 
 #if defined(USE_NSS_CERTS)
 class SSLUITestWithClientCert : public SSLUITest {
-  public:
-   SSLUITestWithClientCert() : cert_db_(NULL) {}
+ public:
+  SSLUITestWithClientCert() : cert_db_(NULL) {}
 
-   void SetUpOnMainThread() override {
-     SSLUITest::SetUpOnMainThread();
+  void SetUpOnMainThread() override {
+    SSLUITest::SetUpOnMainThread();
 
-     base::RunLoop loop;
-     GetNSSCertDatabaseForProfile(
-         browser()->profile(),
-         base::Bind(&SSLUITestWithClientCert::DidGetCertDatabase,
-                    base::Unretained(this),
-                    &loop));
-     loop.Run();
-   }
+    base::RunLoop loop;
+    GetNSSCertDatabaseForProfile(
+        browser()->profile(),
+        base::Bind(&SSLUITestWithClientCert::DidGetCertDatabase,
+                   base::Unretained(this),
+                   &loop));
+    loop.Run();
+  }
 
-  protected:
-   void DidGetCertDatabase(base::RunLoop* loop, net::NSSCertDatabase* cert_db) {
-     cert_db_ = cert_db;
-     loop->Quit();
-   }
+ protected:
+  void DidGetCertDatabase(base::RunLoop* loop, net::NSSCertDatabase* cert_db) {
+    cert_db_ = cert_db;
+    loop->Quit();
+  }
 
-   net::NSSCertDatabase* cert_db_;
+  net::NSSCertDatabase* cert_db_;
 };
 
 // SSL client certificate tests are only enabled when using NSS for private key
@@ -1341,6 +1397,26 @@
       certificate_reporting_test_utils::CERT_REPORT_NOT_EXPECTED, browser());
 }
 
+// Checkbox is shown but unchecked. Reports should never be sent, regardless of
+// Finch config.
+IN_PROC_BROWSER_TEST_F(SSLUITestWithExtendedReporting,
+                       TestBadClockReportingWithNoOptIn) {
+  TestBadClockReporting(
+      certificate_reporting_test_utils::EXTENDED_REPORTING_DO_NOT_OPT_IN,
+      certificate_reporting_test_utils::CERT_REPORT_NOT_EXPECTED, browser());
+}
+
+// Test that when the interstitial closes and the checkbox is checked, a report
+// is sent or not sent depending on the Finch config.
+IN_PROC_BROWSER_TEST_F(SSLUITestWithExtendedReporting,
+                       TestBadClockReportingWithOptIn) {
+  certificate_reporting_test_utils::ExpectReport expect_report =
+      certificate_reporting_test_utils::GetReportExpectedFromFinch();
+  TestBadClockReporting(
+      certificate_reporting_test_utils::EXTENDED_REPORTING_OPT_IN,
+      expect_report, browser());
+}
+
 // Visits a page that runs insecure content and tries to suppress the insecure
 // content warnings by randomizing location.hash.
 // Based on http://crbug.com/8706
@@ -1353,9 +1429,8 @@
       "files/ssl/page_runs_insecure_content.html"));
 
   CheckAuthenticationBrokenState(
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      CertError::NONE,
-      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
+      browser()->tab_strip_model()->GetActiveWebContents(), CertError::NONE,
+      AuthState::RAN_INSECURE_CONTENT);
 }
 
 // Visits a page with unsafe content and make sure that:
@@ -1521,10 +1596,8 @@
   EXPECT_EQ(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
 
   // The new tab has insecure content.
-  CheckAuthenticationBrokenState(
-      tab2,
-      CertError::NONE,
-      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
+  CheckAuthenticationBrokenState(tab2, CertError::NONE,
+                                 AuthState::RAN_INSECURE_CONTENT);
 
   // Which means the origin for the first tab has also been contaminated with
   // insecure content.
@@ -1589,10 +1662,8 @@
   // content (even though the image comes from the WebCore memory cache).
   const GURL url_https = https_server_.GetURL(replacement_path);
   ui_test_utils::NavigateToURL(browser(), url_https);
-  CheckAuthenticationBrokenState(
-      tab,
-      CertError::NONE,
-      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
+  CheckAuthenticationBrokenState(tab, CertError::NONE,
+                                 AuthState::RAN_INSECURE_CONTENT);
 }
 
 // This test ensures the CN invalid status does not 'stick' to a certificate
diff --git a/chrome/browser/ssl/ssl_error_classification.cc b/chrome/browser/ssl/ssl_error_classification.cc
index ce43de58..a9342746 100644
--- a/chrome/browser/ssl/ssl_error_classification.cc
+++ b/chrome/browser/ssl/ssl_error_classification.cc
@@ -7,27 +7,17 @@
 #include "chrome/browser/ssl/ssl_error_classification.h"
 
 #include "base/build_time.h"
-#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/profile.h"
 #include "components/ssl_errors/error_info.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/web_contents.h"
 #include "net/base/net_util.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/cert/x509_cert_types.h"
 #include "net/cert/x509_certificate.h"
 #include "url/gurl.h"
 
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-#include "chrome/browser/captive_portal/captive_portal_service.h"
-#include "chrome/browser/captive_portal/captive_portal_service_factory.h"
-#endif
-
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
@@ -51,27 +41,13 @@
   LIKELY_MULTI_TENANT_HOSTING,
   LOCALHOST,
   PRIVATE_URL,
-  AUTHORITY_ERROR_CAPTIVE_PORTAL,
+  AUTHORITY_ERROR_CAPTIVE_PORTAL,  // Deprecated in M47.
   SELF_SIGNED,
   EXPIRED_RECENTLY,
   LIKELY_SAME_DOMAIN,
   UNUSED_INTERSTITIAL_CAUSE_ENTRY,
 };
 
-// Events for UMA. Do not reorder or change!
-enum SSLInterstitialCauseCaptivePortal {
-  CAPTIVE_PORTAL_ALL,
-  CAPTIVE_PORTAL_DETECTION_ENABLED,
-  CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE,
-  CAPTIVE_PORTAL_PROBE_COMPLETED,
-  CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE,
-  CAPTIVE_PORTAL_NO_RESPONSE,
-  CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE,
-  CAPTIVE_PORTAL_DETECTED,
-  CAPTIVE_PORTAL_DETECTED_OVERRIDABLE,
-  UNUSED_CAPTIVE_PORTAL_EVENT,
-};
-
 void RecordSSLInterstitialCause(bool overridable, SSLInterstitialCause event) {
   if (overridable) {
     UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.cause.overridable", event,
@@ -82,14 +58,6 @@
   }
 }
 
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-void RecordCaptivePortalEventStats(SSLInterstitialCauseCaptivePortal event) {
-  UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.captive_portal",
-                            event,
-                            UNUSED_CAPTIVE_PORTAL_EVENT);
-}
-#endif
-
 int GetLevensteinDistance(const std::string& str1,
                           const std::string& str2) {
   if (str1 == str2)
@@ -121,62 +89,17 @@
 
 } // namespace
 
-SSLErrorClassification::SSLErrorClassification(
-    content::WebContents* web_contents,
-    const base::Time& current_time,
-    const GURL& url,
-    int cert_error,
-    const net::X509Certificate& cert)
-  : web_contents_(web_contents),
-    current_time_(current_time),
-    request_url_(url),
-    cert_error_(cert_error),
-    cert_(cert),
-    captive_portal_detection_enabled_(false),
-    captive_portal_probe_completed_(false),
-    captive_portal_no_response_(false),
-    captive_portal_detected_(false) {
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  Profile* profile = Profile::FromBrowserContext(
-      web_contents_->GetBrowserContext());
-  captive_portal_detection_enabled_ =
-      CaptivePortalServiceFactory::GetForProfile(profile)->enabled();
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
-                 content::Source<Profile>(profile));
-#endif
-}
+SSLErrorClassification::SSLErrorClassification(const base::Time& current_time,
+                                               const GURL& url,
+                                               int cert_error,
+                                               const net::X509Certificate& cert)
+    : current_time_(current_time),
+      request_url_(url),
+      cert_error_(cert_error),
+      cert_(cert) {}
 
 SSLErrorClassification::~SSLErrorClassification() { }
 
-void SSLErrorClassification::RecordCaptivePortalUMAStatistics(
-    bool overridable) const {
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  RecordCaptivePortalEventStats(CAPTIVE_PORTAL_ALL);
-  if (captive_portal_detection_enabled_)
-    RecordCaptivePortalEventStats(
-        overridable ?
-        CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE :
-        CAPTIVE_PORTAL_DETECTION_ENABLED);
-  if (captive_portal_probe_completed_)
-    RecordCaptivePortalEventStats(
-        overridable ?
-        CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE :
-        CAPTIVE_PORTAL_PROBE_COMPLETED);
-  // Log only one of portal detected and no response results.
-  if (captive_portal_detected_)
-    RecordCaptivePortalEventStats(
-        overridable ?
-        CAPTIVE_PORTAL_DETECTED_OVERRIDABLE :
-        CAPTIVE_PORTAL_DETECTED);
-  else if (captive_portal_no_response_)
-    RecordCaptivePortalEventStats(
-        overridable ?
-        CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE :
-        CAPTIVE_PORTAL_NO_RESPONSE);
-#endif
-}
-
 void SSLErrorClassification::RecordUMAStatistics(
     bool overridable) const {
   ssl_errors::ErrorInfo::ErrorType type =
@@ -225,8 +148,6 @@
         RecordSSLInterstitialCause(overridable, LOCALHOST);
       if (IsHostnameNonUniqueOrDotless(hostname))
         RecordSSLInterstitialCause(overridable, PRIVATE_URL);
-      if (captive_portal_probe_completed_ && captive_portal_detected_)
-        RecordSSLInterstitialCause(overridable, AUTHORITY_ERROR_CAPTIVE_PORTAL);
       if (net::X509Certificate::IsSelfSigned(cert_.os_cert_handle()))
         RecordSSLInterstitialCause(overridable, SELF_SIGNED);
       break;
@@ -521,34 +442,3 @@
   return net::IsHostnameNonUnique(hostname) ||
          hostname.find('.') == std::string::npos;
 }
-
-void SSLErrorClassification::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  // When detection is disabled, captive portal service always sends
-  // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
-  if (!captive_portal_detection_enabled_)
-    return;
-  if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
-    captive_portal_probe_completed_ = true;
-    CaptivePortalService::Results* results =
-        content::Details<CaptivePortalService::Results>(details).ptr();
-    // If a captive portal was detected at any point when the interstitial was
-    // displayed, assume that the interstitial was caused by a captive portal.
-    // Example scenario:
-    // 1- Interstitial displayed and captive portal detected, setting the flag.
-    // 2- Captive portal detection automatically opens portal login page.
-    // 3- User logs in on the portal login page.
-    // A notification will be received here for RESULT_INTERNET_CONNECTED. Make
-    // sure we don't clear the captive protal flag, since the interstitial was
-    // potentially caused by the captive portal.
-    captive_portal_detected_ = captive_portal_detected_ ||
-        (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
-    // Also keep track of non-HTTP portals and error cases.
-    captive_portal_no_response_ = captive_portal_no_response_ ||
-        (results->result == captive_portal::RESULT_NO_RESPONSE);
-  }
-#endif
-}
diff --git a/chrome/browser/ssl/ssl_error_classification.h b/chrome/browser/ssl/ssl_error_classification.h
index bdbb04ec..e273365 100644
--- a/chrome/browser/ssl/ssl_error_classification.h
+++ b/chrome/browser/ssl/ssl_error_classification.h
@@ -10,29 +10,16 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/time/time.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 #include "net/cert/x509_certificate.h"
 #include "url/gurl.h"
 
-namespace content {
-class WebContents;
-}
-
-// This class classifies characteristics of SSL errors, including information
-// about captive portal detection.
-//
-// This class should only be used on the UI thread because its
-// implementation uses captive_portal::CaptivePortalService which can only be
-// accessed on the UI thread.
-class SSLErrorClassification : public content::NotificationObserver {
+class SSLErrorClassification {
  public:
-  SSLErrorClassification(content::WebContents* web_contents,
-                         const base::Time& current_time,
+  SSLErrorClassification(const base::Time& current_time,
                          const GURL& url,
                          int cert_error,
                          const net::X509Certificate& cert);
-  ~SSLErrorClassification() override;
+  ~SSLErrorClassification();
 
   // Returns true if the system time is in the past.
   static bool IsUserClockInThePast(const base::Time& time_now);
@@ -63,7 +50,6 @@
                                    std::string* www_match_host_name);
 
   void RecordUMAStatistics(bool overridable) const;
-  void RecordCaptivePortalUMAStatistics(bool overridable) const;
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SSLErrorClassificationTest, TestDateInvalidScore);
@@ -132,24 +118,10 @@
 
   static Tokens Tokenize(const std::string& name);
 
-  // content::NotificationObserver:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
-  content::WebContents* web_contents_;
   base::Time current_time_;
   const GURL request_url_;
   int cert_error_;
   const net::X509Certificate& cert_;
-  bool captive_portal_detection_enabled_;
-  // Did the probe complete before the interstitial was closed?
-  bool captive_portal_probe_completed_;
-  // Did the captive portal probe receive an error or get a non-HTTP response?
-  bool captive_portal_no_response_;
-  bool captive_portal_detected_;
-
-  content::NotificationRegistrar registrar_;
 };
 
 #endif  // CHROME_BROWSER_SSL_SSL_ERROR_CLASSIFICATION_H_
diff --git a/chrome/browser/ssl/ssl_error_classification_unittest.cc b/chrome/browser/ssl/ssl_error_classification_unittest.cc
index 318dbc9..b84676e 100644
--- a/chrome/browser/ssl/ssl_error_classification_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_classification_unittest.cc
@@ -7,8 +7,6 @@
 #include "base/files/file_path.h"
 #include "base/strings/string_split.h"
 #include "base/time/time.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "content/public/browser/web_contents.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_data_directory.h"
 #include "net/cert/x509_cert_types.h"
@@ -19,14 +17,8 @@
 #include "url/gurl.h"
 
 using base::Time;
-using content::WebContents;
 
-class SSLErrorClassificationTest : public ChromeRenderViewHostTestHarness {
- public:
-  SSLErrorClassificationTest() {
-    SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
-  }
-};
+class SSLErrorClassificationTest : public testing::Test {};
 
 TEST_F(SSLErrorClassificationTest, TestNameMismatch) {
   scoped_refptr<net::X509Certificate> google_cert(
@@ -41,16 +33,11 @@
   std::vector<std::vector<std::string>> dns_name_tokens_google;
   dns_name_tokens_google.push_back(dns_names_google);
   int cert_error = net::ERR_CERT_COMMON_NAME_INVALID;
-  WebContents* contents = web_contents();
   {
     GURL origin("https://google.com");
     std::vector<std::string> host_name_tokens = base::SplitString(
         origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-    SSLErrorClassification ssl_error(contents,
-                                     time,
-                                     origin,
-                                     cert_error,
-                                     *google_cert);
+    SSLErrorClassification ssl_error(time, origin, cert_error, *google_cert);
     EXPECT_TRUE(ssl_error.IsWWWSubDomainMatch());
     EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                              dns_name_tokens_google));
@@ -65,11 +52,7 @@
     GURL origin("https://foo.blah.google.com");
     std::vector<std::string> host_name_tokens = base::SplitString(
         origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-    SSLErrorClassification ssl_error(contents,
-                                     time,
-                                     origin,
-                                     cert_error,
-                                     *google_cert);
+    SSLErrorClassification ssl_error(time, origin, cert_error, *google_cert);
     EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
     EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                              dns_name_tokens_google));
@@ -82,11 +65,7 @@
     GURL origin("https://foo.www.google.com");
     std::vector<std::string> host_name_tokens = base::SplitString(
         origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-    SSLErrorClassification ssl_error(contents,
-                                     time,
-                                     origin,
-                                     cert_error,
-                                     *google_cert);
+    SSLErrorClassification ssl_error(time, origin, cert_error, *google_cert);
     EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
     EXPECT_TRUE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                             dns_name_tokens_google));
@@ -99,11 +78,7 @@
      GURL origin("https://www.google.com.foo");
      std::vector<std::string> host_name_tokens = base::SplitString(
          origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-     SSLErrorClassification ssl_error(contents,
-                                      time,
-                                      origin,
-                                      cert_error,
-                                      *google_cert);
+     SSLErrorClassification ssl_error(time, origin, cert_error, *google_cert);
      EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
      EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                               dns_name_tokens_google));
@@ -116,11 +91,7 @@
     GURL origin("https://www.foogoogle.com.");
     std::vector<std::string> host_name_tokens = base::SplitString(
         origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-    SSLErrorClassification ssl_error(contents,
-                                     time,
-                                     origin,
-                                     cert_error,
-                                     *google_cert);
+    SSLErrorClassification ssl_error(time, origin, cert_error, *google_cert);
     EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
     EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                              dns_name_tokens_google));
@@ -142,11 +113,7 @@
     GURL origin("https://a.b.webkit.org");
     std::vector<std::string> host_name_tokens = base::SplitString(
         origin.host(), ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-    SSLErrorClassification ssl_error(contents,
-                                     time,
-                                     origin,
-                                     cert_error,
-                                     *webkit_cert);
+    SSLErrorClassification ssl_error(time, origin, cert_error, *webkit_cert);
     EXPECT_FALSE(ssl_error.IsWWWSubDomainMatch());
     EXPECT_FALSE(ssl_error.NameUnderAnyNames(host_name_tokens,
                                              dns_name_tokens_webkit));
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index 7fe5d025..67385ea4 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -338,7 +338,7 @@
 void SSLErrorHandler::ShowBadClockInterstitial(const base::Time& now) {
   RecordUMA(SHOW_BAD_CLOCK);
   (new BadClockBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_,
-                            now, callback_))
+                            now, ssl_cert_reporter_.Pass(), callback_))
       ->Show();
   // Once an interstitial is displayed, no need to keep the handler around.
   // This is the equivalent of "delete this".
diff --git a/chrome/browser/storage/durable_storage_browsertest.cc b/chrome/browser/storage/durable_storage_browsertest.cc
index a34eb2ac..a59e4e7 100644
--- a/chrome/browser/storage/durable_storage_browsertest.cc
+++ b/chrome/browser/storage/durable_storage_browsertest.cc
@@ -1,18 +1,22 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. 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/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_utils.h"
+#include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
@@ -27,9 +31,25 @@
   void SetUpOnMainThread() override;
 
  protected:
-  content::RenderFrameHost* GetRenderFrameHost() {
-    return browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
+  content::RenderFrameHost* GetRenderFrameHost(Browser* browser) {
+    return browser->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
   }
+
+  content::RenderFrameHost* GetRenderFrameHost() {
+    return GetRenderFrameHost(browser());
+  }
+
+  void Bookmark(Browser* browser) {
+    bookmarks::BookmarkModel* bookmark_model =
+        BookmarkModelFactory::GetForProfile(browser->profile());
+    bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
+    bookmarks::AddIfNotBookmarked(bookmark_model, url_, base::ASCIIToUTF16(""));
+  }
+
+  void Bookmark() {
+    Bookmark(browser());
+  }
+
   GURL url_;
 
  private:
@@ -49,19 +69,71 @@
   url_ = embedded_test_server()->GetURL("/durable/durability-permissions.html");
 }
 
-IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, DenyString) {
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, QueryNonBookmarkedPage) {
   ui_test_utils::NavigateToURL(browser(), url_);
-  PermissionBubbleManager::FromWebContents(
-      browser()->tab_strip_model()->GetActiveWebContents())
-      ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL);
-  bool default_box_is_persistent;
-  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
-      GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
-  EXPECT_FALSE(default_box_is_persistent);
   std::string permission_string;
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
       GetRenderFrameHost(), "checkPermission()", &permission_string));
-  EXPECT_EQ("denied", permission_string);
+  EXPECT_EQ("default", permission_string);
+}
+
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, RequestNonBookmarkedPage) {
+  ui_test_utils::NavigateToURL(browser(), url_);
+  bool default_box_is_persistent = false;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
+  EXPECT_FALSE(default_box_is_persistent);
+}
+
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, QueryBookmarkedPage) {
+  // Documents that the current behavior is to return "default" if script
+  // hasn't requested the durable permission, even if it would be autogranted.
+  Bookmark();
+  ui_test_utils::NavigateToURL(browser(), url_);
+  std::string permission_string;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      GetRenderFrameHost(), "checkPermission()", &permission_string));
+  EXPECT_EQ("default", permission_string);
+}
+
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, RequestBookmarkedPage) {
+  Bookmark();
+  ui_test_utils::NavigateToURL(browser(), url_);
+  bool default_box_is_persistent = false;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
+  EXPECT_TRUE(default_box_is_persistent);
+}
+
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, BookmarkThenUnbookmark) {
+  Bookmark();
+  ui_test_utils::NavigateToURL(browser(), url_);
+  bool default_box_is_persistent = false;
+  std::string permission_string;
+
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
+  EXPECT_TRUE(default_box_is_persistent);
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      GetRenderFrameHost(), "checkPermission()", &permission_string));
+  EXPECT_EQ("granted", permission_string);
+
+  bookmarks::BookmarkModel* bookmark_model =
+      BookmarkModelFactory::GetForProfile(browser()->profile());
+  bookmarks::RemoveAllBookmarks(bookmark_model, url_);
+
+  // Unbookmarking doesn't change the permission.
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      GetRenderFrameHost(), "checkPermission()", &permission_string));
+  EXPECT_EQ("granted", permission_string);
+  // Requesting after unbookmarking doesn't change the default box.
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
+  EXPECT_TRUE(default_box_is_persistent);
+  // Querying after requesting after unbookmarking still reports "granted".
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      GetRenderFrameHost(), "checkPermission()", &permission_string));
+  EXPECT_EQ("granted", permission_string);
 }
 
 IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, FirstTabSeesResult) {
@@ -73,9 +145,7 @@
 
   chrome::NewTab(browser());
   ui_test_utils::NavigateToURL(browser(), url_);
-  PermissionBubbleManager::FromWebContents(
-      browser()->tab_strip_model()->GetActiveWebContents())
-      ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL);
+  Bookmark();
   bool default_box_is_persistent = false;
   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
       GetRenderFrameHost(), "requestPermission()", &default_box_is_persistent));
@@ -86,3 +156,20 @@
       GetRenderFrameHost(), "checkPermission()", &permission_string));
   EXPECT_EQ("granted", permission_string);
 }
+
+IN_PROC_BROWSER_TEST_F(DurableStorageBrowserTest, Incognito) {
+  Browser* browser = CreateIncognitoBrowser();
+  ui_test_utils::NavigateToURL(browser, url_);
+
+  Bookmark(browser);
+  bool default_box_is_persistent = false;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(GetRenderFrameHost(browser),
+                                                   "requestPermission()",
+                                                   &default_box_is_persistent));
+  EXPECT_TRUE(default_box_is_persistent);
+
+  std::string permission_string;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      GetRenderFrameHost(browser), "checkPermission()", &permission_string));
+  EXPECT_EQ("granted", permission_string);
+}
diff --git a/chrome/browser/storage/durable_storage_permission_context.cc b/chrome/browser/storage/durable_storage_permission_context.cc
index 68b5af8a..5a2afbe 100644
--- a/chrome/browser/storage/durable_storage_permission_context.cc
+++ b/chrome/browser/storage/durable_storage_permission_context.cc
@@ -4,16 +4,104 @@
 
 #include "chrome/browser/storage/durable_storage_permission_context.h"
 
+#include <algorithm>
+
+#include "base/logging.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/permissions/permission_request_id.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/browser/website_settings_registry.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/common/origin_util.h"
 #include "url/gurl.h"
 
+using bookmarks::BookmarkModel;
+
 DurableStoragePermissionContext::DurableStoragePermissionContext(
     Profile* profile)
     : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_DURABLE_STORAGE) {
 }
 
+void DurableStoragePermissionContext::DecidePermission(
+    content::WebContents* web_contents,
+    const PermissionRequestID& id,
+    const GURL& requesting_origin,
+    const GURL& embedding_origin,
+    bool user_gesture,
+    const BrowserPermissionCallback& callback) {
+  // TODO(dgrogan): Reuse the base class's implementation of everything from
+  // here to using bookmarks.
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  if (!requesting_origin.is_valid() || !embedding_origin.is_valid()) {
+    std::string type_name =
+        content_settings::WebsiteSettingsRegistry::GetInstance()
+            ->Get(CONTENT_SETTINGS_TYPE_DURABLE_STORAGE)
+            ->name();
+
+    DVLOG(1) << "Attempt to use " << type_name
+             << " from an invalid URL: " << requesting_origin << ","
+             << embedding_origin << " (" << type_name
+             << " is not supported in popups)";
+    NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
+                        false /* persist */, CONTENT_SETTING_BLOCK);
+    return;
+  }
+
+  if (IsRestrictedToSecureOrigins() &&
+      !content::IsOriginSecure(requesting_origin)) {
+    NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
+                        false /* persist */, CONTENT_SETTING_BLOCK);
+    return;
+  }
+
+  ContentSetting content_setting =
+      HostContentSettingsMapFactory::GetForProfile(profile())
+          ->GetContentSettingAndMaybeUpdateLastUsage(
+              requesting_origin, embedding_origin,
+              CONTENT_SETTINGS_TYPE_DURABLE_STORAGE, std::string());
+
+  DCHECK_NE(CONTENT_SETTING_BLOCK, content_setting);
+  if (content_setting == CONTENT_SETTING_ALLOW) {
+    NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
+                        false /* persist */, content_setting);
+    return;
+  }
+
+  // TODO(dgrogan): Remove bookmarks check in favor of site engagement. In the
+  // meantime maybe grant permission to A2HS origins as well.
+  BookmarkModel* model = BookmarkModelFactory::GetForProfileIfExists(profile());
+  if (model) {
+    std::vector<bookmarks::BookmarkModel::URLAndTitle> bookmarks;
+    model->GetBookmarks(&bookmarks);
+    if (IsOriginBookmarked(bookmarks, requesting_origin)) {
+      NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
+                          true /* persist */, CONTENT_SETTING_ALLOW);
+      return;
+    }
+  }
+
+  NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
+                      false /* persist */, CONTENT_SETTING_DEFAULT);
+}
+
 bool DurableStoragePermissionContext::IsRestrictedToSecureOrigins() const {
   return true;
 }
+
+bool DurableStoragePermissionContext::IsOriginBookmarked(
+    const std::vector<bookmarks::BookmarkModel::URLAndTitle>& bookmarks,
+    const GURL& origin) {
+  BookmarkModel::URLAndTitle looking_for;
+  looking_for.url = origin;
+  return std::binary_search(bookmarks.begin(), bookmarks.end(), looking_for,
+                            [](const BookmarkModel::URLAndTitle& a,
+                               const BookmarkModel::URLAndTitle& b) {
+                              return a.url.GetOrigin() < b.url.GetOrigin();
+                            });
+}
diff --git a/chrome/browser/storage/durable_storage_permission_context.h b/chrome/browser/storage/durable_storage_permission_context.h
index 5875749..f6683d00 100644
--- a/chrome/browser/storage/durable_storage_permission_context.h
+++ b/chrome/browser/storage/durable_storage_permission_context.h
@@ -5,16 +5,33 @@
 #ifndef CHROME_BROWSER_STORAGE_DURABLE_STORAGE_PERMISSION_CONTEXT_H_
 #define CHROME_BROWSER_STORAGE_DURABLE_STORAGE_PERMISSION_CONTEXT_H_
 
+#include <vector>
+
 #include "chrome/browser/permissions/permission_context_base.h"
+#include "components/bookmarks/browser/bookmark_model.h"
 
 class DurableStoragePermissionContext : public PermissionContextBase {
  public:
   explicit DurableStoragePermissionContext(Profile* profile);
   ~DurableStoragePermissionContext() override = default;
 
+  // Grant if requesting_origin is bookmarked or already granted.
+  void DecidePermission(content::WebContents* web_contents,
+                        const PermissionRequestID& id,
+                        const GURL& requesting_origin,
+                        const GURL& embedding_origin,
+                        bool user_gesture,
+                        const BrowserPermissionCallback& callback) override;
   bool IsRestrictedToSecureOrigins() const override;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(BookmarksOriginTest, Exists);
+  FRIEND_TEST_ALL_PREFIXES(BookmarksOriginTest, DoesntExist);
+
+  static bool IsOriginBookmarked(
+      const std::vector<bookmarks::BookmarkModel::URLAndTitle>& bookmarks,
+      const GURL& origin);
+
   DISALLOW_COPY_AND_ASSIGN(DurableStoragePermissionContext);
 };
 
diff --git a/chrome/browser/storage/durable_storage_permission_context_unittest.cc b/chrome/browser/storage/durable_storage_permission_context_unittest.cc
new file mode 100644
index 0000000..21517e05
--- /dev/null
+++ b/chrome/browser/storage/durable_storage_permission_context_unittest.cc
@@ -0,0 +1,50 @@
+// Copyright 2015 The Chromium Authors. 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/storage/durable_storage_permission_context.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using bookmarks::BookmarkModel;
+
+class BookmarksOriginTest : public ::testing::Test {
+ protected:
+  static std::vector<BookmarkModel::URLAndTitle> MakeBookmarks(
+      const std::string urls[],
+      const int array_size) {
+    std::vector<BookmarkModel::URLAndTitle> bookmarks;
+    for (int i = 0; i < array_size; ++i) {
+      BookmarkModel::URLAndTitle bookmark;
+      bookmark.url = GURL(urls[i]);
+      EXPECT_TRUE(bookmark.url.is_valid());
+      bookmarks.push_back(bookmark);
+    }
+    return bookmarks;
+  }
+};
+
+TEST_F(BookmarksOriginTest, Exists) {
+  std::string urls[] = {
+    "http://www.google.com/",
+    "https://dogs.com/somepage.html",
+    "https://mail.google.com/mail/u/0/#inbox",
+  };
+  std::vector<BookmarkModel::URLAndTitle> bookmarks =
+      MakeBookmarks(urls, arraysize(urls));
+  GURL looking_for("https://dogs.com");
+  EXPECT_TRUE(DurableStoragePermissionContext::IsOriginBookmarked(
+      bookmarks, looking_for));
+}
+
+TEST_F(BookmarksOriginTest, DoesntExist) {
+  std::string urls[] = {
+    "http://www.google.com/",
+    "https://www.google.com/",
+  };
+  std::vector<BookmarkModel::URLAndTitle> bookmarks =
+      MakeBookmarks(urls, arraysize(urls));
+  GURL looking_for("https://dogs.com");
+  EXPECT_FALSE(DurableStoragePermissionContext::IsOriginBookmarked(
+      bookmarks, looking_for));
+}
diff --git a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc
index 37483a12..d9b6dc2 100644
--- a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc
+++ b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc
@@ -199,7 +199,6 @@
 void PermissionRequestCreatorApiary::OnGetTokenFailure(
     const OAuth2TokenService::Request* request,
     const GoogleServiceAuthError& error) {
-  VLOG(1) << "Couldn't get token";
   RequestIterator it = requests_.begin();
   while (it != requests_.end()) {
     if (request == (*it)->access_token_request.get())
@@ -207,8 +206,8 @@
     ++it;
   }
   DCHECK(it != requests_.end());
-  (*it)->callback.Run(false);
-  requests_.erase(it);
+  LOG(WARNING) << "Token error: " << error.ToString();
+  DispatchResult(it, false);
 }
 
 void PermissionRequestCreatorApiary::OnURLFetchComplete(
@@ -223,7 +222,8 @@
 
   const net::URLRequestStatus& status = source->GetStatus();
   if (!status.is_success()) {
-    DispatchNetworkError(it, status.error());
+    LOG(WARNING) << "Network error " << status.error();
+    DispatchResult(it, false);
     return;
   }
 
@@ -240,8 +240,7 @@
 
   if (response_code != net::HTTP_OK) {
     LOG(WARNING) << "HTTP error " << response_code;
-    DispatchGoogleServiceAuthError(
-        it, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+    DispatchResult(it, false);
     return;
   }
 
@@ -250,33 +249,27 @@
   scoped_ptr<base::Value> value = base::JSONReader::Read(response_body);
   base::DictionaryValue* dict = NULL;
   if (!value || !value->GetAsDictionary(&dict)) {
-    DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
+    LOG(WARNING) << "Invalid top-level dictionary";
+    DispatchResult(it, false);
     return;
   }
   base::DictionaryValue* permission_dict = NULL;
   if (!dict->GetDictionary(kPermissionRequestKey, &permission_dict)) {
-    DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
+    LOG(WARNING) << "Permission request not found";
+    DispatchResult(it, false);
     return;
   }
   std::string id;
   if (!permission_dict->GetString(kIdKey, &id)) {
-    DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
+    LOG(WARNING) << "ID not found";
+    DispatchResult(it, false);
     return;
   }
-  (*it)->callback.Run(true);
-  requests_.erase(it);
+  DispatchResult(it, true);
 }
 
-void PermissionRequestCreatorApiary::DispatchNetworkError(RequestIterator it,
-                                                          int error_code) {
-  DispatchGoogleServiceAuthError(
-      it, GoogleServiceAuthError::FromConnectionError(error_code));
-}
-
-void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
-    RequestIterator it,
-    const GoogleServiceAuthError& error) {
-  VLOG(1) << "GoogleServiceAuthError: " << error.ToString();
-  (*it)->callback.Run(false);
+void PermissionRequestCreatorApiary::DispatchResult(RequestIterator it,
+                                                    bool success) {
+  (*it)->callback.Run(success);
   requests_.erase(it);
 }
diff --git a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h
index 074a6b7..1e6cb3b0 100644
--- a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h
+++ b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.h
@@ -49,7 +49,7 @@
 
  private:
   struct Request;
-  typedef ScopedVector<Request>::iterator RequestIterator;
+  using RequestIterator = ScopedVector<Request>::iterator;
 
   // OAuth2TokenService::Consumer implementation:
   void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
@@ -72,9 +72,7 @@
   // we restart when the returned access token has expired.
   void StartFetching(Request* request);
 
-  void DispatchNetworkError(RequestIterator it, int error_code);
-  void DispatchGoogleServiceAuthError(RequestIterator it,
-                                      const GoogleServiceAuthError& error);
+  void DispatchResult(RequestIterator it, bool success);
 
   OAuth2TokenService* oauth2_token_service_;
   std::string account_id_;
diff --git a/chrome/browser/supervised_user/supervised_user_browsertest.cc b/chrome/browser/supervised_user/supervised_user_browsertest.cc
index d3a3d75..aa41e5c 100644
--- a/chrome/browser/supervised_user/supervised_user_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_browsertest.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/supervised_user/supervised_user_settings_service.h"
 #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index ad1a8471..1e2f005e 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/supervised_user/legacy/permission_request_creator_sync.h"
 #include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service.h"
 #include "chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_factory.h"
-#include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility.h"
 #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/browser/supervised_user/supervised_user_service_observer.h"
@@ -51,6 +50,10 @@
 #include "content/public/browser/user_metrics.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "chrome/browser/supervised_user/legacy/supervised_user_registration_utility.h"
+#endif
+
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
@@ -846,6 +849,7 @@
   }
 }
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
 void SupervisedUserService::RegisterAndInitSync(
     SupervisedUserRegistrationUtility* registration_utility,
     Profile* custodian_profile,
@@ -875,6 +879,7 @@
       base::Bind(&SupervisedUserService::OnCustodianProfileDownloaded,
                  weak_ptr_factory_.GetWeakPtr()));
 }
+#endif
 
 void SupervisedUserService::OnCustodianProfileDownloaded(
     const base::string16& full_name) {
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index bca5978e..ef4142d 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -137,6 +137,7 @@
   // mint access tokens for Sync.
   void InitSync(const std::string& refresh_token);
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
   // Convenience method that registers this supervised user using
   // |registration_utility| and initializes sync with the returned token.
   // The |callback| will be called when registration is complete,
@@ -147,6 +148,7 @@
       Profile* custodian_profile,
       const std::string& supervised_user_id,
       const AuthErrorCallback& callback);
+#endif
 
   void AddNavigationBlockedCallback(const NavigationBlockedCallback& callback);
   void DidBlockNavigation(content::WebContents* web_contents);
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index e697e4c..bb55f5b 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/sync/profile_sync_components_factory_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/themes/theme_service.h"
@@ -27,6 +26,7 @@
 #include "components/dom_distiller/core/dom_distiller_service.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/password_manager/core/browser/password_store.h"
+#include "components/sync_driver/sync_api_component_factory.h"
 #include "components/syncable_prefs/pref_service_syncable.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -70,10 +70,8 @@
 
 ChromeSyncClient::ChromeSyncClient(
     Profile* profile,
-    sync_driver::SyncApiComponentFactory* component_factory)
-    : profile_(profile),
-      component_factory_(component_factory) {
-}
+    scoped_ptr<sync_driver::SyncApiComponentFactory> component_factory)
+    : profile_(profile), component_factory_(component_factory.Pass()) {}
 ChromeSyncClient::~ChromeSyncClient() {
 }
 
@@ -82,6 +80,7 @@
   sync_service_ = sync_service;
   web_data_service_ = GetWebDataService();
   password_store_ = GetPasswordStore();
+  component_factory_->RegisterDataTypes(this);
 }
 
 sync_driver::SyncService* ChromeSyncClient::GetSyncService() {
@@ -253,7 +252,7 @@
 
 sync_driver::SyncApiComponentFactory*
 ChromeSyncClient::GetSyncApiComponentFactory() {
-  return component_factory_;
+  return component_factory_.get();
 }
 
 }  // namespace browser_sync
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h
index 39f69adc..d16d0e7 100644
--- a/chrome/browser/sync/chrome_sync_client.h
+++ b/chrome/browser/sync/chrome_sync_client.h
@@ -18,12 +18,13 @@
 
 class ChromeSyncClient : public sync_driver::SyncClient {
  public:
-  ChromeSyncClient(Profile* profile,
-                   sync_driver::SyncApiComponentFactory* component_factory);
+  ChromeSyncClient(
+      Profile* profile,
+      scoped_ptr<sync_driver::SyncApiComponentFactory> component_factory);
   ~ChromeSyncClient() override;
 
   // Initializes the ChromeSyncClient internal state.
-  void Initialize(sync_driver::SyncService* sync_service);
+  void Initialize(sync_driver::SyncService* sync_service) override;
 
   // SyncClient implementation.
   sync_driver::SyncService* GetSyncService() override;
@@ -41,10 +42,8 @@
  private:
   Profile* const profile_;
 
-  // TODO(zea): This is currently a pointer to the "parent" of this class, and
-  // is therefore not owned, but we should eventually have the SyncClient own
-  // the component factory (crbug.com/512832).
-  sync_driver::SyncApiComponentFactory* const component_factory_;
+  // The sync api component factory in use by this client.
+  scoped_ptr<sync_driver::SyncApiComponentFactory> component_factory_;
 
   // Members that must be fetched on the UI thread but accessed on their
   // respective backend threads.
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc
index a30c726..442197e9 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc
@@ -36,6 +36,7 @@
 #include "components/sync_driver/device_info_data_type_controller.h"
 #include "components/sync_driver/glue/typed_url_model_associator.h"
 #include "components/sync_driver/proxy_data_type_controller.h"
+#include "components/sync_driver/sync_client.h"
 #include "components/sync_driver/ui_data_type_controller.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/oauth2_token_service.h"
@@ -134,7 +135,6 @@
       sync_service_url_(sync_service_url),
       token_service_(token_service),
       url_request_context_getter_(url_request_context_getter),
-      chrome_sync_client_(profile_, this),
       weak_factory_(this) {
   DCHECK(token_service_);
   DCHECK(url_request_context_getter_);
@@ -143,46 +143,42 @@
 ProfileSyncComponentsFactoryImpl::~ProfileSyncComponentsFactoryImpl() {
 }
 
-void ProfileSyncComponentsFactoryImpl::Initialize(
-    sync_driver::SyncService* sync_service) {
-  chrome_sync_client_.Initialize(sync_service);
-}
-
-void ProfileSyncComponentsFactoryImpl::RegisterDataTypes() {
+void ProfileSyncComponentsFactoryImpl::RegisterDataTypes(
+    sync_driver::SyncClient* sync_client) {
   syncer::ModelTypeSet disabled_types =
       GetDisabledTypesFromCommandLine(*command_line_);
   syncer::ModelTypeSet enabled_types =
       GetEnabledTypesFromCommandLine(*command_line_);
-  RegisterCommonDataTypes(disabled_types, enabled_types);
+  RegisterCommonDataTypes(disabled_types, enabled_types, sync_client);
 #if !defined(OS_ANDROID)
-  RegisterDesktopDataTypes(disabled_types, enabled_types);
+  RegisterDesktopDataTypes(disabled_types, enabled_types, sync_client);
 #endif
 }
 
 void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes(
     syncer::ModelTypeSet disabled_types,
-    syncer::ModelTypeSet enabled_types) {
-  sync_driver::SyncService* sync_service = chrome_sync_client_.GetSyncService();
+    syncer::ModelTypeSet enabled_types,
+    sync_driver::SyncClient* sync_client) {
+  sync_driver::SyncService* sync_service = sync_client->GetSyncService();
 
   // TODO(stanisc): can DEVICE_INFO be one of disabled datatypes?
   sync_service->RegisterDataTypeController(new DeviceInfoDataTypeController(
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-      base::Bind(&ChromeReportUnrecoverableError),
-      &chrome_sync_client_,
+      base::Bind(&ChromeReportUnrecoverableError), sync_client,
       sync_service->GetLocalDeviceInfoProvider()));
 
   // Autofill sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::AUTOFILL)) {
     sync_service->RegisterDataTypeController(
-        new AutofillDataTypeController(&chrome_sync_client_));
+        new AutofillDataTypeController(sync_client));
   }
 
   // Autofill profile sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::AUTOFILL_PROFILE)) {
     sync_service->RegisterDataTypeController(
-        new AutofillProfileDataTypeController(&chrome_sync_client_));
+        new AutofillProfileDataTypeController(sync_client));
   }
 
   // Wallet data sync is enabled by default, but behind a syncer experiment
@@ -191,7 +187,7 @@
   if (!wallet_disabled) {
     sync_service->RegisterDataTypeController(
         new browser_sync::AutofillWalletDataTypeController(
-            &chrome_sync_client_, syncer::AUTOFILL_WALLET_DATA));
+            sync_client, syncer::AUTOFILL_WALLET_DATA));
   }
 
   // Wallet metadata sync depends on Wallet data sync and is disabled by
@@ -200,14 +196,14 @@
   if (!wallet_disabled && enabled_types.Has(syncer::AUTOFILL_WALLET_METADATA)) {
     sync_service->RegisterDataTypeController(
         new browser_sync::AutofillWalletDataTypeController(
-            &chrome_sync_client_, syncer::AUTOFILL_WALLET_METADATA));
+            sync_client, syncer::AUTOFILL_WALLET_METADATA));
   }
 
   // Bookmark sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::BOOKMARKS)) {
     sync_service->RegisterDataTypeController(
-        new BookmarkDataTypeController(&chrome_sync_client_));
+        new BookmarkDataTypeController(sync_client));
   }
 
   const bool history_disabled =
@@ -216,7 +212,7 @@
   // or if saving history is disabled.
   if (!disabled_types.Has(syncer::TYPED_URLS) && !history_disabled) {
     sync_service->RegisterDataTypeController(
-        new TypedUrlDataTypeController(&chrome_sync_client_));
+        new TypedUrlDataTypeController(sync_client));
   }
 
   // Delete directive sync is enabled by default.  Register unless full history
@@ -224,7 +220,7 @@
   if (!disabled_types.Has(syncer::HISTORY_DELETE_DIRECTIVES) &&
       !history_disabled) {
     sync_service->RegisterDataTypeController(
-        new HistoryDeleteDirectivesDataTypeController(&chrome_sync_client_));
+        new HistoryDeleteDirectivesDataTypeController(sync_client));
   }
 
   // Session sync is enabled by default.  Register unless explicitly disabled.
@@ -239,7 +235,7 @@
     // ProfileSyncService at this level.
     ProfileSyncService* pss = static_cast<ProfileSyncService*>(sync_service);
     sync_service->RegisterDataTypeController(new SessionDataTypeController(
-        &chrome_sync_client_, profile_, pss->GetSyncedWindowDelegatesGetter(),
+        sync_client, profile_, pss->GetSyncedWindowDelegatesGetter(),
         sync_service->GetLocalDeviceInfoProvider()));
   }
 
@@ -248,97 +244,82 @@
       !disabled_types.Has(syncer::FAVICON_TRACKING) &&
       !history_disabled) {
     // crbug/384552. We disable error uploading for this data types for now.
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Closure(),
-            syncer::FAVICON_IMAGES,
-            &chrome_sync_client_));
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Closure(),
-            syncer::FAVICON_TRACKING,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Closure(), syncer::FAVICON_IMAGES, sync_client));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Closure(), syncer::FAVICON_TRACKING, sync_client));
   }
 
   // Password sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::PASSWORDS)) {
     sync_service->RegisterDataTypeController(
-        new PasswordDataTypeController(&chrome_sync_client_, profile_));
+        new PasswordDataTypeController(sync_client, profile_));
   }
 
   if (!disabled_types.Has(syncer::PRIORITY_PREFERENCES)) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::PRIORITY_PREFERENCES,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError),
+        syncer::PRIORITY_PREFERENCES, sync_client));
   }
 
   // Article sync is disabled by default.  Register only if explicitly enabled.
   if (dom_distiller::IsEnableSyncArticlesSet()) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::ARTICLES,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError), syncer::ARTICLES,
+        sync_client));
   }
 
 #if defined(ENABLE_SUPERVISED_USERS)
   sync_service->RegisterDataTypeController(
-      new SupervisedUserSyncDataTypeController(
-          syncer::SUPERVISED_USER_SETTINGS,
-          &chrome_sync_client_,
-          profile_));
+      new SupervisedUserSyncDataTypeController(syncer::SUPERVISED_USER_SETTINGS,
+                                               sync_client, profile_));
   sync_service->RegisterDataTypeController(
       new SupervisedUserSyncDataTypeController(
-          syncer::SUPERVISED_USER_WHITELISTS,
-          &chrome_sync_client_,
-          profile_));
+          syncer::SUPERVISED_USER_WHITELISTS, sync_client, profile_));
 #endif
 }
 
 void ProfileSyncComponentsFactoryImpl::RegisterDesktopDataTypes(
     syncer::ModelTypeSet disabled_types,
-    syncer::ModelTypeSet enabled_types) {
-  sync_driver::SyncService* sync_service = chrome_sync_client_.GetSyncService();
+    syncer::ModelTypeSet enabled_types,
+    sync_driver::SyncClient* sync_client) {
+  sync_driver::SyncService* sync_service = sync_client->GetSyncService();
 
 #if defined(ENABLE_EXTENSIONS)
   // App sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::APPS)) {
-    sync_service->RegisterDataTypeController(new ExtensionDataTypeController(
-        syncer::APPS, &chrome_sync_client_, profile_));
+    sync_service->RegisterDataTypeController(
+        new ExtensionDataTypeController(syncer::APPS, sync_client, profile_));
   }
 
   // Extension sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::EXTENSIONS)) {
     sync_service->RegisterDataTypeController(new ExtensionDataTypeController(
-        syncer::EXTENSIONS, &chrome_sync_client_, profile_));
+        syncer::EXTENSIONS, sync_client, profile_));
   }
 #endif
 
   // Preference sync is enabled by default.  Register unless explicitly
   // disabled.
   if (!disabled_types.Has(syncer::PREFERENCES)) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::PREFERENCES,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError), syncer::PREFERENCES,
+        sync_client));
   }
 
 #if defined(ENABLE_THEMES)
   // Theme sync is enabled by default.  Register unless explicitly disabled.
   if (!disabled_types.Has(syncer::THEMES)) {
     sync_service->RegisterDataTypeController(
-        new ThemeDataTypeController(&chrome_sync_client_, profile_));
+        new ThemeDataTypeController(sync_client, profile_));
   }
 #endif
 
@@ -346,7 +327,7 @@
   // disabled.
   if (!disabled_types.Has(syncer::SEARCH_ENGINES)) {
     sync_service->RegisterDataTypeController(
-        new SearchEngineDataTypeController(&chrome_sync_client_, profile_));
+        new SearchEngineDataTypeController(sync_client, profile_));
   }
 
 #if defined(ENABLE_EXTENSIONS)
@@ -355,7 +336,7 @@
   if (!disabled_types.Has(syncer::EXTENSION_SETTINGS)) {
     sync_service->RegisterDataTypeController(
         new ExtensionSettingDataTypeController(syncer::EXTENSION_SETTINGS,
-                                               &chrome_sync_client_, profile_));
+                                               sync_client, profile_));
   }
 
   // App setting sync is enabled by default.  Register unless explicitly
@@ -363,55 +344,45 @@
   if (!disabled_types.Has(syncer::APP_SETTINGS)) {
     sync_service->RegisterDataTypeController(
         new ExtensionSettingDataTypeController(syncer::APP_SETTINGS,
-                                               &chrome_sync_client_, profile_));
+                                               sync_client, profile_));
   }
 #endif
 
 #if defined(ENABLE_APP_LIST)
   if (app_list::switches::IsAppListSyncEnabled()) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::APP_LIST,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError), syncer::APP_LIST,
+        sync_client));
   }
 #endif
 
 #if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_CHROMEOS)
   // Dictionary sync is enabled by default.
   if (!disabled_types.Has(syncer::DICTIONARY)) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::DICTIONARY,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError), syncer::DICTIONARY,
+        sync_client));
   }
 #endif
 
 #if defined(ENABLE_SUPERVISED_USERS)
   sync_service->RegisterDataTypeController(
-      new SupervisedUserSyncDataTypeController(
-          syncer::SUPERVISED_USERS,
-          &chrome_sync_client_,
-          profile_));
+      new SupervisedUserSyncDataTypeController(syncer::SUPERVISED_USERS,
+                                               sync_client, profile_));
   sync_service->RegisterDataTypeController(
       new SupervisedUserSyncDataTypeController(
-          syncer::SUPERVISED_USER_SHARED_SETTINGS,
-          &chrome_sync_client_,
-          profile_));
+          syncer::SUPERVISED_USER_SHARED_SETTINGS, sync_client, profile_));
 #endif
 
 #if defined(OS_CHROMEOS)
   if (command_line_->HasSwitch(switches::kEnableWifiCredentialSync) &&
       !disabled_types.Has(syncer::WIFI_CREDENTIALS)) {
-    sync_service->RegisterDataTypeController(
-        new UIDataTypeController(
-            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
-            base::Bind(&ChromeReportUnrecoverableError),
-            syncer::WIFI_CREDENTIALS,
-            &chrome_sync_client_));
+    sync_service->RegisterDataTypeController(new UIDataTypeController(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
+        base::Bind(&ChromeReportUnrecoverableError), syncer::WIFI_CREDENTIALS,
+        sync_client));
   }
 #endif
 }
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.h b/chrome/browser/sync/profile_sync_components_factory_impl.h
index f3e99ca9e..f9f788d 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_components_factory_impl.h
@@ -10,7 +10,6 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/sync/chrome_sync_client.h"
 #include "components/sync_driver/sync_api_component_factory.h"
 #include "sync/internal_api/public/base/model_type.h"
 #include "url/gurl.h"
@@ -45,10 +44,7 @@
       net::URLRequestContextGetter* url_request_context_getter);
   ~ProfileSyncComponentsFactoryImpl() override;
 
-  // Initializes internal state after construction.
-  void Initialize(sync_driver::SyncService* sync_service) override;
-
-  void RegisterDataTypes() override;
+  void RegisterDataTypes(sync_driver::SyncClient* sync_client) override;
 
   sync_driver::DataTypeManager* CreateDataTypeManager(
       const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
@@ -90,12 +86,15 @@
   // |disabled_types| and |enabled_types| correspond only to those types
   // being explicitly enabled/disabled by the command line.
   void RegisterDesktopDataTypes(syncer::ModelTypeSet disabled_types,
-                                syncer::ModelTypeSet enabled_types);
+                                syncer::ModelTypeSet enabled_types,
+                                sync_driver::SyncClient* sync_client);
+
   // Register data types which are enabled on both desktop and mobile.
   // |disabled_types| and |enabled_types| correspond only to those types
   // being explicitly enabled/disabled by the command line.
   void RegisterCommonDataTypes(syncer::ModelTypeSet disabled_types,
-                               syncer::ModelTypeSet enabled_types);
+                               syncer::ModelTypeSet enabled_types,
+                               sync_driver::SyncClient* sync_client);
 
   void DisableBrokenType(syncer::ModelType type,
                          const tracked_objects::Location& from_here,
@@ -108,11 +107,6 @@
   OAuth2TokenService* const token_service_;
   net::URLRequestContextGetter* const url_request_context_getter_;
 
-  // Chrome specific implementation of SyncClient.
-  // TODO(zea): Move the creation of this into the ProfileSyncServiceFactory,
-  // and ownership to the ProfileSyncService itself.
-  browser_sync::ChromeSyncClient chrome_sync_client_;
-
   base::WeakPtrFactory<ProfileSyncComponentsFactoryImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileSyncComponentsFactoryImpl);
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
index 63a5176..1525972 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/profile_sync_components_factory_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -109,20 +110,18 @@
         GetSyncServiceURL(*command_line_, chrome::GetChannel());
     ProfileOAuth2TokenService* token_service =
         ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
-    scoped_ptr<ProfileSyncService> pss(new ProfileSyncService(
-        scoped_ptr<sync_driver::SyncApiComponentFactory>(
-            new ProfileSyncComponentsFactoryImpl(
-                profile_.get(),
-                command_line_.get(),
-                GetSyncServiceURL(*command_line_, chrome::GetChannel()),
-                token_service,
-                profile_->GetRequestContext())),
-        profile_.get(),
-        make_scoped_ptr<SigninManagerWrapper>(NULL),
-        token_service,
-        browser_sync::MANUAL_START));
-    pss->factory()->Initialize(pss.get());
-    pss->factory()->RegisterDataTypes();
+    scoped_ptr<sync_driver::SyncApiComponentFactory> factory(
+        new ProfileSyncComponentsFactoryImpl(
+            profile_.get(), command_line_.get(),
+            GetSyncServiceURL(*command_line_, chrome::GetChannel()),
+            token_service, profile_->GetRequestContext()));
+    scoped_ptr<sync_driver::SyncClient> sync_client(
+        new browser_sync::ChromeSyncClient(profile_.get(), factory.Pass()));
+    scoped_ptr<ProfileSyncService> pss(
+        new ProfileSyncService(sync_client.Pass(), profile_.get(),
+                               make_scoped_ptr<SigninManagerWrapper>(NULL),
+                               token_service, browser_sync::MANUAL_START));
+    pss->GetSyncClient()->Initialize(pss.get());
     DataTypeController::StateMap controller_states;
     pss->GetDataTypeControllerStates(&controller_states);
     EXPECT_EQ(DefaultDatatypesCount() - types.Size(), controller_states.size());
@@ -138,20 +137,18 @@
 TEST_F(ProfileSyncComponentsFactoryImplTest, CreatePSSDefault) {
   ProfileOAuth2TokenService* token_service =
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
-  scoped_ptr<ProfileSyncService> pss(new ProfileSyncService(
-      scoped_ptr<sync_driver::SyncApiComponentFactory>(
-          new ProfileSyncComponentsFactoryImpl(
-              profile_.get(),
-              command_line_.get(),
-              GetSyncServiceURL(*command_line_, chrome::GetChannel()),
-              token_service,
-              profile_->GetRequestContext())),
-      profile_.get(),
-      make_scoped_ptr<SigninManagerWrapper>(NULL),
-      token_service,
-      browser_sync::MANUAL_START));
-  pss->factory()->Initialize(pss.get());
-  pss->factory()->RegisterDataTypes();
+  scoped_ptr<sync_driver::SyncApiComponentFactory> factory(
+      new ProfileSyncComponentsFactoryImpl(
+          profile_.get(), command_line_.get(),
+          GetSyncServiceURL(*command_line_, chrome::GetChannel()),
+          token_service, profile_->GetRequestContext()));
+  scoped_ptr<sync_driver::SyncClient> sync_client(
+      new browser_sync::ChromeSyncClient(profile_.get(), factory.Pass()));
+  scoped_ptr<ProfileSyncService> pss(
+      new ProfileSyncService(sync_client.Pass(), profile_.get(),
+                             make_scoped_ptr<SigninManagerWrapper>(NULL),
+                             token_service, browser_sync::MANUAL_START));
+  pss->GetSyncClient()->Initialize(pss.get());
   DataTypeController::StateMap controller_states;
   pss->GetDataTypeControllerStates(&controller_states);
   EXPECT_EQ(DefaultDatatypesCount(), controller_states.size());
diff --git a/chrome/browser/sync/profile_sync_components_factory_mock.h b/chrome/browser/sync/profile_sync_components_factory_mock.h
index c6f83b18..98e0ebe 100644
--- a/chrome/browser/sync/profile_sync_components_factory_mock.h
+++ b/chrome/browser/sync/profile_sync_components_factory_mock.h
@@ -28,8 +28,7 @@
       sync_driver::ChangeProcessor* change_processor);
   ~ProfileSyncComponentsFactoryMock() override;
 
-  MOCK_METHOD1(Initialize, void(sync_driver::SyncService*));
-  MOCK_METHOD0(RegisterDataTypes, void());
+  MOCK_METHOD1(RegisterDataTypes, void(sync_driver::SyncClient*));
   MOCK_METHOD5(CreateDataTypeManager,
                sync_driver::DataTypeManager*(
                    const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&,
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 7fd0509..d62419ca 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -73,6 +73,7 @@
 #include "components/sync_driver/favicon_cache.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/sync_api_component_factory.h"
+#include "components/sync_driver/sync_client.h"
 #include "components/sync_driver/sync_driver_switches.h"
 #include "components/sync_driver/sync_error_controller.h"
 #include "components/sync_driver/sync_stopped_reporter.h"
@@ -207,7 +208,7 @@
 }
 
 ProfileSyncService::ProfileSyncService(
-    scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
+    scoped_ptr<sync_driver::SyncClient> sync_client,
     Profile* profile,
     scoped_ptr<SigninManagerWrapper> signin_wrapper,
     ProfileOAuth2TokenService* oauth2_token_service,
@@ -215,7 +216,7 @@
     : OAuth2TokenService::Consumer("sync"),
       last_auth_error_(AuthError::AuthErrorNone()),
       passphrase_required_reason_(syncer::REASON_PASSPHRASE_NOT_REQUIRED),
-      factory_(factory.Pass()),
+      sync_client_(sync_client.Pass()),
       profile_(profile),
       sync_prefs_(profile_->GetPrefs()),
       sync_service_url_(
@@ -271,8 +272,8 @@
   scoped_ptr<browser_sync::LocalSessionEventRouter> router(
       new NotificationServiceSessionsRouter(profile, flare));
 
-  DCHECK(factory_.get());
-  local_device_ = factory_->CreateLocalDeviceInfoProvider();
+  local_device_ = sync_client_->GetSyncApiComponentFactory()
+                      ->CreateLocalDeviceInfoProvider();
   sync_stopped_reporter_.reset(
           new browser_sync::SyncStoppedReporter(
               sync_service_url_,
@@ -322,6 +323,8 @@
 }
 
 void ProfileSyncService::Initialize() {
+  sync_client_->Initialize(this);
+
   // We clear this here (vs Shutdown) because we want to remember that an error
   // happened on shutdown so we can display details (message, location) about it
   // in about:sync.
@@ -699,10 +702,8 @@
   directory_path_ = profile_->GetPath().Append(sync_folder);
 
   backend_.reset(
-      factory_->CreateSyncBackendHost(
-          profile_->GetDebugName(),
-          invalidator,
-          sync_prefs_.AsWeakPtr(),
+      sync_client_->GetSyncApiComponentFactory()->CreateSyncBackendHost(
+          profile_->GetDebugName(), invalidator, sync_prefs_.AsWeakPtr(),
           sync_folder));
 
   // Initialize the backend.  Every time we start up a new SyncBackendHost,
@@ -1810,6 +1811,8 @@
 void ProfileSyncService::OnUserChoseDatatypes(
     bool sync_everything,
     syncer::ModelTypeSet chosen_types) {
+  DCHECK(syncer::UserSelectableTypes().HasAll(chosen_types));
+
   if (!backend_.get() && !HasUnrecoverableError()) {
     NOTREACHED();
     return;
@@ -1847,7 +1850,8 @@
 syncer::ModelTypeSet ProfileSyncService::GetPreferredDataTypes() const {
   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   const syncer::ModelTypeSet preferred_types =
-      sync_prefs_.GetPreferredDataTypes(registered_types);
+      Union(sync_prefs_.GetPreferredDataTypes(registered_types),
+            syncer::ControlTypes());
   const syncer::ModelTypeSet enforced_types =
       Intersection(GetDataTypesFromPreferenceProviders(), registered_types);
   return Union(preferred_types, enforced_types);
@@ -1903,9 +1907,10 @@
   bool restart = false;
   if (!data_type_manager_) {
     restart = true;
-    data_type_manager_.reset(factory_->CreateDataTypeManager(
-        debug_info_listener_, &data_type_controllers_, this, backend_.get(),
-        this));
+    data_type_manager_.reset(
+        sync_client_->GetSyncApiComponentFactory()->CreateDataTypeManager(
+            debug_info_listener_, &data_type_controllers_, this, backend_.get(),
+            this));
 
     // We create the migrator at the same time.
     migrator_.reset(new browser_sync::BackendMigrator(
@@ -2655,6 +2660,10 @@
     backend_->FlushDirectory();
 }
 
+sync_driver::SyncClient* ProfileSyncService::GetSyncClient() const {
+  return sync_client_.get();
+}
+
 base::FilePath ProfileSyncService::GetDirectoryPathForTest() const {
   return directory_path_;
 }
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index a7c19ef6..7d40410 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -70,6 +70,7 @@
 class LocalDeviceInfoProvider;
 class OpenTabsUIDelegate;
 class SyncApiComponentFactory;
+class SyncClient;
 }  // namespace sync_driver
 
 namespace syncer {
@@ -228,7 +229,7 @@
 
   // Takes ownership of |factory| and |signin_wrapper|.
   ProfileSyncService(
-      scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
+      scoped_ptr<sync_driver::SyncClient> sync_client,
       Profile* profile,
       scoped_ptr<SigninManagerWrapper> signin_wrapper,
       ProfileOAuth2TokenService* oauth2_token_service,
@@ -408,10 +409,6 @@
   // never become active. Use IsSyncActive to see if sync is running.
   virtual bool IsSyncRequested() const;
 
-  sync_driver::SyncApiComponentFactory* factory() const {
-    return factory_.get();
-  }
-
   // The profile we are syncing for.
   Profile* profile() const { return profile_; }
 
@@ -564,6 +561,9 @@
   // killed in the near future.
   void FlushDirectory() const;
 
+  // Returns the SyncClient associated with this profile.
+  sync_driver::SyncClient* GetSyncClient() const;
+
   // Needed to test whether the directory is deleted properly.
   base::FilePath GetDirectoryPathForTest() const;
 
@@ -780,8 +780,9 @@
   // Restarts sync clearing directory in the process.
   void OnClearServerDataDone();
 
-  // Factory used to create various dependent objects.
-  scoped_ptr<sync_driver::SyncApiComponentFactory> factory_;
+  // This profile's SyncClient, which abstracts away non-Sync dependencies and
+  // the Sync API component factory.
+  scoped_ptr<sync_driver::SyncClient> sync_client_;
 
   // The profile whose data we are synchronizing.
   Profile* profile_;
diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc
index a75318a..898371f0 100644
--- a/chrome/browser/sync/profile_sync_service_android.cc
+++ b/chrome/browser/sync/profile_sync_service_android.cc
@@ -311,14 +311,12 @@
 ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetActiveDataTypes(
       JNIEnv* env, jobject obj) {
   syncer::ModelTypeSet types = sync_service_->GetActiveDataTypes();
-  types.PutAll(syncer::ControlTypes());
   return ModelTypeSetToJavaIntArray(env, types);
 }
 
 ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetPreferredDataTypes(
       JNIEnv* env, jobject obj) {
   syncer::ModelTypeSet types = sync_service_->GetPreferredDataTypes();
-  types.PutAll(syncer::ControlTypes());
   return ModelTypeSetToJavaIntArray(env, types);
 }
 
@@ -333,7 +331,6 @@
   for (size_t i = 0; i < types_vector.size(); i++) {
     types.Put(static_cast<syncer::ModelType>(types_vector[i]));
   }
-  types.RetainAll(syncer::UserSelectableTypes());
   sync_service_->OnUserChoseDatatypes(sync_everything, types);
 }
 
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 74075bf..dfab2554 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -512,7 +512,7 @@
     sync_client_->SetSyncService(sync_service_);
 
     ProfileSyncComponentsFactoryMock* components =
-        sync_service_->components_factory_mock();
+        sync_service_->GetSyncApiComponentFactoryMock();
 
     EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _)).
         WillOnce(ReturnNewDataTypeManagerWithDebugListener(
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index 74e4891..abe5d80 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/profile_sync_components_factory_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/startup_controller.h"
@@ -154,14 +155,15 @@
   browser_sync::ProfileSyncServiceStartBehavior behavior =
       browser_defaults::kSyncAutoStarts ? browser_sync::AUTO_START
                                         : browser_sync::MANUAL_START;
-  ProfileSyncService* pss = new ProfileSyncService(
-      scoped_ptr<sync_driver::SyncApiComponentFactory>(
-          new ProfileSyncComponentsFactoryImpl(
-              profile, base::CommandLine::ForCurrentProcess(), sync_service_url,
-              token_service, url_request_context_getter)),
-      profile, signin_wrapper.Pass(), token_service, behavior);
-  pss->factory()->Initialize(pss);
-  pss->factory()->RegisterDataTypes();
+  scoped_ptr<sync_driver::SyncApiComponentFactory> sync_factory(
+      new ProfileSyncComponentsFactoryImpl(
+          profile, base::CommandLine::ForCurrentProcess(), sync_service_url,
+          token_service, url_request_context_getter));
+  scoped_ptr<browser_sync::ChromeSyncClient> sync_client(
+      new browser_sync::ChromeSyncClient(profile, sync_factory.Pass()));
+  ProfileSyncService* pss =
+      new ProfileSyncService(sync_client.Pass(), profile, signin_wrapper.Pass(),
+                             token_service, behavior);
   pss->Initialize();
   return pss;
 }
diff --git a/chrome/browser/sync/profile_sync_service_mock.cc b/chrome/browser/sync/profile_sync_service_mock.cc
index 83a4b70..3d677a24 100644
--- a/chrome/browser/sync/profile_sync_service_mock.cc
+++ b/chrome/browser/sync/profile_sync_service_mock.cc
@@ -8,6 +8,7 @@
 #include "base/prefs/testing_pref_store.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -18,15 +19,18 @@
 
 ProfileSyncServiceMock::ProfileSyncServiceMock(Profile* profile)
     : ProfileSyncServiceMock(
-          scoped_ptr<sync_driver::SyncApiComponentFactory>(
-              new ProfileSyncComponentsFactoryMock()),
-          profile) {
-}
+          make_scoped_ptr(
+              new browser_sync::ChromeSyncClient(
+                  profile,
+                  make_scoped_ptr(new ProfileSyncComponentsFactoryMock())))
+              .Pass(),
+          profile) {}
 
 ProfileSyncServiceMock::ProfileSyncServiceMock(
-    scoped_ptr<sync_driver::SyncApiComponentFactory> factory, Profile* profile)
+    scoped_ptr<sync_driver::SyncClient> sync_client,
+    Profile* profile)
     : ProfileSyncService(
-          factory.Pass(),
+          sync_client.Pass(),
           profile,
           make_scoped_ptr(new SigninManagerWrapper(
               SigninManagerFactory::GetForProfile(profile))),
diff --git a/chrome/browser/sync/profile_sync_service_mock.h b/chrome/browser/sync/profile_sync_service_mock.h
index a241cb30..b6968ac 100644
--- a/chrome/browser/sync/profile_sync_service_mock.h
+++ b/chrome/browser/sync/profile_sync_service_mock.h
@@ -23,12 +23,15 @@
 
 using ::testing::Invoke;
 
+namespace sync_driver {
+class SyncClient;
+}
+
 class ProfileSyncServiceMock : public ProfileSyncService {
  public:
   explicit ProfileSyncServiceMock(Profile* profile);
-  ProfileSyncServiceMock(
-      scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
-      Profile* profile);
+  ProfileSyncServiceMock(scoped_ptr<sync_driver::SyncClient> sync_client,
+                         Profile* profile);
   virtual ~ProfileSyncServiceMock();
 
   // A utility used by sync tests to create a TestingProfile with a Google
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index 8e6e216..babea25 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/signin/fake_signin_manager_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service.h"
@@ -77,13 +78,16 @@
 class TestProfileSyncServiceNoBackup : public ProfileSyncService {
  public:
   TestProfileSyncServiceNoBackup(
-      scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
+      scoped_ptr<sync_driver::SyncClient> sync_client,
       Profile* profile,
       scoped_ptr<SigninManagerWrapper> signin_wrapper,
       ProfileOAuth2TokenService* oauth2_token_service,
       browser_sync::ProfileSyncServiceStartBehavior start_behavior)
-     : ProfileSyncService(factory.Pass(), profile, signin_wrapper.Pass(),
-                          oauth2_token_service, start_behavior) {}
+      : ProfileSyncService(sync_client.Pass(),
+                           profile,
+                           signin_wrapper.Pass(),
+                           oauth2_token_service,
+                           start_behavior) {}
 
  protected:
   bool NeedBackup() const override { return false; }
@@ -124,11 +128,13 @@
   static scoped_ptr<KeyedService> BuildService(
       content::BrowserContext* browser_context) {
     Profile* profile = static_cast<Profile*>(browser_context);
+    scoped_ptr<browser_sync::ChromeSyncClient> sync_client(
+        new browser_sync::ChromeSyncClient(
+            profile, make_scoped_ptr(new ProfileSyncComponentsFactoryMock())));
     return make_scoped_ptr(new TestProfileSyncServiceNoBackup(
-        scoped_ptr<sync_driver::SyncApiComponentFactory>(
-            new ProfileSyncComponentsFactoryMock()),
-        profile, make_scoped_ptr(new SigninManagerWrapper(
-                     SigninManagerFactory::GetForProfile(profile))),
+        sync_client.Pass(), profile,
+        make_scoped_ptr(new SigninManagerWrapper(
+            SigninManagerFactory::GetForProfile(profile))),
         ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
         browser_sync::MANUAL_START));
   }
@@ -144,8 +150,9 @@
         ->UpdateCredentials(account_id, "oauth2_login_token");
   }
 
-  ProfileSyncComponentsFactoryMock* components_factory_mock() {
-    return static_cast<ProfileSyncComponentsFactoryMock*>(sync_->factory());
+  ProfileSyncComponentsFactoryMock* GetSyncApiComponentFactoryMock() {
+    return static_cast<ProfileSyncComponentsFactoryMock*>(
+        sync_->GetSyncClient()->GetSyncApiComponentFactory());
   }
 
   FakeSigninManagerForTesting* fake_signin() {
@@ -184,18 +191,18 @@
 
   DataTypeManagerMock* SetUpDataTypeManager() {
     DataTypeManagerMock* data_type_manager = new DataTypeManagerMock();
-    EXPECT_CALL(*components_factory_mock(),
-                CreateDataTypeManager(_, _, _, _, _)).
-        WillOnce(Return(data_type_manager));
+    EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+                CreateDataTypeManager(_, _, _, _, _))
+        .WillOnce(Return(data_type_manager));
     return data_type_manager;
   }
 
   browser_sync::SyncBackendHostMock* SetUpSyncBackendHost() {
     browser_sync::SyncBackendHostMock* sync_backend_host =
         new browser_sync::SyncBackendHostMock();
-    EXPECT_CALL(*components_factory_mock(),
-                CreateSyncBackendHost(_, _, _, _)).
-        WillOnce(Return(sync_backend_host));
+    EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+                CreateSyncBackendHost(_, _, _, _))
+        .WillOnce(Return(sync_backend_host));
     return sync_backend_host;
   }
 
@@ -227,11 +234,13 @@
     ProfileOAuth2TokenService* oauth2_token_service =
         ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
     EXPECT_TRUE(signin->IsAuthenticated());
+    scoped_ptr<browser_sync::ChromeSyncClient> sync_client(
+        new browser_sync::ChromeSyncClient(
+            profile, make_scoped_ptr(new ProfileSyncComponentsFactoryMock())));
     return make_scoped_ptr(new TestProfileSyncServiceNoBackup(
-        scoped_ptr<sync_driver::SyncApiComponentFactory>(
-            new ProfileSyncComponentsFactoryMock()),
-        profile, make_scoped_ptr(new SigninManagerWrapper(signin)),
-        oauth2_token_service, browser_sync::AUTO_START));
+        sync_client.Pass(), profile,
+        make_scoped_ptr(new SigninManagerWrapper(signin)), oauth2_token_service,
+        browser_sync::AUTO_START));
   }
 };
 
@@ -285,8 +294,9 @@
 
   // Should not actually start, rather just clean things up and wait
   // to be enabled.
-  EXPECT_CALL(*components_factory_mock(),
-              CreateDataTypeManager(_, _, _, _, _)).Times(0);
+  EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+              CreateDataTypeManager(_, _, _, _, _))
+      .Times(0);
   EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
   sync_->Initialize();
 
@@ -359,10 +369,12 @@
 #define MAYBE_StartCrosNoCredentials StartCrosNoCredentials
 #endif
 TEST_F(ProfileSyncServiceStartupCrosTest, MAYBE_StartCrosNoCredentials) {
-  EXPECT_CALL(*components_factory_mock(),
-              CreateDataTypeManager(_, _, _, _, _)).Times(0);
-  EXPECT_CALL(*components_factory_mock(),
-              CreateSyncBackendHost(_, _, _, _)).Times(0);
+  EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+              CreateDataTypeManager(_, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+              CreateSyncBackendHost(_, _, _, _))
+      .Times(0);
   profile_->GetPrefs()->ClearPref(sync_driver::prefs::kSyncHasSetupCompleted);
   EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
 
@@ -498,8 +510,9 @@
 
   // Disable sync through policy.
   profile_->GetPrefs()->SetBoolean(sync_driver::prefs::kSyncManaged, true);
-  EXPECT_CALL(*components_factory_mock(),
-              CreateDataTypeManager(_, _, _, _, _)).Times(0);
+  EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+              CreateDataTypeManager(_, _, _, _, _))
+      .Times(0);
   EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
 
   sync_->Initialize();
@@ -528,8 +541,9 @@
   // When switching back to unmanaged, the state should change, but the service
   // should not start up automatically (kSyncSetupCompleted will be false).
   Mock::VerifyAndClearExpectations(data_type_manager);
-  EXPECT_CALL(*components_factory_mock(),
-              CreateDataTypeManager(_, _, _, _, _)).Times(0);
+  EXPECT_CALL(*GetSyncApiComponentFactoryMock(),
+              CreateDataTypeManager(_, _, _, _, _))
+      .Times(0);
   EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
   profile_->GetPrefs()->ClearPref(sync_driver::prefs::kSyncManaged);
 }
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index a11f16e..ccc86b92 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -268,14 +268,10 @@
       signin->SetAuthenticatedAccountInfo("gaia_id", "test");
       sync_service_ = TestProfileSyncService::BuildAutoStartAsyncInit(profile_,
                                                                       callback);
-      ProfileSyncComponentsFactoryMock* components =
-          sync_service_->components_factory_mock();
-      sync_client_.reset(
-          new browser_sync::ChromeSyncClient(profile_, components));
-      sync_client_->Initialize(sync_service_);
       TypedUrlDataTypeController* data_type_controller =
-          new TypedUrlDataTypeController(sync_client_.get());
-
+          new TypedUrlDataTypeController(sync_service_->GetSyncClient());
+      ProfileSyncComponentsFactoryMock* components =
+          sync_service_->GetSyncApiComponentFactoryMock();
       EXPECT_CALL(*components, CreateTypedUrlSyncComponents(_, _, _)).
           WillOnce(MakeTypedUrlSyncComponents(profile_,
                                               sync_service_,
@@ -411,7 +407,6 @@
   scoped_refptr<HistoryBackendMock> history_backend_;
   HistoryServiceMock* history_service_;
   sync_driver::DataTypeErrorHandlerMock error_handler_;
-  scoped_ptr<browser_sync::ChromeSyncClient> sync_client_;
 };
 
 void AddTypedUrlEntries(ProfileSyncServiceTypedUrlTest* test,
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index b79347d..67ce7645 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -38,6 +38,7 @@
 #include "components/sync_driver/data_type_manager.h"
 #include "components/sync_driver/data_type_manager_observer.h"
 #include "components/sync_driver/fake_data_type_controller.h"
+#include "components/sync_driver/fake_sync_client.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/signin_manager_wrapper.h"
 #include "components/sync_driver/sync_driver_switches.h"
@@ -276,12 +277,12 @@
     signin->SetAuthenticatedAccountInfo(kGaiaId, kEmail);
     ProfileOAuth2TokenService* oauth2_token_service =
         ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
-    components_factory_ = new ProfileSyncComponentsFactoryMock();
+    components_factory_.reset(new ProfileSyncComponentsFactoryMock());
+    scoped_ptr<sync_driver::FakeSyncClient> sync_client(
+        new sync_driver::FakeSyncClient(components_factory_.get()));
     service_.reset(new ProfileSyncService(
-        scoped_ptr<sync_driver::SyncApiComponentFactory>(components_factory_),
-        profile_,
-        make_scoped_ptr(new SigninManagerWrapper(signin)),
-        oauth2_token_service,
+        sync_client.Pass(), profile_,
+        make_scoped_ptr(new SigninManagerWrapper(signin)), oauth2_token_service,
         behavior));
     service_->SetClearingBrowseringDataForTesting(
         base::Bind(&ProfileSyncServiceTest::ClearBrowsingDataCallback,
@@ -393,7 +394,7 @@
   }
 
   ProfileSyncComponentsFactoryMock* components_factory() {
-    return components_factory_;
+    return components_factory_.get();
   }
 
   void ClearBrowsingDataCallback(BrowsingDataRemover::Observer* observer,
@@ -421,8 +422,9 @@
   TestingProfile* profile_;
   scoped_ptr<ProfileSyncService> service_;
 
-  // Pointer to the components factory.  Not owned.  May be null.
-  ProfileSyncComponentsFactoryMock* components_factory_;
+  // The current component factory used by sync. May be null if the server
+  // hasn't been created yet.
+  scoped_ptr<ProfileSyncComponentsFactoryMock> components_factory_;
 };
 
 // Verify that the server URLs are sane.
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index 433a8be..a3901d9 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -44,12 +44,15 @@
   // Setup sync with no enabled types.
   ASSERT_TRUE(GetClient(0)->SetupSync(syncer::ModelTypeSet()));
 
-  const syncer::ModelTypeSet registered_types =
-      GetSyncService(0)->GetRegisteredDataTypes();
   syncer::UserShare* user_share = GetSyncService(0)->GetUserShare();
   const sync_driver::DataTypeStatusTable& data_type_status_table =
       GetSyncService(0)->data_type_status_table();
-  for (syncer::ModelTypeSet::Iterator it = registered_types.First();
+
+  const syncer::ModelTypeSet registered_types =
+      GetSyncService(0)->GetRegisteredDataTypes();
+  const syncer::ModelTypeSet registered_user_types =
+      Intersection(registered_types, syncer::UserSelectableTypes());
+  for (syncer::ModelTypeSet::Iterator it = registered_user_types.First();
        it.Good(); it.Inc()) {
     ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(it.Get()));
 
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
index 1527dc6b..d6670c1b 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -133,7 +133,7 @@
 }
 
 bool ProfileSyncServiceHarness::SetupSync() {
-  bool result = SetupSync(syncer::ModelTypeSet::All());
+  bool result = SetupSync(syncer::UserSelectableTypes());
   if (result == false) {
     std::string status = GetServiceStatus();
     LOG(ERROR) << profile_debug_name_
@@ -189,8 +189,7 @@
 
   // Choose the datatypes to be synced. If all datatypes are to be synced,
   // set sync_everything to true; otherwise, set it to false.
-  bool sync_everything =
-      synced_datatypes.Equals(syncer::ModelTypeSet::All());
+  bool sync_everything = synced_datatypes.Equals(syncer::UserSelectableTypes());
   service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
 
   // Notify ProfileSyncService that we are done with configuration.
@@ -345,6 +344,7 @@
   }
 
   synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
+  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
   service()->OnUserChoseDatatypes(false, synced_datatypes);
   if (AwaitSyncSetupCompletion()) {
     DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index 9522fd1..1e37357b 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -51,6 +51,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
@@ -455,7 +456,7 @@
         BookmarkModelFactory::GetForProfile(verifier()));
     ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
         verifier(), ServiceAccessType::EXPLICIT_ACCESS));
-    ui_test_utils::WaitForTemplateURLServiceToLoad(
+    search_test_utils::WaitForTemplateURLServiceToLoad(
         TemplateURLServiceFactory::GetForProfile(verifier()));
   }
   // Error cases are all handled by LOG(FATAL) messages. So there is not really
@@ -519,7 +520,7 @@
       BookmarkModelFactory::GetForProfile(GetProfile(index)));
   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
       GetProfile(index), ServiceAccessType::EXPLICIT_ACCESS));
-  ui_test_utils::WaitForTemplateURLServiceToLoad(
+  search_test_utils::WaitForTemplateURLServiceToLoad(
       TemplateURLServiceFactory::GetForProfile(GetProfile(index)));
 }
 
@@ -969,9 +970,9 @@
 
   // In order to kick off the encryption we have to reconfigure. Just grab the
   // currently synced types and use them.
-  const syncer::ModelTypeSet synced_datatypes =
-      service->GetPreferredDataTypes();
+  syncer::ModelTypeSet synced_datatypes = service->GetPreferredDataTypes();
   bool sync_everything = synced_datatypes.Equals(syncer::ModelTypeSet::All());
+  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
   service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
 
   return AwaitEncryptionComplete(index);
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index a7e1f49..323b9571 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
@@ -118,13 +119,14 @@
 }
 
 TestProfileSyncService::TestProfileSyncService(
-    scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
     Profile* profile,
     SigninManagerBase* signin,
     ProfileOAuth2TokenService* oauth2_token_service,
     browser_sync::ProfileSyncServiceStartBehavior behavior)
     : ProfileSyncService(
-          factory.Pass(),
+          make_scoped_ptr(new browser_sync::ChromeSyncClient(
+              profile,
+              make_scoped_ptr(new ProfileSyncComponentsFactoryMock))),
           profile,
           make_scoped_ptr(new SigninManagerWrapper(signin)),
           oauth2_token_service,
@@ -144,8 +146,6 @@
   ProfileOAuth2TokenService* oauth2_token_service =
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
   return make_scoped_ptr(new TestProfileSyncService(
-      scoped_ptr<sync_driver::SyncApiComponentFactory>(
-          new ProfileSyncComponentsFactoryMock()),
       profile, signin, oauth2_token_service, browser_sync::AUTO_START));
 }
 
@@ -156,7 +156,7 @@
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
             profile, &TestProfileSyncService::TestFactoryFunction));
   ProfileSyncComponentsFactoryMock* components =
-      sync_service->components_factory_mock();
+      sync_service->GetSyncApiComponentFactoryMock();
   // TODO(tim): Convert to a fake instead of mock.
   EXPECT_CALL(*components, CreateSyncBackendHost(testing::_, testing::_,
                                                  testing::_, testing::_))
@@ -172,9 +172,10 @@
 }
 
 ProfileSyncComponentsFactoryMock*
-TestProfileSyncService::components_factory_mock() {
+TestProfileSyncService::GetSyncApiComponentFactoryMock() {
   // We always create a mock factory, see Build* routines.
-  return static_cast<ProfileSyncComponentsFactoryMock*>(factory());
+  return static_cast<ProfileSyncComponentsFactoryMock*>(
+      GetSyncClient()->GetSyncApiComponentFactory());
 }
 
 void TestProfileSyncService::OnConfigureDone(
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 152072b..edd4e54 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -72,7 +72,6 @@
   // TODO(tim): Add ability to inject TokenService alongside SigninManager.
   // TODO(rogerta): what does above comment mean?
   TestProfileSyncService(
-      scoped_ptr<sync_driver::SyncApiComponentFactory> factory,
       Profile* profile,
       SigninManagerBase* signin,
       ProfileOAuth2TokenService* oauth2_token_service,
@@ -89,7 +88,7 @@
   static TestProfileSyncService* BuildAutoStartAsyncInit(
       Profile* profile, base::Closure callback);
 
-  ProfileSyncComponentsFactoryMock* components_factory_mock();
+  ProfileSyncComponentsFactoryMock* GetSyncApiComponentFactoryMock();
 
   syncer::TestIdFactory* id_factory();
 
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index f7feec4..ab4d5a9 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/task_manager/tab_contents_information.h"
 #include "chrome/browser/task_manager/web_contents_resource_provider.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/user_manager.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index cf6e4fcd..e0c8bda 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/panels/panel.h"
 #include "chrome/browser/ui/panels/panel_manager.h"
diff --git a/chrome/browser/themes/theme_syncable_service_unittest.cc b/chrome/browser/themes/theme_syncable_service_unittest.cc
index cf0bdfa8..7a77287 100644
--- a/chrome/browser/themes/theme_syncable_service_unittest.cc
+++ b/chrome/browser/themes/theme_syncable_service_unittest.cc
@@ -186,13 +186,9 @@
                                           kCustomThemeName,
                                           GetThemeLocation(),
                                           kCustomThemeUrl);
-    extensions::APIPermissionSet empty_set;
-    extensions::ManifestPermissionSet empty_manifest_permissions;
-    extensions::URLPatternSet empty_extent;
-    extensions::PermissionSet permissions(empty_set, empty_manifest_permissions,
-                                          empty_extent, empty_extent);
     extensions::ExtensionPrefs::Get(profile_.get())
-        ->AddGrantedPermissions(theme_extension_->id(), &permissions);
+        ->AddGrantedPermissions(theme_extension_->id(),
+                                extensions::PermissionSet());
     service->AddExtension(theme_extension_.get());
     extensions::ExtensionRegistry* registry =
         extensions::ExtensionRegistry::Get(profile_.get());
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 66e0fd4..656a4876 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -182,9 +182,6 @@
                            "//chrome")
     deps += [ "//chrome/browser/chromeos" ]
   } else {
-    sources += rebase_path(gypi_values.chrome_browser_ui_non_chromeos_sources,
-                           ".",
-                           "//chrome")
     defines += [ "FRAME_AVATAR_BUTTON=1" ]
   }
   if (use_cups) {
@@ -526,6 +523,16 @@
     }
   }
 
+  if (is_android) {
+    sources -= [
+      "exclusive_access/fullscreen_controller_state_test.cc",
+      "exclusive_access/fullscreen_controller_state_test.h",
+      "exclusive_access/fullscreen_controller_state_tests.h",
+      "exclusive_access/fullscreen_controller_test.cc",
+      "exclusive_access/fullscreen_controller_test.h",
+    ]
+  }
+
   public_deps = [
     ":ui",
   ]
diff --git a/chrome/browser/ui/android/tab_model/tab_model_list.cc b/chrome/browser/ui/android/tab_model/tab_model_list.cc
index 04985b7..bcf950c 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_list.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model_list.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "content/public/browser/web_contents.h"
 
 namespace {
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate_impl.cc b/chrome/browser/ui/app_list/app_list_controller_delegate_impl.cc
index 4733461f..f7e62f3f 100644
--- a/chrome/browser/ui/app_list/app_list_controller_delegate_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_controller_delegate_impl.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
index 6b48d665..55fba9c 100644
--- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
+++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc
@@ -122,8 +122,9 @@
 // Returns true if icon image of |result_image| equals to |expected_image|.
 bool IsEqual(const gfx::ImageSkia& expected_image,
              const gfx::ImageSkia& result_image) {
-  return gfx::test::IsEqual(expected_image.GetRepresentation(1.0).sk_bitmap(),
-                            result_image.GetRepresentation(1.0).sk_bitmap());
+  return gfx::test::AreBitmapsEqual(
+      expected_image.GetRepresentation(1.0).sk_bitmap(),
+      result_image.GetRepresentation(1.0).sk_bitmap());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/app_list/start_page_service.cc b/chrome/browser/ui/app_list/start_page_service.cc
index 33308bcf2..599f11a 100644
--- a/chrome/browser/ui/app_list/start_page_service.cc
+++ b/chrome/browser/ui/app_list/start_page_service.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_piece.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/media/media_stream_infobar_delegate.h"
+#include "chrome/browser/media/media_stream_devices_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/hotword_service.h"
 #include "chrome/browser/search/hotword_service_factory.h"
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/app_list/start_page_observer.h"
 #include "chrome/browser/ui/app_list/start_page_service_factory.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/common/chrome_switches.h"
@@ -156,7 +157,8 @@
       content::WebContents* web_contents,
       const content::MediaStreamRequest& request,
       const content::MediaResponseCallback& callback) override {
-    if (MediaStreamInfoBarDelegate::Create(web_contents, request, callback))
+    MediaStreamDevicesController controller(web_contents, request, callback);
+    if (controller.IsAskingForVideo() || controller.IsAskingForAudio())
       NOTREACHED() << "Media stream not allowed for WebUI";
   }
 
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc
index 7910b96..906cdeb 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_delegate.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
diff --git a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
index ee162fc..0a90207 100644
--- a/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_controller_ash.cc
@@ -8,6 +8,7 @@
 #include "ash/shell.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "extensions/common/extension.h"
 #include "ui/app_list/views/app_list_view.h"
 
diff --git a/chrome/browser/ui/ash/cast_config_delegate_chromeos.cc b/chrome/browser/ui/ash/cast_config_delegate_chromeos.cc
index 9b7e6ef8..2b7fd6e 100644
--- a/chrome/browser/ui/ash/cast_config_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/cast_config_delegate_chromeos.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/extensions/api/tab_capture/tab_capture_api.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/extensions/api/cast_devices_private.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index b4de47c9..109c3b0 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 
 #include "ash/content/gpu_support_impl.h"
+#include "ash/session/session_state_delegate.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -16,9 +17,11 @@
 #include "chrome/browser/ui/ash/ash_keyboard_controller_proxy.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
+#include "chrome/browser/ui/ash/session_util.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/grit/chromium_strings.h"
 #include "components/signin/core/common/profile_management_switches.h"
@@ -105,6 +108,10 @@
   return false;
 }
 
+bool ChromeShellDelegate::CanShowWindowForUser(aura::Window* window) const {
+  return ::CanShowWindowForUser(window, base::Bind(&::GetActiveBrowserContext));
+}
+
 bool ChromeShellDelegate::IsForceMaximizeOnFirstRun() const {
 #if defined(OS_CHROMEOS)
   const user_manager::User* const user =
@@ -124,10 +131,7 @@
 }
 
 content::BrowserContext* ChromeShellDelegate::GetActiveBrowserContext() {
-#if defined(OS_CHROMEOS)
-  DCHECK(user_manager::UserManager::Get()->GetLoggedInUsers().size());
-#endif
-  return ProfileManager::GetActiveUserProfile();
+  return ::GetActiveBrowserContext();
 }
 
 app_list::AppListViewDelegate* ChromeShellDelegate::GetAppListViewDelegate() {
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index 001e2f5..05f965cf 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -53,6 +53,7 @@
   bool IsIncognitoAllowed() const override;
   bool IsRunningInForcedAppMode() const override;
   bool IsMultiAccountEnabled() const override;
+  bool CanShowWindowForUser(aura::Window* window) const override;
   bool IsForceMaximizeOnFirstRun() const override;
   void PreInit() override;
   void PreShutdown() override;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index a343bdb..1853c5b 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -86,6 +86,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/keyboard/keyboard_util.h"
 #include "ui/resources/grit/ui_resources.h"
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
index b664989..fce9ef3 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
 #include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h"
+#include "chrome/browser/ui/ash/session_util.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
@@ -85,6 +86,15 @@
                : NULL;
   }
 
+  bool CanShowWindowForUser(aura::Window* window) const override {
+    // Note that the implementation of GetActiveBrowserContext() here differs
+    // from the implementation in ChromeShellDelegate/session_util.cc.
+    return ::CanShowWindowForUser(
+        window, base::Bind(&TestShellDelegateChromeOS::GetActiveBrowserContext,
+                           base::Unretained(
+                               const_cast<TestShellDelegateChromeOS*>(this))));
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(TestShellDelegateChromeOS);
 };
diff --git a/chrome/browser/ui/ash/session_util.cc b/chrome/browser/ui/ash/session_util.cc
new file mode 100644
index 0000000..57c0bd3d
--- /dev/null
+++ b/chrome/browser/ui/ash/session_util.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2015 The Chromium Authors. 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/ash/session_util.h"
+
+#include "ash/session/session_state_delegate.h"
+#include "ash/shell.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "ui/aura/window.h"
+
+#if defined(OS_CHROMEOS)
+#include "components/user_manager/user_manager.h"
+#endif
+
+content::BrowserContext* GetActiveBrowserContext() {
+#if defined(OS_CHROMEOS)
+  DCHECK(user_manager::UserManager::Get()->GetLoggedInUsers().size());
+#endif
+  return ProfileManager::GetActiveUserProfile();
+}
+
+bool CanShowWindowForUser(
+    aura::Window* window,
+    const GetActiveBrowserContextCallback& get_context_callback) {
+  ash::SessionStateDelegate* delegate =
+      ash::Shell::GetInstance()->session_state_delegate();
+  if (delegate->NumberOfLoggedInUsers() > 1) {
+    content::BrowserContext* active_browser_context =
+        get_context_callback.Run();
+    content::BrowserContext* owner_browser_context =
+        delegate->GetBrowserContextForWindow(window);
+    content::BrowserContext* shown_browser_context =
+        delegate->GetUserPresentingBrowserContextForWindow(window);
+
+    if (owner_browser_context && active_browser_context &&
+        owner_browser_context != active_browser_context &&
+        shown_browser_context != active_browser_context) {
+      return false;
+    }
+  }
+  return true;
+}
diff --git a/chrome/browser/ui/ash/session_util.h b/chrome/browser/ui/ash/session_util.h
new file mode 100644
index 0000000..dea51b6
--- /dev/null
+++ b/chrome/browser/ui/ash/session_util.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2015 The Chromium Authors. 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_ASH_SESSION_UTIL_H_
+#define CHROME_BROWSER_UI_ASH_SESSION_UTIL_H_
+
+#include "base/callback.h"
+
+namespace aura {
+class Window;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+content::BrowserContext* GetActiveBrowserContext();
+
+using GetActiveBrowserContextCallback =
+    base::Callback<content::BrowserContext*(void)>;
+
+// See documentation in ash/shell_delegate.h for the method of the same name.
+// |context| is the content::BrowserContext deemed active for the current
+// scenario. This is passed in because it can differ in tests vs. production.
+// See for example MultiUserWindowManagerTestChromeOS.
+bool CanShowWindowForUser(
+    aura::Window* window,
+    const GetActiveBrowserContextCallback& get_context_callback);
+
+#endif  // CHROME_BROWSER_UI_ASH_SESSION_UTIL_H_
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
index d9f7938..f0cfb39 100644
--- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -366,21 +366,21 @@
   return enterprise_domain_;
 }
 
-const base::string16 SystemTrayDelegateChromeOS::GetEnterpriseMessage() const {
+base::string16 SystemTrayDelegateChromeOS::GetEnterpriseMessage() const {
   if (GetEnterpriseDomain().empty())
     return base::string16();
   return l10n_util::GetStringFUTF16(IDS_DEVICE_OWNED_BY_NOTICE,
                                     base::UTF8ToUTF16(GetEnterpriseDomain()));
 }
 
-const std::string SystemTrayDelegateChromeOS::GetSupervisedUserManager() const {
+std::string SystemTrayDelegateChromeOS::GetSupervisedUserManager() const {
   if (!IsUserSupervised())
     return std::string();
   return SupervisedUserServiceFactory::GetForProfile(user_profile_)->
       GetCustodianEmailAddress();
 }
 
-const base::string16
+base::string16
 SystemTrayDelegateChromeOS::GetSupervisedUserManagerName() const {
   if (!IsUserSupervised())
     return base::string16();
@@ -388,7 +388,7 @@
       user_profile_)->GetCustodianName());
 }
 
-const base::string16 SystemTrayDelegateChromeOS::GetSupervisedUserMessage()
+base::string16 SystemTrayDelegateChromeOS::GetSupervisedUserMessage()
     const {
   if (!IsUserSupervised())
     return base::string16();
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
index 3daab60..2a04e44 100644
--- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
+++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
@@ -81,10 +81,10 @@
   ash::user::LoginStatus GetUserLoginStatus() const override;
   void ChangeProfilePicture() override;
   std::string GetEnterpriseDomain() const override;
-  const base::string16 GetEnterpriseMessage() const override;
-  const std::string GetSupervisedUserManager() const override;
-  const base::string16 GetSupervisedUserManagerName() const override;
-  const base::string16 GetSupervisedUserMessage() const override;
+  base::string16 GetEnterpriseMessage() const override;
+  std::string GetSupervisedUserManager() const override;
+  base::string16 GetSupervisedUserManagerName() const override;
+  base::string16 GetSupervisedUserMessage() const override;
   bool IsUserSupervised() const override;
   bool IsUserChild() const override;
   void GetSystemUpdateInfo(ash::UpdateInfo* info) const override;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 9553ad5..ed397097 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc b/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc
index 0492435..e9e4ce2 100644
--- a/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc
+++ b/chrome/browser/ui/autofill/card_unmask_prompt_view_browsertest.cc
@@ -16,6 +16,7 @@
 #include "components/autofill/core/browser/card_unmask_delegate.h"
 #include "components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.h"
 #include "components/user_prefs/user_prefs.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_utils.h"
 
diff --git a/chrome/browser/ui/blocked_content/blocked_window_params.cc b/chrome/browser/ui/blocked_content/blocked_window_params.cc
index 03e457f..351a3698 100644
--- a/chrome/browser/ui/blocked_content/blocked_window_params.cc
+++ b/chrome/browser/ui/blocked_content/blocked_window_params.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/blocked_content/blocked_window_params.h"
 
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/blocked_content/blocked_window_params.h b/chrome/browser/ui/blocked_content/blocked_window_params.h
index afed194c..f759b628 100644
--- a/chrome/browser/ui/blocked_content/blocked_window_params.h
+++ b/chrome/browser/ui/blocked_content/blocked_window_params.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_BLOCKED_WINDOW_PARAMS_H_
 #define CHROME_BROWSER_UI_BLOCKED_CONTENT_BLOCKED_WINDOW_PARAMS_H_
 
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "content/public/common/referrer.h"
 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
 #include "ui/base/window_open_disposition.h"
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index 0aa4a74..ced26fc 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -24,6 +24,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/test_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
@@ -422,7 +423,7 @@
 
   TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
       browser()->profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(service);
   LocationBar* location_bar = browser()->window()->GetLocationBar();
   ui_test_utils::SendToOmniboxAndSubmit(location_bar, search_string);
   OmniboxEditModel* model = location_bar->GetOmniboxView()->model();
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
index ebd7bef..ac28874 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/blocked_content/blocked_window_params.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/render_messages.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
index cd4afd22..9ca97a5 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc
index ddc4dbb4..a1d7a17b 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc
similarity index 98%
rename from chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
rename to chrome/browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc
index b0a51f9..e297064 100644
--- a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc
@@ -2,17 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
-
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-
 using base::ASCIIToUTF16;
 using bookmarks::BookmarkModel;
 using bookmarks::BookmarkNode;
@@ -125,4 +123,3 @@
 }
 
 }  // namespace
-#endif
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.cc b/chrome/browser/ui/bookmarks/bookmark_utils.cc
index 2c5fbc17..dde64ac 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_utils.cc
@@ -7,21 +7,11 @@
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
-#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
-#include "chrome/browser/ui/app_list/app_list_util.h"
-#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/simple_message_box.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node_data.h"
 #include "components/search/search.h"
@@ -30,7 +20,6 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drop_target_event.h"
-#include "ui/base/l10n/l10n_util.h"
 
 #if defined(ENABLE_EXTENSIONS)
 #include "chrome/browser/extensions/api/commands/command_service.h"
@@ -55,8 +44,6 @@
 
 namespace chrome {
 
-int num_bookmark_urls_before_prompting = 15;
-
 namespace {
 
 // The ways in which extensions may customize the bookmark shortcut.
@@ -66,112 +53,6 @@
   BOOKMARK_SHORTCUT_DISPOSITION_OVERRIDE_REQUESTED
 };
 
-// Iterator that iterates through a set of BookmarkNodes returning the URLs
-// for nodes that are urls, or the URLs for the children of non-url urls.
-// This does not recurse through all descendants, only immediate children.
-// The following illustrates
-// typical usage:
-// OpenURLIterator iterator(nodes);
-// while (iterator.has_next()) {
-//   const GURL* url = iterator.NextURL();
-//   // do something with |urll|.
-// }
-class OpenURLIterator {
- public:
-  explicit OpenURLIterator(const std::vector<const BookmarkNode*>& nodes)
-      : child_index_(0),
-        next_(NULL),
-        parent_(nodes.begin()),
-        end_(nodes.end()) {
-    FindNext();
-  }
-
-  bool has_next() { return next_ != NULL;}
-
-  const GURL* NextURL() {
-    if (!has_next()) {
-      NOTREACHED();
-      return NULL;
-    }
-
-    const GURL* next = next_;
-    FindNext();
-    return next;
-  }
-
- private:
-  // Seach next node which has URL.
-  void FindNext() {
-    for (; parent_ < end_; ++parent_, child_index_ = 0) {
-      if ((*parent_)->is_url()) {
-        next_ = &(*parent_)->url();
-        ++parent_;
-        child_index_ = 0;
-        return;
-      } else {
-        for (; child_index_ < (*parent_)->child_count(); ++child_index_) {
-          const BookmarkNode* child = (*parent_)->GetChild(child_index_);
-          if (child->is_url()) {
-            next_ = &child->url();
-            ++child_index_;
-            return;
-          }
-        }
-      }
-    }
-    next_ = NULL;
-  }
-
-  int child_index_;
-  const GURL* next_;
-  std::vector<const BookmarkNode*>::const_iterator parent_;
-  const std::vector<const BookmarkNode*>::const_iterator end_;
-
-  DISALLOW_COPY_AND_ASSIGN(OpenURLIterator);
-};
-
-bool ShouldOpenAll(gfx::NativeWindow parent,
-                   const std::vector<const BookmarkNode*>& nodes) {
-  int child_count = 0;
-  OpenURLIterator iterator(nodes);
-  while (iterator.has_next()) {
-    iterator.NextURL();
-    child_count++;
-  }
-
-  if (child_count < num_bookmark_urls_before_prompting)
-    return true;
-
-  return ShowMessageBox(parent,
-      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
-      l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL,
-                                 base::IntToString16(child_count)),
-      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
-}
-
-// Returns the total number of descendants nodes.
-int ChildURLCountTotal(const BookmarkNode* node) {
-  int result = 0;
-  for (int i = 0; i < node->child_count(); ++i) {
-    const BookmarkNode* child = node->GetChild(i);
-    result++;
-    if (child->is_folder())
-      result += ChildURLCountTotal(child);
-  }
-  return result;
-}
-
-// Returns in |urls|, the url and title pairs for each open tab in browser.
-void GetURLsForOpenTabs(Browser* browser,
-                        std::vector<std::pair<GURL, base::string16> >* urls) {
-  for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
-    std::pair<GURL, base::string16> entry;
-    GetURLAndTitleToBookmark(browser->tab_strip_model()->GetWebContentsAt(i),
-                             &(entry.first), &(entry.second));
-    urls->push_back(entry);
-  }
-}
-
 // Indicates how the bookmark shortcut has been changed by extensions associated
 // with |profile|, if at all.
 BookmarkShortcutDisposition GetBookmarkShortcutDisposition(Profile* profile) {
@@ -217,100 +98,6 @@
 
 }  // namespace
 
-void OpenAll(gfx::NativeWindow parent,
-             content::PageNavigator* navigator,
-             const std::vector<const BookmarkNode*>& nodes,
-             WindowOpenDisposition initial_disposition,
-             content::BrowserContext* browser_context) {
-  if (!ShouldOpenAll(parent, nodes))
-    return;
-
-  // Opens all |nodes| of type URL and any children of |nodes| that are of type
-  // URL. |navigator| is the PageNavigator used to open URLs. After the first
-  // url is opened |opened_first_url| is set to true and |navigator| is set to
-  // the PageNavigator of the last active tab. This is done to handle a window
-  // disposition of new window, in which case we want subsequent tabs to open in
-  // that window.
-  bool opened_first_url = false;
-  WindowOpenDisposition disposition = initial_disposition;
-  OpenURLIterator iterator(nodes);
-  while (iterator.has_next()) {
-    const GURL* url = iterator.NextURL();
-    // When |initial_disposition| is OFF_THE_RECORD, a node which can't be
-    // opened in incognito window, it is detected using |browser_context|, is
-    // not opened.
-    if (initial_disposition == OFF_THE_RECORD &&
-        !IsURLAllowedInIncognito(*url, browser_context))
-      continue;
-
-    content::WebContents* opened_tab = navigator->OpenURL(
-        content::OpenURLParams(*url, content::Referrer(), disposition,
-                               ui::PAGE_TRANSITION_AUTO_BOOKMARK, false));
-
-    if (!opened_first_url) {
-      opened_first_url = true;
-      disposition = NEW_BACKGROUND_TAB;
-      // We opened the first URL which may have opened a new window or clobbered
-      // the current page, reset the navigator just to be sure. |opened_tab| may
-      // be NULL in tests.
-      if (opened_tab)
-        navigator = opened_tab;
-    }
-  }
-}
-
-void OpenAll(gfx::NativeWindow parent,
-             content::PageNavigator* navigator,
-             const BookmarkNode* node,
-             WindowOpenDisposition initial_disposition,
-             content::BrowserContext* browser_context) {
-  std::vector<const BookmarkNode*> nodes;
-  nodes.push_back(node);
-  OpenAll(parent, navigator, nodes, initial_disposition, browser_context);
-}
-
-bool ConfirmDeleteBookmarkNode(const BookmarkNode* node,
-                               gfx::NativeWindow window) {
-  DCHECK(node && node->is_folder() && !node->empty());
-  return ShowMessageBox(window,
-      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
-      l10n_util::GetStringFUTF16Int(IDS_BOOKMARK_EDITOR_CONFIRM_DELETE,
-                                    ChildURLCountTotal(node)),
-      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
-}
-
-void ShowBookmarkAllTabsDialog(Browser* browser) {
-  Profile* profile = browser->profile();
-  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile);
-  DCHECK(model && model->loaded());
-
-  const BookmarkNode* parent = model->GetParentForNewNodes();
-  BookmarkEditor::EditDetails details =
-      BookmarkEditor::EditDetails::AddFolder(parent, parent->child_count());
-  GetURLsForOpenTabs(browser, &(details.urls));
-  DCHECK(!details.urls.empty());
-
-  BookmarkEditor::Show(browser->window()->GetNativeWindow(), profile, details,
-                       BookmarkEditor::SHOW_TREE);
-}
-
-bool HasBookmarkURLs(const std::vector<const BookmarkNode*>& selection) {
-  OpenURLIterator iterator(selection);
-  return iterator.has_next();
-}
-
-bool HasBookmarkURLsAllowedInIncognitoMode(
-    const std::vector<const BookmarkNode*>& selection,
-    content::BrowserContext* browser_context) {
-  OpenURLIterator iterator(selection);
-  while (iterator.has_next()) {
-    const GURL* url = iterator.NextURL();
-    if (IsURLAllowedInIncognito(*url, browser_context))
-      return true;
-  }
-  return false;
-}
-
 GURL GetURLToBookmark(content::WebContents* web_contents) {
   DCHECK(web_contents);
   return search::IsInstantNTP(web_contents) ? GURL(kChromeUINewTabURL)
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.h b/chrome/browser/ui/bookmarks/bookmark_utils.h
index 0df90b4..2a0e2f7 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils.h
+++ b/chrome/browser/ui/bookmarks/bookmark_utils.h
@@ -12,7 +12,6 @@
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/native_widget_types.h"
 
-class Browser;
 class GURL;
 class PrefService;
 class Profile;
@@ -24,7 +23,6 @@
 
 namespace content {
 class BrowserContext;
-class PageNavigator;
 class WebContents;
 }
 
@@ -38,48 +36,6 @@
 
 namespace chrome {
 
-// Number of bookmarks we'll open before prompting the user to see if they
-// really want to open all.
-//
-// NOTE: treat this as a const. It is not const so unit tests can change the
-// value.
-extern int num_bookmark_urls_before_prompting;
-
-// Opens all the bookmarks in |nodes| that are of type url and all the child
-// bookmarks that are of type url for folders in |nodes|. |initial_disposition|
-// dictates how the first URL is opened, all subsequent URLs are opened as
-// background tabs. |navigator| is used to open the URLs.
-void OpenAll(gfx::NativeWindow parent,
-             content::PageNavigator* navigator,
-             const std::vector<const bookmarks::BookmarkNode*>& nodes,
-             WindowOpenDisposition initial_disposition,
-             content::BrowserContext* browser_context);
-
-// Convenience for OpenAll() with a single BookmarkNode.
-void OpenAll(gfx::NativeWindow parent,
-             content::PageNavigator* navigator,
-             const bookmarks::BookmarkNode* node,
-             WindowOpenDisposition initial_disposition,
-             content::BrowserContext* browser_context);
-
-// Asks the user before deleting a non-empty bookmark folder.
-bool ConfirmDeleteBookmarkNode(const bookmarks::BookmarkNode* node,
-                               gfx::NativeWindow window);
-
-// Shows the bookmark all tabs dialog.
-void ShowBookmarkAllTabsDialog(Browser* browser);
-
-// Returns true if OpenAll() can open at least one bookmark of type url
-// in |selection|.
-bool HasBookmarkURLs(
-    const std::vector<const bookmarks::BookmarkNode*>& selection);
-
-// Returns true if OpenAll() can open at least one bookmark of type url
-// in |selection| with incognito mode.
-bool HasBookmarkURLsAllowedInIncognitoMode(
-    const std::vector<const bookmarks::BookmarkNode*>& selection,
-    content::BrowserContext* browser_context);
-
 // Returns the bookmarkable URL for |web_contents|.
 // This is normally the current URL, but when the page is the Instant Extended
 // New Tab Page, the precise current URL may reflect various flags or other
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
new file mode 100644
index 0000000..132aeb53
--- /dev/null
+++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
@@ -0,0 +1,271 @@
+// Copyright 2015 The Chromium Authors. 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/bookmarks/bookmark_utils_desktop.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/app_list/app_list_util.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/simple_message_box.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node_data.h"
+#include "components/search/search.h"
+#include "components/url_formatter/url_formatter.h"
+#include "components/user_prefs/user_prefs.h"
+#include "content/public/browser/web_contents.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/drop_target_event.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(ENABLE_EXTENSIONS)
+#include "chrome/browser/extensions/api/commands/command_service.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension_set.h"
+#endif
+
+#if defined(TOOLKIT_VIEWS)
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icons_public.h"
+#endif
+
+#if defined(OS_WIN)
+#include "chrome/grit/theme_resources.h"
+#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/resource/resource_bundle.h"
+#endif
+
+using bookmarks::BookmarkModel;
+using bookmarks::BookmarkNode;
+
+namespace chrome {
+
+int num_bookmark_urls_before_prompting = 15;
+
+namespace {
+
+// Iterator that iterates through a set of BookmarkNodes returning the URLs
+// for nodes that are urls, or the URLs for the children of non-url urls.
+// This does not recurse through all descendants, only immediate children.
+// The following illustrates
+// typical usage:
+// OpenURLIterator iterator(nodes);
+// while (iterator.has_next()) {
+//   const GURL* url = iterator.NextURL();
+//   // do something with |urll|.
+// }
+class OpenURLIterator {
+ public:
+  explicit OpenURLIterator(const std::vector<const BookmarkNode*>& nodes)
+      : child_index_(0),
+        next_(NULL),
+        parent_(nodes.begin()),
+        end_(nodes.end()) {
+    FindNext();
+  }
+
+  bool has_next() { return next_ != NULL;}
+
+  const GURL* NextURL() {
+    if (!has_next()) {
+      NOTREACHED();
+      return NULL;
+    }
+
+    const GURL* next = next_;
+    FindNext();
+    return next;
+  }
+
+ private:
+  // Seach next node which has URL.
+  void FindNext() {
+    for (; parent_ < end_; ++parent_, child_index_ = 0) {
+      if ((*parent_)->is_url()) {
+        next_ = &(*parent_)->url();
+        ++parent_;
+        child_index_ = 0;
+        return;
+      } else {
+        for (; child_index_ < (*parent_)->child_count(); ++child_index_) {
+          const BookmarkNode* child = (*parent_)->GetChild(child_index_);
+          if (child->is_url()) {
+            next_ = &child->url();
+            ++child_index_;
+            return;
+          }
+        }
+      }
+    }
+    next_ = NULL;
+  }
+
+  int child_index_;
+  const GURL* next_;
+  std::vector<const BookmarkNode*>::const_iterator parent_;
+  const std::vector<const BookmarkNode*>::const_iterator end_;
+
+  DISALLOW_COPY_AND_ASSIGN(OpenURLIterator);
+};
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+bool ShouldOpenAll(gfx::NativeWindow parent,
+                   const std::vector<const BookmarkNode*>& nodes) {
+  int child_count = 0;
+  OpenURLIterator iterator(nodes);
+  while (iterator.has_next()) {
+    iterator.NextURL();
+    child_count++;
+  }
+
+  if (child_count < num_bookmark_urls_before_prompting)
+    return true;
+
+  return ShowMessageBox(parent,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
+      l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL,
+                                 base::IntToString16(child_count)),
+      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
+}
+#endif
+
+// Returns the total number of descendants nodes.
+int ChildURLCountTotal(const BookmarkNode* node) {
+  int result = 0;
+  for (int i = 0; i < node->child_count(); ++i) {
+    const BookmarkNode* child = node->GetChild(i);
+    result++;
+    if (child->is_folder())
+      result += ChildURLCountTotal(child);
+  }
+  return result;
+}
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Returns in |urls|, the url and title pairs for each open tab in browser.
+void GetURLsForOpenTabs(Browser* browser,
+                        std::vector<std::pair<GURL, base::string16> >* urls) {
+  for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
+    std::pair<GURL, base::string16> entry;
+    GetURLAndTitleToBookmark(browser->tab_strip_model()->GetWebContentsAt(i),
+                             &(entry.first), &(entry.second));
+    urls->push_back(entry);
+  }
+}
+#endif
+
+}  // namespace
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void OpenAll(gfx::NativeWindow parent,
+             content::PageNavigator* navigator,
+             const std::vector<const BookmarkNode*>& nodes,
+             WindowOpenDisposition initial_disposition,
+             content::BrowserContext* browser_context) {
+  if (!ShouldOpenAll(parent, nodes))
+    return;
+
+  // Opens all |nodes| of type URL and any children of |nodes| that are of type
+  // URL. |navigator| is the PageNavigator used to open URLs. After the first
+  // url is opened |opened_first_url| is set to true and |navigator| is set to
+  // the PageNavigator of the last active tab. This is done to handle a window
+  // disposition of new window, in which case we want subsequent tabs to open in
+  // that window.
+  bool opened_first_url = false;
+  WindowOpenDisposition disposition = initial_disposition;
+  OpenURLIterator iterator(nodes);
+  while (iterator.has_next()) {
+    const GURL* url = iterator.NextURL();
+    // When |initial_disposition| is OFF_THE_RECORD, a node which can't be
+    // opened in incognito window, it is detected using |browser_context|, is
+    // not opened.
+    if (initial_disposition == OFF_THE_RECORD &&
+        !IsURLAllowedInIncognito(*url, browser_context))
+      continue;
+
+    content::WebContents* opened_tab = navigator->OpenURL(
+        content::OpenURLParams(*url, content::Referrer(), disposition,
+                               ui::PAGE_TRANSITION_AUTO_BOOKMARK, false));
+
+    if (!opened_first_url) {
+      opened_first_url = true;
+      disposition = NEW_BACKGROUND_TAB;
+      // We opened the first URL which may have opened a new window or clobbered
+      // the current page, reset the navigator just to be sure. |opened_tab| may
+      // be NULL in tests.
+      if (opened_tab)
+        navigator = opened_tab;
+    }
+  }
+}
+
+void OpenAll(gfx::NativeWindow parent,
+             content::PageNavigator* navigator,
+             const BookmarkNode* node,
+             WindowOpenDisposition initial_disposition,
+             content::BrowserContext* browser_context) {
+  std::vector<const BookmarkNode*> nodes;
+  nodes.push_back(node);
+  OpenAll(parent, navigator, nodes, initial_disposition, browser_context);
+}
+
+bool ConfirmDeleteBookmarkNode(const BookmarkNode* node,
+                               gfx::NativeWindow window) {
+  DCHECK(node && node->is_folder() && !node->empty());
+  return ShowMessageBox(window,
+      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
+      l10n_util::GetStringFUTF16Int(IDS_BOOKMARK_EDITOR_CONFIRM_DELETE,
+                                    ChildURLCountTotal(node)),
+      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
+}
+
+void ShowBookmarkAllTabsDialog(Browser* browser) {
+  Profile* profile = browser->profile();
+  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile);
+  DCHECK(model && model->loaded());
+
+  const BookmarkNode* parent = model->GetParentForNewNodes();
+  BookmarkEditor::EditDetails details =
+      BookmarkEditor::EditDetails::AddFolder(parent, parent->child_count());
+  GetURLsForOpenTabs(browser, &(details.urls));
+  DCHECK(!details.urls.empty());
+
+  BookmarkEditor::Show(browser->window()->GetNativeWindow(), profile, details,
+                       BookmarkEditor::SHOW_TREE);
+}
+
+bool HasBookmarkURLs(const std::vector<const BookmarkNode*>& selection) {
+  OpenURLIterator iterator(selection);
+  return iterator.has_next();
+}
+
+bool HasBookmarkURLsAllowedInIncognitoMode(
+    const std::vector<const BookmarkNode*>& selection,
+    content::BrowserContext* browser_context) {
+  OpenURLIterator iterator(selection);
+  while (iterator.has_next()) {
+    const GURL* url = iterator.NextURL();
+    if (IsURLAllowedInIncognito(*url, browser_context))
+      return true;
+  }
+  return false;
+}
+#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h
new file mode 100644
index 0000000..062817b
--- /dev/null
+++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h
@@ -0,0 +1,70 @@
+// Copyright 2015 The Chromium Authors. 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_BOOKMARKS_BOOKMARK_UTILS_DESKTOP_H_
+#define CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_UTILS_DESKTOP_H_
+
+#include <vector>
+
+#include "ui/base/window_open_disposition.h"
+#include "ui/gfx/native_widget_types.h"
+
+class Browser;
+
+namespace bookmarks {
+class BookmarkNode;
+}
+
+namespace content {
+class BrowserContext;
+class PageNavigator;
+}
+
+namespace chrome {
+
+// Number of bookmarks we'll open before prompting the user to see if they
+// really want to open all.
+//
+// NOTE: treat this as a const. It is not const so unit tests can change the
+// value.
+extern int num_bookmark_urls_before_prompting;
+
+// Opens all the bookmarks in |nodes| that are of type url and all the child
+// bookmarks that are of type url for folders in |nodes|. |initial_disposition|
+// dictates how the first URL is opened, all subsequent URLs are opened as
+// background tabs. |navigator| is used to open the URLs.
+void OpenAll(gfx::NativeWindow parent,
+             content::PageNavigator* navigator,
+             const std::vector<const bookmarks::BookmarkNode*>& nodes,
+             WindowOpenDisposition initial_disposition,
+             content::BrowserContext* browser_context);
+
+// Convenience for OpenAll() with a single BookmarkNode.
+void OpenAll(gfx::NativeWindow parent,
+             content::PageNavigator* navigator,
+             const bookmarks::BookmarkNode* node,
+             WindowOpenDisposition initial_disposition,
+             content::BrowserContext* browser_context);
+
+// Asks the user before deleting a non-empty bookmark folder.
+bool ConfirmDeleteBookmarkNode(const bookmarks::BookmarkNode* node,
+                               gfx::NativeWindow window);
+
+// Shows the bookmark all tabs dialog.
+void ShowBookmarkAllTabsDialog(Browser* browser);
+
+// Returns true if OpenAll() can open at least one bookmark of type url
+// in |selection|.
+bool HasBookmarkURLs(
+    const std::vector<const bookmarks::BookmarkNode*>& selection);
+
+// Returns true if OpenAll() can open at least one bookmark of type url
+// in |selection| with incognito mode.
+bool HasBookmarkURLsAllowedInIncognitoMode(
+    const std::vector<const bookmarks::BookmarkNode*>& selection,
+    content::BrowserContext* browser_context);
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_UTILS_DESKTOP_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 3fc98551..41d0a34 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -98,8 +98,9 @@
 #include "chrome/browser/ui/browser_instant_controller.h"
 #include "chrome/browser/ui/browser_iterator.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tab_strip_model_delegate.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_toolbar_model_delegate.h"
@@ -378,7 +379,7 @@
       content_setting_bubble_model_delegate_(
           new BrowserContentSettingBubbleModelDelegate(this)),
       toolbar_model_delegate_(new BrowserToolbarModelDelegate(this)),
-      tab_restore_service_delegate_(new BrowserTabRestoreServiceDelegate(this)),
+      live_tab_context_(new BrowserLiveTabContext(this)),
       synced_window_delegate_(new BrowserSyncedWindowDelegate(this)),
       bookmark_bar_state_(BookmarkBar::HIDDEN),
       command_controller_(new chrome::BrowserCommandController(this)),
@@ -510,7 +511,7 @@
   sessions::TabRestoreService* tab_restore_service =
       TabRestoreServiceFactory::GetForProfile(profile());
   if (tab_restore_service)
-    tab_restore_service->BrowserClosed(tab_restore_service_delegate());
+    tab_restore_service->BrowserClosed(live_tab_context());
 
 #if !defined(OS_MACOSX)
   if (!chrome::GetTotalBrowserCountForProfile(profile_)) {
@@ -734,11 +735,11 @@
 
 #if defined(USE_AURA)
   if (tab_restore_service && is_app() && !is_devtools())
-    tab_restore_service->BrowserClosing(tab_restore_service_delegate());
+    tab_restore_service->BrowserClosing(live_tab_context());
 #endif
 
   if (tab_restore_service && is_type_tabbed() && tab_strip_model_->count())
-    tab_restore_service->BrowserClosing(tab_restore_service_delegate());
+    tab_restore_service->BrowserClosing(live_tab_context());
 
   // TODO(sky): convert session/tab restore to use notification.
   content::NotificationService::current()->Notify(
@@ -1054,13 +1055,8 @@
   exclusive_access_manager_->OnTabDetachedFromView(old_contents);
 
   // Discarded tabs always get reloaded.
-  if (TabDiscardState::IsDiscarded(new_contents)) {
-    LOG(WARNING) << "Reloading discarded tab at " << index;
-    static int reload_count = 0;
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Tabs.Discard.ReloadCount", ++reload_count, 1, 1000, 50);
+  if (TabDiscardState::IsDiscarded(new_contents))
     chrome::Reload(this, CURRENT_TAB);
-  }
 
   // If we have any update pending, do it now.
   if (chrome_updater_factory_.HasWeakPtrs() && old_contents)
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index cf14541..e296569 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -56,7 +56,7 @@
 class BrowserInstantController;
 class BrowserSyncedWindowDelegate;
 class BrowserToolbarModelDelegate;
-class BrowserTabRestoreServiceDelegate;
+class BrowserLiveTabContext;
 class BrowserWindow;
 class FindBarController;
 class PrefService;
@@ -271,9 +271,7 @@
       content_setting_bubble_model_delegate() {
     return content_setting_bubble_model_delegate_.get();
   }
-  BrowserTabRestoreServiceDelegate* tab_restore_service_delegate() {
-    return tab_restore_service_delegate_.get();
-  }
+  BrowserLiveTabContext* live_tab_context() { return live_tab_context_.get(); }
   BrowserSyncedWindowDelegate* synced_window_delegate() {
     return synced_window_delegate_.get();
   }
@@ -956,8 +954,8 @@
   // |search_model_| state with the tab's state.
   scoped_ptr<SearchDelegate> search_delegate_;
 
-  // Helper which implements the TabRestoreServiceDelegate interface.
-  scoped_ptr<BrowserTabRestoreServiceDelegate> tab_restore_service_delegate_;
+  // Helper which implements the LiveTabContext interface.
+  scoped_ptr<BrowserLiveTabContext> live_tab_context_;
 
   // Helper which implements the SyncedWindowDelegate interface.
   scoped_ptr<BrowserSyncedWindowDelegate> synced_window_delegate_;
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index aac338a..89435cc3 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -41,7 +41,6 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_iterator.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_ui_prefs.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 1de24d7..395cdc9 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -778,6 +778,9 @@
       ash::accelerators::ToggleTouchHudProjection();
       break;
 #endif
+    case IDC_ROUTE_MEDIA:
+      RouteMedia(browser_);
+      break;
 
     default:
       LOG(WARNING) << "Received Unimplemented Command: " << id;
@@ -821,6 +824,7 @@
   PrintingStateChanged();
   FullscreenStateChanged();
   UpdateCommandsForFind();
+  UpdateCommandsForMediaRouter();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1137,6 +1141,7 @@
   UpdateCommandsForContentRestrictionState();
   UpdateCommandsForBookmarkEditing();
   UpdateCommandsForFind();
+  UpdateCommandsForMediaRouter();
   // Update the zoom commands when an active tab is selected.
   UpdateCommandsForZoomState();
 }
@@ -1343,6 +1348,11 @@
   command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, enabled);
 }
 
+void BrowserCommandController::UpdateCommandsForMediaRouter() {
+  command_updater_.UpdateCommandEnabled(IDC_ROUTE_MEDIA,
+                                        CanRouteMedia(browser_));
+}
+
 void BrowserCommandController::AddInterstitialObservers(WebContents* contents) {
   interstitial_observers_.push_back(new InterstitialObserver(this, contents));
 }
diff --git a/chrome/browser/ui/browser_command_controller.h b/chrome/browser/ui/browser_command_controller.h
index 702534fe..2a8730e9 100644
--- a/chrome/browser/ui/browser_command_controller.h
+++ b/chrome/browser/ui/browser_command_controller.h
@@ -155,10 +155,13 @@
   // |force| is true if the button should change its icon immediately.
   void UpdateReloadStopState(bool is_loading, bool force);
 
+  void UpdateTabRestoreCommandState();
+
   // Updates commands for find.
   void UpdateCommandsForFind();
 
-  void UpdateTabRestoreCommandState();
+  // Updates commands for Media Router.
+  void UpdateCommandsForMediaRouter();
 
   // Add/remove observers for interstitial attachment/detachment from
   // |contents|.
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index cb8a4dc..b67f11a 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/dom_distiller/tab_utils.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/media/router/media_router_dialog_controller.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
@@ -26,11 +27,13 @@
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "chrome/browser/ui/accelerator_utils.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_instant_controller.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -54,8 +57,8 @@
 #include "components/bookmarks/browser/bookmark_utils.h"
 #include "components/favicon/content/content_favicon_driver.h"
 #include "components/google/core/browser/google_util.h"
+#include "components/sessions/core/live_tab_context.h"
 #include "components/sessions/core/tab_restore_service.h"
-#include "components/sessions/core/tab_restore_service_delegate.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/translate/core/browser/language_state.h"
 #include "components/ui/zoom/page_zoom.h"
@@ -216,11 +219,10 @@
   if (!new_tab->FocusLocationBarByDefault())
     new_tab->Focus();
 
-  if (DevToolsWindow* devtools =
-      DevToolsWindow::GetInstanceForInspectedWebContents(new_tab)) {
-    devtools->ReloadInspectedWebContents(ignore_cache);
+  DevToolsWindow* devtools =
+      DevToolsWindow::GetInstanceForInspectedWebContents(new_tab);
+  if (devtools && devtools->ReloadInspectedWebContents(ignore_cache))
     return;
-  }
 
   if (ignore_cache)
     new_tab->GetController().ReloadIgnoringCache(true);
@@ -911,6 +913,27 @@
 }
 #endif  // ENABLE_BASIC_PRINTING
 
+bool CanRouteMedia(Browser* browser) {
+  if (!switches::MediaRouterEnabled() || browser->profile()->IsOffTheRecord())
+    return false;
+
+  // Do not allow user to open Media Router dialog when there is already an
+  // active modal dialog. This avoids overlapping dialogs.
+  return !IsShowingWebContentsModalDialog(browser);
+}
+
+void RouteMedia(Browser* browser) {
+  DCHECK(CanRouteMedia(browser));
+
+  media_router::MediaRouterDialogController* dialog_controller =
+      media_router::MediaRouterDialogController::GetOrCreateForWebContents(
+          browser->tab_strip_model()->GetActiveWebContents());
+  if (!dialog_controller)
+    return;
+
+  dialog_controller->ShowMediaRouterDialog();
+}
+
 void EmailPageLocation(Browser* browser) {
   content::RecordAction(UserMetricsAction("EmailPageLocation"));
   WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index d2d37ee..013db314 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -117,6 +117,8 @@
 void BasicPrint(Browser* browser);
 bool CanBasicPrint(Browser* browser);
 #endif  // ENABLE_BASIC_PRINTING
+bool CanRouteMedia(Browser* browser);
+void RouteMedia(Browser* browser);
 void EmailPageLocation(Browser* browser);
 bool CanEmailPageLocation(const Browser* browser);
 void CutCopyPaste(Browser* browser, int command_id);
diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc
index e415dae..7511437 100644
--- a/chrome/browser/ui/browser_focus_uitest.cc
+++ b/chrome/browser/ui/browser_focus_uitest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -67,10 +68,10 @@
 
 class BrowserFocusTest : public InProcessBrowserTest {
  public:
-   // InProcessBrowserTest overrides:
+  // InProcessBrowserTest overrides:
   void SetUpOnMainThread() override {
      ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
-   }
+  }
 
   bool IsViewFocused(ViewID vid) {
     return ui_test_utils::IsViewFocused(browser(), vid);
@@ -439,7 +440,8 @@
 
 // Test forward and reverse focus traversal while an interstitial is showing.
 // Disabled, see http://crbug.com/60973
-IN_PROC_BROWSER_TEST_F(BrowserFocusTest, DISABLED_FocusTraversalOnInterstitial) {
+IN_PROC_BROWSER_TEST_F(BrowserFocusTest,
+                       DISABLED_FocusTraversalOnInterstitial) {
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   const GURL url = embedded_test_server()->GetURL(kSimplePage);
   ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/ui/browser_tab_restore_service_delegate.cc b/chrome/browser/ui/browser_live_tab_context.cc
similarity index 71%
rename from chrome/browser/ui/browser_tab_restore_service_delegate.cc
rename to chrome/browser/ui/browser_live_tab_context.cc
index 38ce3ed6..54f4e78 100644
--- a/chrome/browser/ui/browser_tab_restore_service_delegate.cc
+++ b/chrome/browser/ui/browser_live_tab_context.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/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -19,42 +19,41 @@
 using content::SessionStorageNamespace;
 using content::WebContents;
 
-void BrowserTabRestoreServiceDelegate::ShowBrowserWindow() {
+void BrowserLiveTabContext::ShowBrowserWindow() {
   browser_->window()->Show();
 }
 
-const SessionID& BrowserTabRestoreServiceDelegate::GetSessionID() const {
+const SessionID& BrowserLiveTabContext::GetSessionID() const {
   return browser_->session_id();
 }
 
-int BrowserTabRestoreServiceDelegate::GetTabCount() const {
+int BrowserLiveTabContext::GetTabCount() const {
   return browser_->tab_strip_model()->count();
 }
 
-int BrowserTabRestoreServiceDelegate::GetSelectedIndex() const {
+int BrowserLiveTabContext::GetSelectedIndex() const {
   return browser_->tab_strip_model()->active_index();
 }
 
-std::string BrowserTabRestoreServiceDelegate::GetAppName() const {
+std::string BrowserLiveTabContext::GetAppName() const {
   return browser_->app_name();
 }
 
-sessions::LiveTab* BrowserTabRestoreServiceDelegate::GetLiveTabAt(
-    int index) const {
+sessions::LiveTab* BrowserLiveTabContext::GetLiveTabAt(int index) const {
   return sessions::ContentLiveTab::GetForWebContents(
       browser_->tab_strip_model()->GetWebContentsAt(index));
 }
 
-sessions::LiveTab* BrowserTabRestoreServiceDelegate::GetActiveLiveTab() const {
+sessions::LiveTab* BrowserLiveTabContext::GetActiveLiveTab() const {
   return sessions::ContentLiveTab::GetForWebContents(
       browser_->tab_strip_model()->GetActiveWebContents());
 }
 
-bool BrowserTabRestoreServiceDelegate::IsTabPinned(int index) const {
+bool BrowserLiveTabContext::IsTabPinned(int index) const {
   return browser_->tab_strip_model()->IsTabPinned(index);
 }
 
-sessions::LiveTab* BrowserTabRestoreServiceDelegate::AddRestoredTab(
+sessions::LiveTab* BrowserLiveTabContext::AddRestoredTab(
     const std::vector<sessions::SerializedNavigationEntry>& navigations,
     int tab_index,
     int selected_navigation,
@@ -78,7 +77,7 @@
   return sessions::ContentLiveTab::GetForWebContents(web_contents);
 }
 
-sessions::LiveTab* BrowserTabRestoreServiceDelegate::ReplaceRestoredTab(
+sessions::LiveTab* BrowserLiveTabContext::ReplaceRestoredTab(
     const std::vector<sessions::SerializedNavigationEntry>& navigations,
     int selected_navigation,
     bool from_last_session,
@@ -99,12 +98,12 @@
   return sessions::ContentLiveTab::GetForWebContents(web_contents);
 }
 
-void BrowserTabRestoreServiceDelegate::CloseTab() {
+void BrowserLiveTabContext::CloseTab() {
   chrome::CloseTab(browser_);
 }
 
 // static
-sessions::TabRestoreServiceDelegate* BrowserTabRestoreServiceDelegate::Create(
+sessions::LiveTabContext* BrowserLiveTabContext::Create(
     Profile* profile,
     chrome::HostDesktopType host_desktop_type,
     const std::string& app_name) {
@@ -113,31 +112,29 @@
     browser = new Browser(Browser::CreateParams(profile, host_desktop_type));
   } else {
     // Only trusted app popup windows should ever be restored.
-    browser = new Browser(
-        Browser::CreateParams::CreateForApp(
-            app_name, true /* trusted_source */, gfx::Rect(), profile,
-            host_desktop_type));
+    browser = new Browser(Browser::CreateParams::CreateForApp(
+        app_name, true /* trusted_source */, gfx::Rect(), profile,
+        host_desktop_type));
   }
   if (browser)
-    return browser->tab_restore_service_delegate();
+    return browser->live_tab_context();
   else
     return NULL;
 }
 
 // static
-sessions::TabRestoreServiceDelegate*
-BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+sessions::LiveTabContext* BrowserLiveTabContext::FindContextForWebContents(
     const WebContents* contents) {
   Browser* browser = chrome::FindBrowserWithWebContents(contents);
-  return browser ? browser->tab_restore_service_delegate() : nullptr;
+  return browser ? browser->live_tab_context() : nullptr;
 }
 
 // static
-sessions::TabRestoreServiceDelegate*
-BrowserTabRestoreServiceDelegate::FindDelegateWithID(
+sessions::LiveTabContext* BrowserLiveTabContext::FindContextWithID(
     SessionID::id_type desired_id,
     chrome::HostDesktopType host_desktop_type) {
   Browser* browser = chrome::FindBrowserWithID(desired_id);
-  return (browser && browser->host_desktop_type() == host_desktop_type) ?
-             browser->tab_restore_service_delegate() : NULL;
+  return (browser && browser->host_desktop_type() == host_desktop_type)
+             ? browser->live_tab_context()
+             : NULL;
 }
diff --git a/chrome/browser/ui/browser_tab_restore_service_delegate.h b/chrome/browser/ui/browser_live_tab_context.h
similarity index 67%
rename from chrome/browser/ui/browser_tab_restore_service_delegate.h
rename to chrome/browser/ui/browser_live_tab_context.h
index e0dd2d5..6b347760 100644
--- a/chrome/browser/ui/browser_tab_restore_service_delegate.h
+++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_BROWSER_TAB_RESTORE_SERVICE_DELEGATE_H_
-#define CHROME_BROWSER_UI_BROWSER_TAB_RESTORE_SERVICE_DELEGATE_H_
+#ifndef CHROME_BROWSER_UI_BROWSER_LIVE_TAB_CONTEXT_H_
+#define CHROME_BROWSER_UI_BROWSER_LIVE_TAB_CONTEXT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/compiler_specific.h"
 #include "chrome/browser/ui/host_desktop.h"
-#include "components/sessions/core/tab_restore_service_delegate.h"
+#include "components/sessions/core/live_tab_context.h"
 
 class Browser;
 class Profile;
@@ -19,16 +19,14 @@
 class WebContents;
 }
 
-// Implementation of TabRestoreServiceDelegate which uses an instance of
+// Implementation of LiveTabContext which uses an instance of
 // Browser in order to fulfil its duties.
-class BrowserTabRestoreServiceDelegate
-    : public sessions::TabRestoreServiceDelegate {
+class BrowserLiveTabContext : public sessions::LiveTabContext {
  public:
-  explicit BrowserTabRestoreServiceDelegate(Browser* browser)
-      : browser_(browser) {}
-  ~BrowserTabRestoreServiceDelegate() override {}
+  explicit BrowserLiveTabContext(Browser* browser) : browser_(browser) {}
+  ~BrowserLiveTabContext() override {}
 
-  // Overridden from TabRestoreServiceDelegate:
+  // Overridden from LiveTabContext:
   void ShowBrowserWindow() override;
   const SessionID& GetSessionID() const override;
   int GetTabCount() const override;
@@ -57,26 +55,26 @@
   void CloseTab() override;
 
   // see Browser::Create
-  static sessions::TabRestoreServiceDelegate* Create(
+  static sessions::LiveTabContext* Create(
       Profile* profile,
       chrome::HostDesktopType host_desktop_type,
       const std::string& app_name);
 
   // see browser::FindBrowserForWebContents
-  static sessions::TabRestoreServiceDelegate* FindDelegateForWebContents(
+  static sessions::LiveTabContext* FindContextForWebContents(
       const content::WebContents* contents);
 
   // see chrome::FindBrowserWithID
-  // Returns the TabRestoreServiceDelegate of the Browser with |desired_id| if
+  // Returns the LiveTabContext of the Browser with |desired_id| if
   // such a Browser exists and is on the desktop defined by |host_desktop_type|.
-  static sessions::TabRestoreServiceDelegate* FindDelegateWithID(
+  static sessions::LiveTabContext* FindContextWithID(
       SessionID::id_type desired_id,
       chrome::HostDesktopType host_desktop_type);
 
  private:
   Browser* browser_;
 
-  DISALLOW_COPY_AND_ASSIGN(BrowserTabRestoreServiceDelegate);
+  DISALLOW_COPY_AND_ASSIGN(BrowserLiveTabContext);
 };
 
-#endif  // CHROME_BROWSER_UI_BROWSER_TAB_RESTORE_SERVICE_DELEGATE_H_
+#endif  // CHROME_BROWSER_UI_BROWSER_LIVE_TAB_CONTEXT_H_
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index b9b4683b..d5573b1 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -21,6 +21,7 @@
 #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/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
@@ -399,109 +400,11 @@
       prerender_manager->MaybeUsePrerenderedPage(url, params);
 }
 
-chrome::HostDesktopType GetHostDesktop(Browser* browser) {
-  if (browser)
-    return browser->host_desktop_type();
-  return chrome::GetActiveDesktop();
-}
-
 }  // namespace
 
+
 namespace chrome {
 
-NavigateParams::NavigateParams(Browser* a_browser,
-                               const GURL& a_url,
-                               ui::PageTransition a_transition)
-    : url(a_url),
-      frame_tree_node_id(-1),
-      uses_post(false),
-      target_contents(NULL),
-      source_contents(NULL),
-      disposition(CURRENT_TAB),
-      trusted_source(false),
-      transition(a_transition),
-      is_renderer_initiated(false),
-      tabstrip_index(-1),
-      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
-      window_action(NO_ACTION),
-      user_gesture(true),
-      path_behavior(RESPECT),
-      ref_behavior(IGNORE_REF),
-      browser(a_browser),
-      initiating_profile(NULL),
-      host_desktop_type(GetHostDesktop(a_browser)),
-      should_replace_current_entry(false),
-      created_with_opener(false) {
-}
-
-NavigateParams::NavigateParams(Browser* a_browser,
-                               WebContents* a_target_contents)
-    : frame_tree_node_id(-1),
-      uses_post(false),
-      target_contents(a_target_contents),
-      source_contents(NULL),
-      disposition(CURRENT_TAB),
-      trusted_source(false),
-      transition(ui::PAGE_TRANSITION_LINK),
-      is_renderer_initiated(false),
-      tabstrip_index(-1),
-      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
-      window_action(NO_ACTION),
-      user_gesture(true),
-      path_behavior(RESPECT),
-      ref_behavior(IGNORE_REF),
-      browser(a_browser),
-      initiating_profile(NULL),
-      host_desktop_type(GetHostDesktop(a_browser)),
-      should_replace_current_entry(false),
-      created_with_opener(false) {
-}
-
-NavigateParams::NavigateParams(Profile* a_profile,
-                               const GURL& a_url,
-                               ui::PageTransition a_transition)
-    : url(a_url),
-      frame_tree_node_id(-1),
-      uses_post(false),
-      target_contents(NULL),
-      source_contents(NULL),
-      disposition(NEW_FOREGROUND_TAB),
-      trusted_source(false),
-      transition(a_transition),
-      is_renderer_initiated(false),
-      tabstrip_index(-1),
-      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
-      window_action(SHOW_WINDOW),
-      user_gesture(true),
-      path_behavior(RESPECT),
-      ref_behavior(IGNORE_REF),
-      browser(NULL),
-      initiating_profile(a_profile),
-      host_desktop_type(chrome::GetActiveDesktop()),
-      should_replace_current_entry(false),
-      created_with_opener(false) {
-}
-
-NavigateParams::~NavigateParams() {}
-
-void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
-                                         const content::OpenURLParams& params) {
-  nav_params->referrer = params.referrer;
-  nav_params->source_site_instance = params.source_site_instance;
-  nav_params->frame_tree_node_id = params.frame_tree_node_id;
-  nav_params->redirect_chain = params.redirect_chain;
-  nav_params->extra_headers = params.extra_headers;
-  nav_params->disposition = params.disposition;
-  nav_params->trusted_source = false;
-  nav_params->is_renderer_initiated = params.is_renderer_initiated;
-  nav_params->transferred_global_request_id =
-      params.transferred_global_request_id;
-  nav_params->should_replace_current_entry =
-      params.should_replace_current_entry;
-  nav_params->uses_post = params.uses_post;
-  nav_params->browser_initiated_post_data = params.browser_initiated_post_data;
-}
-
 void Navigate(NavigateParams* params) {
   Browser* source_browser = params->browser;
   if (source_browser)
diff --git a/chrome/browser/ui/browser_navigator.h b/chrome/browser/ui/browser_navigator.h
index 07754c72..ccdbfbd 100644
--- a/chrome/browser/ui/browser_navigator.h
+++ b/chrome/browser/ui/browser_navigator.h
@@ -5,249 +5,15 @@
 #ifndef CHROME_BROWSER_UI_BROWSER_NAVIGATOR_H_
 #define CHROME_BROWSER_UI_BROWSER_NAVIGATOR_H_
 
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_memory.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/global_request_id.h"
-#include "content/public/browser/page_navigator.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/common/referrer.h"
-#include "ui/base/page_transition_types.h"
-#include "ui/base/window_open_disposition.h"
-#include "ui/gfx/geometry/rect.h"
-#include "url/gurl.h"
-
-class Browser;
-class Profile;
+class GURL;
 
 namespace content {
-class WebContents;
+class BrowserContext;
 }
 
 namespace chrome {
 
-// Parameters that tell Navigate() what to do.
-//
-// Some basic examples:
-//
-// Simple Navigate to URL in current tab:
-// chrome::NavigateParams params(browser, GURL("http://www.google.com/"),
-//                               ui::PAGE_TRANSITION_LINK);
-// chrome::Navigate(&params);
-//
-// Open bookmark in new background tab:
-// chrome::NavigateParams params(browser, url,
-//                               ui::PAGE_TRANSITION_AUTO_BOOKMARK);
-// params.disposition = NEW_BACKGROUND_TAB;
-// chrome::Navigate(&params);
-//
-// Opens a popup WebContents:
-// chrome::NavigateParams params(browser, popup_contents);
-// params.source_contents = source_contents;
-// chrome::Navigate(&params);
-//
-// See browser_navigator_browsertest.cc for more examples.
-//
-struct NavigateParams {
-  NavigateParams(Browser* browser,
-                 const GURL& a_url,
-                 ui::PageTransition a_transition);
-  NavigateParams(Browser* browser,
-                 content::WebContents* a_target_contents);
-  NavigateParams(Profile* profile,
-                 const GURL& a_url,
-                 ui::PageTransition a_transition);
-  ~NavigateParams();
-
-  // The URL/referrer to be loaded. Ignored if |target_contents| is non-NULL.
-  GURL url;
-  content::Referrer referrer;
-
-  // The browser-global ID of the frame to navigate, or -1 for the main frame.
-  int frame_tree_node_id;
-
-  // Any redirect URLs that occurred for this navigation before |url|.
-  // Usually empty.
-  std::vector<GURL> redirect_chain;
-
-  // Indicates whether this navigation will be sent using POST.
-  // The POST method is limited support for basic POST data by leveraging
-  // NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST.
-  // It is not for things like file uploads.
-  bool uses_post;
-
-  // The post data when the navigation uses POST.
-  scoped_refptr<base::RefCountedMemory> browser_initiated_post_data;
-
-  // Extra headers to add to the request for this page.  Headers are
-  // represented as "<name>: <value>" and separated by \r\n.  The entire string
-  // is terminated by \r\n.  May be empty if no extra headers are needed.
-  std::string extra_headers;
-
-  // [in]  A WebContents to be navigated or inserted into the target
-  //       Browser's tabstrip. If NULL, |url| or the homepage will be used
-  //       instead. When non-NULL, Navigate() assumes it has already been
-  //       navigated to its intended destination and will not load any URL in it
-  //       (i.e. |url| is ignored).
-  //       Default is NULL.
-  // [out] The WebContents in which the navigation occurred or that was
-  //       inserted. Guaranteed non-NULL except for note below:
-  // Note: If this field is set to NULL by the caller and Navigate() creates
-  //       a new WebContents, this field will remain NULL and the
-  //       WebContents deleted if the WebContents it created is
-  //       not added to a TabStripModel before Navigate() returns.
-  content::WebContents* target_contents;
-
-  // [in]  The WebContents that initiated the Navigate() request if such
-  //       context is necessary. Default is NULL, i.e. no context.
-  // [out] If NULL, this value will be set to the selected WebContents in
-  //       the originating browser prior to the operation performed by
-  //       Navigate(). However, if the originating page is from a different
-  //       profile (e.g. an OFF_THE_RECORD page originating from a non-OTR
-  //       window), then |source_contents| is reset to NULL.
-  content::WebContents* source_contents;
-
-  // The disposition requested by the navigation source. Default is
-  // CURRENT_TAB. What follows is a set of coercions that happen to this value
-  // when other factors are at play:
-  //
-  // [in]:                Condition:                        [out]:
-  // NEW_BACKGROUND_TAB   target browser tabstrip is empty  NEW_FOREGROUND_TAB
-  // CURRENT_TAB          "     "     "                     NEW_FOREGROUND_TAB
-  // OFF_THE_RECORD       target browser profile is incog.  NEW_FOREGROUND_TAB
-  //
-  // If disposition is NEW_BACKGROUND_TAB, TabStripModel::ADD_ACTIVE is
-  // removed from |tabstrip_add_types| automatically.
-  // If disposition is one of NEW_WINDOW, NEW_POPUP, NEW_FOREGROUND_TAB or
-  // SINGLETON_TAB, then TabStripModel::ADD_ACTIVE is automatically added to
-  // |tabstrip_add_types|.
-  WindowOpenDisposition disposition;
-
-  // Sets browser->is_trusted_source. Default is false.
-  bool trusted_source;
-
-  // The transition type of the navigation. Default is
-  // ui::PAGE_TRANSITION_LINK when target_contents is specified in the
-  // constructor.
-  ui::PageTransition transition;
-
-  // Whether this navigation was initiated by the renderer process. Default is
-  // false.
-  bool is_renderer_initiated;
-
-  // The index the caller would like the tab to be positioned at in the
-  // TabStrip. The actual index will be determined by the TabHandler in
-  // accordance with |add_types|. Defaults to -1 (allows the TabHandler to
-  // decide).
-  int tabstrip_index;
-
-  // A bitmask of values defined in TabStripModel::AddTabTypes. Helps
-  // determine where to insert a new tab and whether or not it should be
-  // selected, among other properties. Default is ADD_ACTIVE.
-  int tabstrip_add_types;
-
-  // If non-empty, the new tab is an app tab.
-  std::string extension_app_id;
-
-  // If non-empty, specifies the desired initial position and size of the
-  // window if |disposition| == NEW_POPUP.
-  // TODO(beng): Figure out if this can be used to create Browser windows
-  //             for other callsites that use set_override_bounds, or
-  //             remove this comment.
-  gfx::Rect window_bounds;
-
-  // Determines if and how the target window should be made visible at the end
-  // of the call to Navigate().
-  enum WindowAction {
-    // Do not show or activate the browser window after navigating.
-    NO_ACTION,
-    // Show and activate the browser window after navigating.
-    SHOW_WINDOW,
-    // Show the browser window after navigating but do not activate.
-    SHOW_WINDOW_INACTIVE
-  };
-  // Default is NO_ACTION (don't show or activate the window).
-  // If disposition is NEW_WINDOW or NEW_POPUP, and |window_action| is set to
-  // NO_ACTION, |window_action| will be set to SHOW_WINDOW.
-  WindowAction window_action;
-
-  // If false then the navigation was not initiated by a user gesture.
-  // Default is true.
-  bool user_gesture;
-
-  // What to do with the path component of the URL for singleton navigations.
-  enum PathBehavior {
-    // Two URLs with differing paths are different.
-    RESPECT,
-    // Ignore path when finding existing tab, navigate to new URL.
-    IGNORE_AND_NAVIGATE,
-    // Ignore path when finding existing tab, don't navigate tab.
-    IGNORE_AND_STAY_PUT,
-  };
-  // Default is RESPECT.
-  PathBehavior path_behavior;
-
-  // What to do with the ref component of the URL for singleton navigations.
-  enum RefBehavior {
-    // Two URLs with differing refs are same.
-    IGNORE_REF,
-    // Two URLs with differing refs are different.
-    RESPECT_REF,
-  };
-  // Default is IGNORE.
-  RefBehavior ref_behavior;
-
-  // [in]  Specifies a Browser object where the navigation could occur or the
-  //       tab could be added. Navigate() is not obliged to use this Browser if
-  //       it is not compatible with the operation being performed. This can be
-  //       NULL, in which case |initiating_profile| must be provided.
-  // [out] Specifies the Browser object where the navigation occurred or the
-  //       tab was added. Guaranteed non-NULL unless the disposition did not
-  //       require a navigation, in which case this is set to NULL
-  //       (SUPPRESS_OPEN, SAVE_TO_DISK, IGNORE_ACTION).
-  // Note: If |show_window| is set to false and a new Browser is created by
-  //       Navigate(), the caller is responsible for showing it so that its
-  //       window can assume responsibility for the Browser's lifetime (Browser
-  //       objects are deleted when the user closes a visible browser window).
-  Browser* browser;
-
-  // The profile that is initiating the navigation. If there is a non-NULL
-  // browser passed in via |browser|, it's profile will be used instead.
-  Profile* initiating_profile;
-
-  // Refers to a navigation that was parked in the browser in order to be
-  // transferred to another RVH. Only used in case of a redirection of a request
-  // to a different site that created a new RVH.
-  content::GlobalRequestID transferred_global_request_id;
-
-  // Refers to which desktop this navigation should occur on. May be passed
-  // explicitly or inferred from an existing Browser instance.
-  chrome::HostDesktopType host_desktop_type;
-
-  // Indicates whether this navigation  should replace the current
-  // navigation entry.
-  bool should_replace_current_entry;
-
-  // Indicates whether |target_contents| is being created with a window.opener.
-  bool created_with_opener;
-
-  // SiteInstance of the frame that initiated the navigation or null if we
-  // don't know it. This should be assigned from the OpenURLParams of the
-  // WebContentsDelegate::OpenURLFromTab implementation and is used to determine
-  // the SiteInstance that will be used for the resulting frame in the case of
-  // an about:blank or a data url navigation.
-  scoped_refptr<content::SiteInstance> source_site_instance;
-
- private:
-  NavigateParams();
-};
-
-// Copies fields from |params| struct to |nav_params| struct.
-void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
-                                         const content::OpenURLParams& params);
+struct NavigateParams;
 
 // Navigates according to the configuration specified in |params|.
 void Navigate(NavigateParams* params);
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index 02d5494..ba50af6 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
diff --git a/chrome/browser/ui/browser_navigator_browsertest.h b/chrome/browser/ui/browser_navigator_browsertest.h
index 372f68fa..4964ac3 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.h
+++ b/chrome/browser/ui/browser_navigator_browsertest.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/notification_types.h"
 
@@ -17,10 +18,6 @@
 class CommandLine;
 }
 
-namespace chrome {
-struct NavigateParams;
-}
-
 namespace content {
 class WebContents;
 }
diff --git a/chrome/browser/ui/browser_navigator_params.cc b/chrome/browser/ui/browser_navigator_params.cc
new file mode 100644
index 0000000..74e086ce
--- /dev/null
+++ b/chrome/browser/ui/browser_navigator_params.cc
@@ -0,0 +1,152 @@
+// Copyright 2015 The Chromium Authors. 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/browser_navigator_params.h"
+
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/page_navigator.h"
+
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/host_desktop.h"
+#endif
+
+using content::GlobalRequestID;
+using content::NavigationController;
+using content::WebContents;
+
+namespace chrome {
+
+#if !defined(OS_ANDROID)
+namespace {
+
+HostDesktopType GetHostDesktop(Browser* browser) {
+  if (browser)
+    return browser->host_desktop_type();
+  return GetActiveDesktop();
+}
+
+}  // namespace
+#endif
+
+#if defined(OS_ANDROID)
+NavigateParams::NavigateParams(WebContents* a_target_contents)
+    : frame_tree_node_id(-1),
+      uses_post(false),
+      target_contents(a_target_contents),
+      source_contents(nullptr),
+      disposition(CURRENT_TAB),
+      trusted_source(false),
+      transition(ui::PAGE_TRANSITION_LINK),
+      is_renderer_initiated(false),
+      tabstrip_index(-1),
+      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
+      window_action(NO_ACTION),
+      user_gesture(true),
+      path_behavior(RESPECT),
+      ref_behavior(IGNORE_REF),
+      initiating_profile(nullptr),
+      host_desktop_type(GetActiveDesktop()),
+      should_replace_current_entry(false),
+      created_with_opener(false) {
+}
+#else
+NavigateParams::NavigateParams(Browser* a_browser,
+                               const GURL& a_url,
+                               ui::PageTransition a_transition)
+    : url(a_url),
+      frame_tree_node_id(-1),
+      uses_post(false),
+      target_contents(NULL),
+      source_contents(NULL),
+      disposition(CURRENT_TAB),
+      trusted_source(false),
+      transition(a_transition),
+      is_renderer_initiated(false),
+      tabstrip_index(-1),
+      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
+      window_action(NO_ACTION),
+      user_gesture(true),
+      path_behavior(RESPECT),
+      ref_behavior(IGNORE_REF),
+      browser(a_browser),
+      initiating_profile(NULL),
+      host_desktop_type(GetHostDesktop(a_browser)),
+      should_replace_current_entry(false),
+      created_with_opener(false) {
+}
+
+NavigateParams::NavigateParams(Browser* a_browser,
+                               WebContents* a_target_contents)
+    : frame_tree_node_id(-1),
+      uses_post(false),
+      target_contents(a_target_contents),
+      source_contents(NULL),
+      disposition(CURRENT_TAB),
+      trusted_source(false),
+      transition(ui::PAGE_TRANSITION_LINK),
+      is_renderer_initiated(false),
+      tabstrip_index(-1),
+      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
+      window_action(NO_ACTION),
+      user_gesture(true),
+      path_behavior(RESPECT),
+      ref_behavior(IGNORE_REF),
+      browser(a_browser),
+      initiating_profile(NULL),
+      host_desktop_type(GetHostDesktop(a_browser)),
+      should_replace_current_entry(false),
+      created_with_opener(false) {
+}
+#endif  // !defined(OS_ANDROID)
+
+NavigateParams::NavigateParams(Profile* a_profile,
+                               const GURL& a_url,
+                               ui::PageTransition a_transition)
+    : url(a_url),
+      frame_tree_node_id(-1),
+      uses_post(false),
+      target_contents(NULL),
+      source_contents(NULL),
+      disposition(NEW_FOREGROUND_TAB),
+      trusted_source(false),
+      transition(a_transition),
+      is_renderer_initiated(false),
+      tabstrip_index(-1),
+      tabstrip_add_types(TabStripModel::ADD_ACTIVE),
+      window_action(SHOW_WINDOW),
+      user_gesture(true),
+      path_behavior(RESPECT),
+      ref_behavior(IGNORE_REF),
+#if !defined(OS_ANDROID)
+      browser(NULL),
+#endif
+      initiating_profile(a_profile),
+      host_desktop_type(GetActiveDesktop()),
+      should_replace_current_entry(false),
+      created_with_opener(false) {
+}
+
+NavigateParams::~NavigateParams() {}
+
+void FillNavigateParamsFromOpenURLParams(NavigateParams* nav_params,
+                                         const content::OpenURLParams& params) {
+  nav_params->referrer = params.referrer;
+  nav_params->source_site_instance = params.source_site_instance;
+  nav_params->frame_tree_node_id = params.frame_tree_node_id;
+  nav_params->redirect_chain = params.redirect_chain;
+  nav_params->extra_headers = params.extra_headers;
+  nav_params->disposition = params.disposition;
+  nav_params->trusted_source = false;
+  nav_params->is_renderer_initiated = params.is_renderer_initiated;
+  nav_params->transferred_global_request_id =
+      params.transferred_global_request_id;
+  nav_params->should_replace_current_entry =
+      params.should_replace_current_entry;
+  nav_params->uses_post = params.uses_post;
+  nav_params->browser_initiated_post_data = params.browser_initiated_post_data;
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/browser_navigator_params.h b/chrome/browser/ui/browser_navigator_params.h
new file mode 100644
index 0000000..d011c0eb
--- /dev/null
+++ b/chrome/browser/ui/browser_navigator_params.h
@@ -0,0 +1,261 @@
+// Copyright 2015 The Chromium Authors. 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_BROWSER_NAVIGATOR_PARAMS_H_
+#define CHROME_BROWSER_UI_BROWSER_NAVIGATOR_PARAMS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
+#include "ui/base/window_open_disposition.h"
+#include "ui/gfx/geometry/rect.h"
+#include "url/gurl.h"
+
+class Browser;
+class Profile;
+
+namespace content {
+class WebContents;
+struct OpenURLParams;
+}
+
+namespace chrome {
+
+// Parameters that tell Navigate() what to do.
+//
+// Some basic examples:
+//
+// Simple Navigate to URL in current tab:
+// chrome::NavigateParams params(browser, GURL("http://www.google.com/"),
+//                               ui::PAGE_TRANSITION_LINK);
+// chrome::Navigate(&params);
+//
+// Open bookmark in new background tab:
+// chrome::NavigateParams params(browser, url,
+//                               ui::PAGE_TRANSITION_AUTO_BOOKMARK);
+// params.disposition = NEW_BACKGROUND_TAB;
+// chrome::Navigate(&params);
+//
+// Opens a popup WebContents:
+// chrome::NavigateParams params(browser, popup_contents);
+// params.source_contents = source_contents;
+// chrome::Navigate(&params);
+//
+// See browser_navigator_browsertest.cc for more examples.
+
+// TODO(thestig): Split or ifdef out more fields that are not used on Android.
+struct NavigateParams {
+#if defined(OS_ANDROID)
+  explicit NavigateParams(content::WebContents* a_target_contents);
+#else
+  NavigateParams(Browser* browser,
+                 const GURL& a_url,
+                 ui::PageTransition a_transition);
+  NavigateParams(Browser* browser,
+                 content::WebContents* a_target_contents);
+#endif
+  NavigateParams(Profile* profile,
+                 const GURL& a_url,
+                 ui::PageTransition a_transition);
+  ~NavigateParams();
+
+  // The URL/referrer to be loaded. Ignored if |target_contents| is non-NULL.
+  GURL url;
+  content::Referrer referrer;
+
+  // The browser-global ID of the frame to navigate, or -1 for the main frame.
+  int frame_tree_node_id;
+
+  // Any redirect URLs that occurred for this navigation before |url|.
+  // Usually empty.
+  std::vector<GURL> redirect_chain;
+
+  // Indicates whether this navigation will be sent using POST.
+  // The POST method is limited support for basic POST data by leveraging
+  // NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST.
+  // It is not for things like file uploads.
+  bool uses_post;
+
+  // The post data when the navigation uses POST.
+  scoped_refptr<base::RefCountedMemory> browser_initiated_post_data;
+
+  // Extra headers to add to the request for this page.  Headers are
+  // represented as "<name>: <value>" and separated by \r\n.  The entire string
+  // is terminated by \r\n.  May be empty if no extra headers are needed.
+  std::string extra_headers;
+
+  // [in]  A WebContents to be navigated or inserted into the target
+  //       Browser's tabstrip. If NULL, |url| or the homepage will be used
+  //       instead. When non-NULL, Navigate() assumes it has already been
+  //       navigated to its intended destination and will not load any URL in it
+  //       (i.e. |url| is ignored).
+  //       Default is NULL.
+  // [out] The WebContents in which the navigation occurred or that was
+  //       inserted. Guaranteed non-NULL except for note below:
+  // Note: If this field is set to NULL by the caller and Navigate() creates
+  //       a new WebContents, this field will remain NULL and the
+  //       WebContents deleted if the WebContents it created is
+  //       not added to a TabStripModel before Navigate() returns.
+  content::WebContents* target_contents;
+
+  // [in]  The WebContents that initiated the Navigate() request if such
+  //       context is necessary. Default is NULL, i.e. no context.
+  // [out] If NULL, this value will be set to the selected WebContents in
+  //       the originating browser prior to the operation performed by
+  //       Navigate(). However, if the originating page is from a different
+  //       profile (e.g. an OFF_THE_RECORD page originating from a non-OTR
+  //       window), then |source_contents| is reset to NULL.
+  content::WebContents* source_contents;
+
+  // The disposition requested by the navigation source. Default is
+  // CURRENT_TAB. What follows is a set of coercions that happen to this value
+  // when other factors are at play:
+  //
+  // [in]:                Condition:                        [out]:
+  // NEW_BACKGROUND_TAB   target browser tabstrip is empty  NEW_FOREGROUND_TAB
+  // CURRENT_TAB          "     "     "                     NEW_FOREGROUND_TAB
+  // OFF_THE_RECORD       target browser profile is incog.  NEW_FOREGROUND_TAB
+  //
+  // If disposition is NEW_BACKGROUND_TAB, TabStripModel::ADD_ACTIVE is
+  // removed from |tabstrip_add_types| automatically.
+  // If disposition is one of NEW_WINDOW, NEW_POPUP, NEW_FOREGROUND_TAB or
+  // SINGLETON_TAB, then TabStripModel::ADD_ACTIVE is automatically added to
+  // |tabstrip_add_types|.
+  WindowOpenDisposition disposition;
+
+  // Sets browser->is_trusted_source. Default is false.
+  bool trusted_source;
+
+  // The transition type of the navigation. Default is
+  // ui::PAGE_TRANSITION_LINK when target_contents is specified in the
+  // constructor.
+  ui::PageTransition transition;
+
+  // Whether this navigation was initiated by the renderer process. Default is
+  // false.
+  bool is_renderer_initiated;
+
+  // The index the caller would like the tab to be positioned at in the
+  // TabStrip. The actual index will be determined by the TabHandler in
+  // accordance with |add_types|. Defaults to -1 (allows the TabHandler to
+  // decide).
+  int tabstrip_index;
+
+  // A bitmask of values defined in TabStripModel::AddTabTypes. Helps
+  // determine where to insert a new tab and whether or not it should be
+  // selected, among other properties. Default is ADD_ACTIVE.
+  int tabstrip_add_types;
+
+  // If non-empty, the new tab is an app tab.
+  std::string extension_app_id;
+
+  // If non-empty, specifies the desired initial position and size of the
+  // window if |disposition| == NEW_POPUP.
+  // TODO(beng): Figure out if this can be used to create Browser windows
+  //             for other callsites that use set_override_bounds, or
+  //             remove this comment.
+  gfx::Rect window_bounds;
+
+  // Determines if and how the target window should be made visible at the end
+  // of the call to Navigate().
+  enum WindowAction {
+    // Do not show or activate the browser window after navigating.
+    NO_ACTION,
+    // Show and activate the browser window after navigating.
+    SHOW_WINDOW,
+    // Show the browser window after navigating but do not activate.
+    SHOW_WINDOW_INACTIVE
+  };
+  // Default is NO_ACTION (don't show or activate the window).
+  // If disposition is NEW_WINDOW or NEW_POPUP, and |window_action| is set to
+  // NO_ACTION, |window_action| will be set to SHOW_WINDOW.
+  WindowAction window_action;
+
+  // If false then the navigation was not initiated by a user gesture.
+  // Default is true.
+  bool user_gesture;
+
+  // What to do with the path component of the URL for singleton navigations.
+  enum PathBehavior {
+    // Two URLs with differing paths are different.
+    RESPECT,
+    // Ignore path when finding existing tab, navigate to new URL.
+    IGNORE_AND_NAVIGATE,
+    // Ignore path when finding existing tab, don't navigate tab.
+    IGNORE_AND_STAY_PUT,
+  };
+  // Default is RESPECT.
+  PathBehavior path_behavior;
+
+  // What to do with the ref component of the URL for singleton navigations.
+  enum RefBehavior {
+    // Two URLs with differing refs are same.
+    IGNORE_REF,
+    // Two URLs with differing refs are different.
+    RESPECT_REF,
+  };
+  // Default is IGNORE.
+  RefBehavior ref_behavior;
+
+#if !defined(OS_ANDROID)
+  // [in]  Specifies a Browser object where the navigation could occur or the
+  //       tab could be added. Navigate() is not obliged to use this Browser if
+  //       it is not compatible with the operation being performed. This can be
+  //       NULL, in which case |initiating_profile| must be provided.
+  // [out] Specifies the Browser object where the navigation occurred or the
+  //       tab was added. Guaranteed non-NULL unless the disposition did not
+  //       require a navigation, in which case this is set to NULL
+  //       (SUPPRESS_OPEN, SAVE_TO_DISK, IGNORE_ACTION).
+  // Note: If |show_window| is set to false and a new Browser is created by
+  //       Navigate(), the caller is responsible for showing it so that its
+  //       window can assume responsibility for the Browser's lifetime (Browser
+  //       objects are deleted when the user closes a visible browser window).
+  Browser* browser;
+#endif
+
+  // The profile that is initiating the navigation. If there is a non-NULL
+  // browser passed in via |browser|, it's profile will be used instead.
+  Profile* initiating_profile;
+
+  // Refers to a navigation that was parked in the browser in order to be
+  // transferred to another RVH. Only used in case of a redirection of a request
+  // to a different site that created a new RVH.
+  content::GlobalRequestID transferred_global_request_id;
+
+  // Refers to which desktop this navigation should occur on. May be passed
+  // explicitly or inferred from an existing Browser instance.
+  chrome::HostDesktopType host_desktop_type;
+
+  // Indicates whether this navigation  should replace the current
+  // navigation entry.
+  bool should_replace_current_entry;
+
+  // Indicates whether |target_contents| is being created with a window.opener.
+  bool created_with_opener;
+
+  // SiteInstance of the frame that initiated the navigation or null if we
+  // don't know it. This should be assigned from the OpenURLParams of the
+  // WebContentsDelegate::OpenURLFromTab implementation and is used to determine
+  // the SiteInstance that will be used for the resulting frame in the case of
+  // an about:blank or a data url navigation.
+  scoped_refptr<content::SiteInstance> source_site_instance;
+
+ private:
+  NavigateParams();
+};
+
+// Copies fields from |params| struct to |nav_params| struct.
+void FillNavigateParamsFromOpenURLParams(chrome::NavigateParams* nav_params,
+                                         const content::OpenURLParams& params);
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_UI_BROWSER_NAVIGATOR_PARAMS_H_
diff --git a/chrome/browser/ui/browser_tab_restorer.cc b/chrome/browser/ui/browser_tab_restorer.cc
index 981e61dc..91abc58 100644
--- a/chrome/browser/ui/browser_tab_restorer.cc
+++ b/chrome/browser/ui/browser_tab_restorer.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/sessions/core/tab_restore_service_observer.h"
 #include "content/public/browser/user_metrics.h"
@@ -107,7 +107,7 @@
     return;
 
   if (service->IsLoaded()) {
-    service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
+    service->RestoreMostRecentEntry(browser->live_tab_context(),
                                     browser->host_desktop_type());
     return;
   }
diff --git a/chrome/browser/ui/browser_tab_strip_model_delegate.cc b/chrome/browser/ui/browser_tab_strip_model_delegate.cc
index 047b9f2..653d0d72 100644
--- a/chrome/browser/ui/browser_tab_strip_model_delegate.cc
+++ b/chrome/browser/ui/browser_tab_strip_model_delegate.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/task_management/web_contents_tags.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/fast_unload_controller.h"
diff --git a/chrome/browser/ui/browser_tabrestore_browsertest.cc b/chrome/browser/ui/browser_tabrestore_browsertest.cc
index 3d5144dc..395f2efb 100644
--- a/chrome/browser/ui/browser_tabrestore_browsertest.cc
+++ b/chrome/browser/ui/browser_tabrestore_browsertest.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -123,16 +123,16 @@
       TabRestoreServiceFactory::GetForProfile(browser->profile());
   bool has_tab_restore_service = !!service;
   ASSERT_TRUE(has_tab_restore_service);
-  sessions::TabRestoreServiceDelegate* delegate =
-      BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+  sessions::LiveTabContext* context =
+      BrowserLiveTabContext::FindContextForWebContents(
           browser->tab_strip_model()->GetActiveWebContents());
-  bool has_tab_restore_delegate = !!delegate;
-  ASSERT_TRUE(has_tab_restore_delegate);
+  bool has_live_tab_context = !!context;
+  ASSERT_TRUE(has_live_tab_context);
 
   // Restore tabs using that delegated restore service.
   content::DOMMessageQueue queue;
   service->RestoreMostRecentEntry(
-      delegate, browser->host_desktop_type());
+      context, browser->host_desktop_type());
   AwaitTabsReady(&queue, 2);
 
   // There should be 3 restored tabs in the new browser.
diff --git a/chrome/browser/ui/browser_tabstrip.cc b/chrome/browser/ui/browser_tabstrip.cc
index bb20e62..995e0de 100644
--- a/chrome/browser/ui/browser_tabstrip.cc
+++ b/chrome/browser/ui/browser_tabstrip.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index e5755f4c..b377723a 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -255,11 +255,6 @@
       translate::TranslateErrors::Type error_type,
       bool is_user_gesture) = 0;
 
-  // Create a session recovery bubble if the last session crashed. It also
-  // offers the option to enable metrics reporting if it's not already enabled.
-  // Returns true if a bubble is created, returns false if nothing is created.
-  virtual bool ShowSessionCrashedBubble() = 0;
-
   // Shows the profile reset bubble on the platforms that support it.
   virtual bool IsProfileResetBubbleSupported() const = 0;
   virtual GlobalErrorBubbleViewBase* ShowProfileResetBubble(
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 8152d56..4e601389 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
diff --git a/chrome/browser/ui/chrome_select_file_policy.cc b/chrome/browser/ui/chrome_select_file_policy.cc
index caff78ef..1b32227 100644
--- a/chrome/browser/ui/chrome_select_file_policy.cc
+++ b/chrome/browser/ui/chrome_select_file_policy.cc
@@ -14,6 +14,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/infobars/core/simple_alert_infobar_delegate.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/vector_icons_public.h"
 
 ChromeSelectFilePolicy::ChromeSelectFilePolicy(
     content::WebContents* source_contents)
@@ -32,6 +33,7 @@
     SimpleAlertInfoBarDelegate::Create(
         InfoBarService::FromWebContents(source_contents_),
         infobars::InfoBarDelegate::kNoIconID,
+        gfx::VectorIconId::VECTOR_ICON_NONE,
         l10n_util::GetStringUTF16(IDS_FILE_SELECTION_DIALOG_INFOBAR), true);
   } else {
     LOG(WARNING) << "File-selection dialogs are disabled but no WebContents "
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
index 7fdede6..e0874c64 100644
--- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/cocoa/applescript/constants_applescript.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
index 6f0a942..6e3f50a 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.mm
@@ -19,6 +19,7 @@
 #import "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/chrome_pages.h"
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
index d5734c0..0a14142 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
@@ -9,6 +9,7 @@
 #import "chrome/browser/app_controller_mac.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 35e1049..637edc5 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -118,7 +118,6 @@
                            translate::TranslateStep step,
                            translate::TranslateErrors::Type error_type,
                            bool is_user_gesture) override;
-  bool ShowSessionCrashedBubble() override;
   bool IsProfileResetBubbleSupported() const override;
   GlobalErrorBubbleViewBase* ShowProfileResetBubble(
       const base::WeakPtr<ProfileResetGlobalError>& global_error) override;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index 75abbe9..028c744 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -644,10 +644,6 @@
                                        errorType:error_type];
 }
 
-bool BrowserWindowCocoa::ShowSessionCrashedBubble() {
-  return false;
-}
-
 bool BrowserWindowCocoa::IsProfileResetBubbleSupported() const {
   return false;
 }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
index 2e253f1..07e09f9 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm
@@ -44,6 +44,7 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "ui/base/cocoa/nsview_additions.h"
 #include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/vector_icons_public.h"
 
 namespace {
 
@@ -207,7 +208,7 @@
     SimpleAlertInfoBarDelegate::Create(
         InfoBarService::FromWebContents(
             browser->tab_strip_model()->GetActiveWebContents()),
-        0, base::string16(), false);
+        0, gfx::VectorIconId::VECTOR_ICON_NONE, base::string16(), false);
   }
 
   NSView* GetViewWithID(ViewID view_id) const {
diff --git a/chrome/browser/ui/cocoa/download/download_item_cell.mm b/chrome/browser/ui/cocoa/download/download_item_cell.mm
index 3180b8c..892ceb0 100644
--- a/chrome/browser/ui/cocoa/download/download_item_cell.mm
+++ b/chrome/browser/ui/cocoa/download/download_item_cell.mm
@@ -29,6 +29,9 @@
 // Distance from left border to icon.
 const CGFloat kImagePaddingLeft = 9;
 
+// Horizontal distance from the icon to the text.
+const CGFloat kImagePaddingRight = 7;
+
 // Width of icon.
 const CGFloat kImageWidth = 16;
 
@@ -37,7 +40,7 @@
 
 // x coordinate of download name string, in view coords.
 const CGFloat kTextPosLeft = kImagePaddingLeft +
-    kImageWidth + DownloadShelf::kFiletypeIconOffset;
+    kImageWidth + DownloadShelf::kFiletypeIconOffset + kImagePaddingRight;
 
 // Distance from end of download name string to dropdown area.
 const CGFloat kTextPaddingRight = 3;
@@ -548,9 +551,9 @@
     int x = imagePosition.x - DownloadShelf::kFiletypeIconOffset;
     int y = imagePosition.y - DownloadShelf::kFiletypeIconOffset;
     NSRect dirtyRect = NSMakeRect(
-        x, y,
-        DownloadShelf::kProgressIndicatorSize,
-        DownloadShelf::kProgressIndicatorSize);
+        x - 1, y - 1,
+        DownloadShelf::kProgressIndicatorSize + 2,
+        DownloadShelf::kProgressIndicatorSize + 2);
 
     gfx::CanvasSkiaPaint canvas(dirtyRect, false);
     canvas.set_composite_alpha(true);
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
index 4789f29..6421cf7 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
@@ -13,6 +13,7 @@
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/chrome_style.h"
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm
index f3a9503..b92fce9a 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -87,7 +87,7 @@
   // (which is likely to be forced in enterprise deployments anyway).
   const PrefService::Preference* metrics_reporting_pref =
       g_browser_process->local_state()->FindPreference(
-          prefs::kMetricsReportingEnabled);
+          metrics::prefs::kMetricsReportingEnabled);
   if (!metrics_reporting_pref || !metrics_reporting_pref->IsManaged()) {
     base::scoped_nsobject<FirstRunDialogController> dialog(
         [[FirstRunDialogController alloc] init]);
diff --git a/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm
index ed86edd6..f1325ac 100644
--- a/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm
+++ b/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm
@@ -10,8 +10,9 @@
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/history_types.h"
@@ -46,9 +47,9 @@
   if (node->session_id && service) {
     Browser* browser = chrome::FindTabbedBrowser(bridge_->profile(), false,
         chrome::HOST_DESKTOP_TYPE_NATIVE);
-    BrowserTabRestoreServiceDelegate* delegate = browser ?
-        browser->tab_restore_service_delegate() : NULL;
-    service->RestoreEntryById(delegate, node->session_id,
+    BrowserLiveTabContext* context =
+        browser ? browser->live_tab_context() : NULL;
+    service->RestoreEntryById(context, node->session_id,
         chrome::HOST_DESKTOP_TYPE_NATIVE, UNKNOWN);
   } else {
     DCHECK(node->url.is_valid());
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
index df2027b..188c70e 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h
@@ -33,6 +33,7 @@
   // Overridden from OmniboxPopupView:
   bool IsOpen() const override;
   void InvalidateLine(size_t line) override {}
+  void OnLineSelected(size_t line) override {}
   void UpdatePopupAppearance() override;
   gfx::Rect GetTargetBounds() override;
   // This is only called by model in SetSelectedLine() after updating
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 09dc46f..298dc4f 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
@@ -52,6 +52,7 @@
   // Overridden from OmniboxPopupView:
   bool IsOpen() const override { return is_open_; }
   void InvalidateLine(size_t line) override {}
+  void OnLineSelected(size_t line) override {}
   void UpdatePopupAppearance() override {}
   gfx::Rect GetTargetBounds() override { return gfx::Rect(); }
   void PaintUpdatesNow() override {}
diff --git a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
index 2af31fd..82de329 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller.mm
@@ -13,6 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #import "chrome/browser/ui/chrome_style.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_control_utils.h"
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
diff --git a/chrome/browser/ui/cocoa/session_crashed_bubble.mm b/chrome/browser/ui/cocoa/session_crashed_bubble.mm
new file mode 100644
index 0000000..3563bc17
--- /dev/null
+++ b/chrome/browser/ui/cocoa/session_crashed_bubble.mm
@@ -0,0 +1,9 @@
+// Copyright 2015 The Chromium Authors. 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/session_crashed_bubble.h"
+
+bool SessionCrashedBubble::Show(Browser* /* browser */) {
+  return false;
+}
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index 5f9cff2..9fe0804d 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -25,6 +25,7 @@
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #include "chrome/browser/ui/cocoa/drag_util.h"
@@ -2126,6 +2127,10 @@
   GURL url(GURL(url_formatter::FixupURL(
       base::SysNSStringToUTF8([urls objectAtIndex:0]), std::string())));
 
+  // If the URL isn't valid, don't bother.
+  if (!url.is_valid())
+    return;
+
   [self openURL:&url inView:view at:point];
 }
 
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 1eb9c75..76351bd 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index 152a3f2..8752b2f5 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
diff --git a/chrome/browser/ui/extensions/extension_install_ui_default.cc b/chrome/browser/ui/extensions/extension_install_ui_default.cc
index 32b306b..7d859f6 100644
--- a/chrome/browser/ui/extensions/extension_install_ui_default.cc
+++ b/chrome/browser/ui/extensions/extension_install_ui_default.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 590bcdd..a949449 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index a74309e..a25b311 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -27,6 +28,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
@@ -267,7 +269,7 @@
         TemplateURLServiceFactory::GetForProfile(profile);
     ASSERT_TRUE(model);
 
-    ui_test_utils::WaitForTemplateURLServiceToLoad(model);
+    search_test_utils::WaitForTemplateURLServiceToLoad(model);
 
     ASSERT_TRUE(model->loaded());
 
diff --git a/chrome/browser/ui/panels/panel_host.cc b/chrome/browser/ui/panels/panel_host.cc
index 2fbc91c3..b3a00f5 100644
--- a/chrome/browser/ui/panels/panel_host.cc
+++ b/chrome/browser/ui/panels/panel_host.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/panels/panel.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "components/favicon/content/content_favicon_driver.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_state.cc b/chrome/browser/ui/passwords/manage_passwords_state.cc
index dda3d3a..33649b866 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_state.cc
@@ -149,7 +149,7 @@
   // TODO(vabr): Revert back to DCHECK once http://crbug.com/486931 is fixed.
   CHECK(!password_form_map.empty());
   ClearData();
-  if (password_form_map.begin()->second->IsPublicSuffixMatch()) {
+  if (password_form_map.begin()->second->is_public_suffix_match) {
     // Don't show the UI for PSL matched passwords. They are not stored for this
     // page and cannot be deleted.
     origin_ = GURL();
diff --git a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
index b36df63..656468c2 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
@@ -358,7 +358,7 @@
 
 TEST_F(ManagePasswordsStateTest, InactiveOnPSLMatched) {
   autofill::PasswordForm psl_matched_test_form = test_local_form();
-  psl_matched_test_form.original_signon_realm = "http://pslmatched.example.com";
+  psl_matched_test_form.is_public_suffix_match = true;
   autofill::PasswordFormMap password_form_map;
   password_form_map.insert(
       psl_matched_test_form.username_value,
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
index 74f5b86..595528f 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
@@ -156,8 +157,17 @@
 
 void ManagePasswordsUIController::OnPasswordAutofilled(
     const PasswordFormMap& password_form_map) {
-  passwords_data_.OnPasswordAutofilled(password_form_map);
-  UpdateBubbleAndIconVisibility();
+  // If we fill a form while a dialog is open, then skip the state change; we
+  // have
+  // the information we need, and the dialog will change its own state once the
+  // interaction is complete.
+  if (passwords_data_.state() !=
+          password_manager::ui::AUTO_SIGNIN_STATE &&
+      passwords_data_.state() !=
+          password_manager::ui::CREDENTIAL_REQUEST_STATE) {
+    passwords_data_.OnPasswordAutofilled(password_form_map);
+    UpdateBubbleAndIconVisibility();
+  }
 }
 
 void ManagePasswordsUIController::OnBlacklistBlockedAutofill(
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
index 1697393..4914f0b 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -544,13 +544,32 @@
   EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state());
 }
 
+TEST_F(ManagePasswordsUIControllerTest, AutofillDuringAutoSignin) {
+  ScopedVector<autofill::PasswordForm> local_credentials;
+  local_credentials.push_back(new autofill::PasswordForm(test_local_form()));
+  controller()->OnAutoSignin(local_credentials.Pass());
+  ManagePasswordsIconMock mock;
+  controller()->UpdateIconAndBubbleState(&mock);
+  EXPECT_EQ(password_manager::ui::AUTO_SIGNIN_STATE, mock.state());
+  EXPECT_EQ(password_manager::ui::AUTO_SIGNIN_STATE, controller()->state());
+
+  scoped_ptr<autofill::PasswordForm> test_form(
+      new autofill::PasswordForm(test_local_form()));
+  autofill::PasswordFormMap map;
+  base::string16 kTestUsername = test_form->username_value;
+  map.insert(kTestUsername, test_form.Pass());
+  controller()->OnPasswordAutofilled(map);
+
+  EXPECT_EQ(password_manager::ui::AUTO_SIGNIN_STATE, mock.state());
+  EXPECT_EQ(password_manager::ui::AUTO_SIGNIN_STATE, controller()->state());
+}
+
 TEST_F(ManagePasswordsUIControllerTest, InactiveOnPSLMatched) {
   base::string16 kTestUsername = base::ASCIIToUTF16("test_username");
   autofill::PasswordFormMap map;
   scoped_ptr<autofill::PasswordForm> psl_matched_test_form(
       new autofill::PasswordForm(test_local_form()));
-  psl_matched_test_form->original_signon_realm =
-      "http://pslmatched.example.com";
+  psl_matched_test_form->is_public_suffix_match = true;
   map.insert(kTestUsername, psl_matched_test_form.Pass());
   controller()->OnPasswordAutofilled(map);
 
diff --git a/chrome/browser/ui/search/instant_search_prerenderer.cc b/chrome/browser/ui/search/instant_search_prerenderer.cc
index 1d190c4..2bbe5d0 100644
--- a/chrome/browser/ui/search/instant_search_prerenderer.cc
+++ b/chrome/browser/ui/search/instant_search_prerenderer.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/search/search.h"
diff --git a/chrome/browser/ui/search/instant_test_utils.cc b/chrome/browser/ui/search/instant_test_utils.cc
index 1402129..56841fc 100644
--- a/chrome/browser/ui/search/instant_test_utils.cc
+++ b/chrome/browser/ui/search/instant_test_utils.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/interactive_test_utils.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/variations/entropy_provider.h"
@@ -49,7 +49,7 @@
 
   TemplateURLService* service =
       TemplateURLServiceFactory::GetForProfile(browser_->profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(service);
 
   TemplateURLData data;
   // Necessary to use exact URL for both the main URL and the alternate URL for
@@ -72,7 +72,7 @@
 void InstantTestBase::SetInstantURL(const std::string& url) {
   TemplateURLService* service =
       TemplateURLServiceFactory::GetForProfile(browser_->profile());
-  ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+  search_test_utils::WaitForTemplateURLServiceToLoad(service);
 
   TemplateURLData data;
   data.SetShortName(base::ASCIIToUTF16("name"));
diff --git a/chrome/browser/ui/search/new_tab_page_interceptor_browsertest.cc b/chrome/browser/ui/search/new_tab_page_interceptor_browsertest.cc
index 3684620d..656fa28 100644
--- a/chrome/browser/ui/search/new_tab_page_interceptor_browsertest.cc
+++ b/chrome/browser/ui/search/new_tab_page_interceptor_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_controller.h"
@@ -48,7 +49,7 @@
   void ChangeDefaultSearchProvider(const char* new_tab_path) {
     TemplateURLService* template_url_service =
         TemplateURLServiceFactory::GetForProfile(browser()->profile());
-    ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
+    search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
     UIThreadSearchTermsData::SetGoogleBaseURL("https://mock.http/");
     std::string base_url("{google:baseURL}");
     TemplateURLData data;
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index 24c3c119..a9507a7 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/search_test_utils.h"
 #include "components/omnibox/common/omnibox_focus_state.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_controller.h"
@@ -105,7 +105,7 @@
         &TemplateURLServiceFactory::BuildInstanceFor);
     TemplateURLService* template_url_service =
         TemplateURLServiceFactory::GetForProfile(profile());
-    ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
+    search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
 
     TemplateURLData data;
     data.SetShortName(base::ASCIIToUTF16("foo.com"));
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 2464b71..b90872377 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/app_list/app_list_util.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/omnibox/clipboard_utils.h"
diff --git a/chrome/browser/ui/session_crashed_bubble.h b/chrome/browser/ui/session_crashed_bubble.h
new file mode 100644
index 0000000..1bade0fe
--- /dev/null
+++ b/chrome/browser/ui/session_crashed_bubble.h
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. 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_SESSION_CRASHED_BUBBLE_H_
+#define CHROME_BROWSER_UI_SESSION_CRASHED_BUBBLE_H_
+
+#include "base/macros.h"
+
+class Browser;
+
+// Base class for a session restore request bubble, to be displayed when the
+// previous session has crashed. It also presents an option to enable metrics
+// reporting, if it not enabled already.
+class SessionCrashedBubble {
+ public:
+  // Create a session recovery bubble if the last session crashed. It also
+  // offers the option to enable metrics reporting if it's not already enabled.
+  // Returns true if a bubble is created, returns false if nothing is created.
+  static bool Show(Browser* browser);
+
+  virtual ~SessionCrashedBubble() {}
+
+ protected:
+  SessionCrashedBubble() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SessionCrashedBubble);
+};
+
+#endif  // CHROME_BROWSER_UI_SESSION_CRASHED_BUBBLE_H_
diff --git a/chrome/browser/ui/settings_window_manager.cc b/chrome/browser/ui/settings_window_manager.cc
index d050e61..9a8d599 100644
--- a/chrome/browser/ui/settings_window_manager.cc
+++ b/chrome/browser/ui/settings_window_manager.cc
@@ -6,8 +6,8 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/settings_window_manager_observer.h"
diff --git a/chrome/browser/ui/singleton_tabs.cc b/chrome/browser/ui/singleton_tabs.cc
index 7c450c44..870e8df 100644
--- a/chrome/browser/ui/singleton_tabs.cc
+++ b/chrome/browser/ui/singleton_tabs.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/browser_url_handler.h"
diff --git a/chrome/browser/ui/singleton_tabs.h b/chrome/browser/ui/singleton_tabs.h
index 04ed83d..d13b724 100644
--- a/chrome/browser/ui/singleton_tabs.h
+++ b/chrome/browser/ui/singleton_tabs.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_SINGLETON_TABS_H_
 #define CHROME_BROWSER_UI_SINGLETON_TABS_H_
 
+#include "chrome/browser/ui/browser_navigator_params.h"
+
 class Browser;
 class GURL;
 
@@ -13,8 +15,6 @@
 
 namespace chrome {
 
-struct NavigateParams;
-
 // Core singleton tab API:
 
 // Show a given a URL. If a tab with the same URL (ignoring the ref) is
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc
index cfd8d7f..82d9317 100644
--- a/chrome/browser/ui/startup/bad_flags_prompt.cc
+++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -26,6 +26,7 @@
 #include "google_apis/gaia/gaia_switches.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/vector_icons_public.h"
 
 namespace chrome {
 
@@ -105,9 +106,10 @@
       SimpleAlertInfoBarDelegate::Create(
           InfoBarService::FromWebContents(web_contents),
           infobars::InfoBarDelegate::kNoIconID,
-          l10n_util::GetStringFUTF16(IDS_BAD_FLAGS_WARNING_MESSAGE,
-                                     base::UTF8ToUTF16(
-                                         std::string("--") + *flag)),
+          gfx::VectorIconId::VECTOR_ICON_NONE,
+          l10n_util::GetStringFUTF16(
+              IDS_BAD_FLAGS_WARNING_MESSAGE,
+              base::UTF8ToUTF16(std::string("--") + *flag)),
           false);
       return;
     }
diff --git a/chrome/browser/ui/startup/default_browser_prompt.cc b/chrome/browser/ui/startup/default_browser_prompt.cc
index ce1585d..c091cf8 100644
--- a/chrome/browser/ui/startup/default_browser_prompt.cc
+++ b/chrome/browser/ui/startup/default_browser_prompt.cc
@@ -32,7 +32,7 @@
 #include "content/public/browser/web_contents.h"
 #include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
-
+#include "ui/gfx/vector_icons_public.h"
 
 namespace {
 
@@ -115,7 +115,9 @@
   void AllowExpiry() { should_expire_ = true; }
 
   // ConfirmInfoBarDelegate:
+  Type GetInfoBarType() const override;
   int GetIconId() const override;
+  gfx::VectorIconId GetVectorIconId() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
   base::string16 GetMessageText() const override;
   base::string16 GetButtonLabel(InfoBarButton button) const override;
@@ -165,10 +167,23 @@
     UMA_HISTOGRAM_BOOLEAN("DefaultBrowserWarning.Ignored", true);
 }
 
+infobars::InfoBarDelegate::Type DefaultBrowserInfoBarDelegate::GetInfoBarType()
+    const {
+  return PAGE_ACTION_TYPE;
+}
+
 int DefaultBrowserInfoBarDelegate::GetIconId() const {
   return IDR_PRODUCT_LOGO_32;
 }
 
+gfx::VectorIconId DefaultBrowserInfoBarDelegate::GetVectorIconId() const {
+#if defined(OS_MACOSX) || defined(OS_ANDROID) || defined(OS_IOS)
+  return gfx::VectorIconId::VECTOR_ICON_NONE;
+#else
+  return gfx::VectorIconId::CHROME_PRODUCT;
+#endif
+}
+
 bool DefaultBrowserInfoBarDelegate::ShouldExpire(
     const NavigationDetails& details) const {
   return should_expire_ && ConfirmInfoBarDelegate::ShouldExpire(details);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 61fb39c..7614fec3 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabrestore.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -61,6 +62,7 @@
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/session_crashed_bubble.h"
 #include "chrome/browser/ui/startup/autolaunch_prompt.h"
 #include "chrome/browser/ui/startup/bad_flags_prompt.h"
 #include "chrome/browser/ui/startup/default_browser_prompt.h"
@@ -803,7 +805,7 @@
     return;
 
   if (HasPendingUncleanExit(browser->profile()) &&
-      !browser->window()->ShowSessionCrashedBubble()) {
+      !SessionCrashedBubble::Show(browser)) {
     SessionCrashedInfoBarDelegate::Create(browser);
   }
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
index e872c3f..24deba51 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
@@ -155,13 +155,11 @@
   TabStripModel* tab_strip = new_browser->tab_strip_model();
   ASSERT_EQ(2, tab_strip->count());
 
-  if (signin::ShouldShowPromoAtStartup(browser()->profile(), true)) {
-    EXPECT_EQ(signin::GetPromoURL(signin_metrics::SOURCE_START_PAGE, false),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-  } else {
-    EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
-              tab_strip->GetWebContentsAt(0)->GetURL());
-  }
+  GURL expected_first_tab_url =
+      signin::ShouldShowPromoAtStartup(browser()->profile(), true)
+          ? signin::GetPromoURL(signin_metrics::SOURCE_START_PAGE, false)
+          : GURL(chrome::kChromeUINewTabURL);
+  EXPECT_EQ(expected_first_tab_url, tab_strip->GetWebContentsAt(0)->GetURL());
 
   EXPECT_EQ("title1.html",
             tab_strip->GetWebContentsAt(1)->GetURL().ExtractFileName());
diff --git a/chrome/browser/ui/sync/one_click_signin_bubble_links_delegate.cc b/chrome/browser/ui/sync/one_click_signin_bubble_links_delegate.cc
index 0712703..3e06aee 100644
--- a/chrome/browser/ui/sync/one_click_signin_bubble_links_delegate.cc
+++ b/chrome/browser/ui/sync/one_click_signin_bubble_links_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/common/url_constants.h"
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
index 2cab4fc..b7f43a88 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
@@ -71,8 +71,6 @@
  private:
   explicit OneClickTestProfileSyncService(Profile* profile)
       : TestProfileSyncService(
-          scoped_ptr<sync_driver::SyncApiComponentFactory>(
-              new ProfileSyncComponentsFactoryMock()),
           profile,
           SigninManagerFactory::GetForProfile(profile),
           ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
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 a87c44c..da7a847 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
index 5e7f279..3c9bea0 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
@@ -212,9 +212,8 @@
       CreateExtension("web store",
                       extensions::kWebStoreAppId,
                       extensions::Manifest::COMPONENT);
-  extensions::PermissionSet empty_permissions;
   extensions::ExtensionPrefs::Get(profile_.get())
-      ->AddGrantedPermissions(webstore->id(), &empty_permissions);
+      ->AddGrantedPermissions(webstore->id(), extensions::PermissionSet());
   extensions->AddExtension(webstore.get());
   EXPECT_FALSE(GetCallbackResult(
       base::Bind(&ui::CheckShouldPromptForNewProfile, profile_.get())));
@@ -222,7 +221,7 @@
   scoped_refptr<extensions::Extension> extension =
       CreateExtension("foo", std::string(), extensions::Manifest::INTERNAL);
   extensions::ExtensionPrefs::Get(profile_.get())
-      ->AddGrantedPermissions(extension->id(), &empty_permissions);
+      ->AddGrantedPermissions(extension->id(), extensions::PermissionSet());
   extensions->AddExtension(extension.get());
   EXPECT_TRUE(GetCallbackResult(
       base::Bind(&ui::CheckShouldPromptForNewProfile, profile_.get())));
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 53736b45..d49e7a2 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
-#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "chrome/browser/ui/navigation_correction_tab_observer.h"
 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
@@ -60,6 +59,7 @@
 #include "chrome/browser/plugins/plugin_observer.h"
 #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h"
 #include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
+#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/hung_plugin_tab_helper.h"
 #include "chrome/browser/ui/sad_tab_helper.h"
 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
@@ -143,7 +143,6 @@
       autofill::ChromeAutofillClient::FromWebContents(web_contents),
       g_browser_process->GetApplicationLocale(),
       autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
-  BookmarkTabHelper::CreateForWebContents(web_contents);
   chrome_browser_net::NetErrorTabHelper::CreateForWebContents(web_contents);
   chrome_browser_net::PredictorTabHelper::CreateForWebContents(web_contents);
   ChromeContentSettingsClient::CreateForWebContents(web_contents);
@@ -185,6 +184,7 @@
   VoiceSearchTabHelper::CreateForWebContents(web_contents);
   WindowAndroidHelper::CreateForWebContents(web_contents);
 #else
+  BookmarkTabHelper::CreateForWebContents(web_contents);
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
       web_contents);
   extensions::WebNavigationTabObserver::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/tabs/tab_discard_state.cc b/chrome/browser/ui/tabs/tab_discard_state.cc
index 7a7e8f05..da2a386 100644
--- a/chrome/browser/ui/tabs/tab_discard_state.cc
+++ b/chrome/browser/ui/tabs/tab_discard_state.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/tabs/tab_discard_state.h"
 
+#include "base/metrics/histogram.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 
 using content::WebContents;
@@ -16,6 +18,7 @@
 
 // static
 TabDiscardState* TabDiscardState::Get(WebContents* web_contents) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   TabDiscardState* discard_state = static_cast<TabDiscardState*>(
       web_contents->GetUserData(&kDiscardStateKey));
 
@@ -31,6 +34,7 @@
 
 // static
 void TabDiscardState::Set(WebContents* web_contents, TabDiscardState* state) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   web_contents->SetUserData(&kDiscardStateKey, state);
 }
 
@@ -43,6 +47,12 @@
 // static
 void TabDiscardState::SetDiscardState(WebContents* web_contents, bool state) {
   TabDiscardState* discard_state = TabDiscardState::Get(web_contents);
+  if (discard_state->is_discarded_ && !state) {
+    static int reload_count = 0;
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.Discard.ReloadCount", ++reload_count, 1,
+                                1000, 50);
+  }
+
   discard_state->is_discarded_ = state;
 }
 
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model.cc b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
index 15d58e7e..2fff7c07 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
@@ -467,7 +468,7 @@
 std::string BackForwardMenuModel::BuildActionName(
     const std::string& action, int index) const {
   DCHECK(!action.empty());
-  DCHECK(index >= -1);
+  DCHECK_GE(index, -1);
   std::string metric_string;
   if (model_type_ == FORWARD_MENU)
     metric_string += "ForwardMenu_";
diff --git a/chrome/browser/ui/toolbar/media_router_action_unittest.cc b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
index e2358e6..c10392f 100644
--- a/chrome/browser/ui/toolbar/media_router_action_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
@@ -183,34 +183,34 @@
   EXPECT_EQ("media_router_action", action()->GetId());
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_TITLE),
       action()->GetActionName());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 }
 
 // Tests the MediaRouterAction icon based on updates to issues.
 TEST_F(MediaRouterActionUnitTest, UpdateIssues) {
   // Initially, there are no issues.
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Don't update |current_icon_| since the issue is only a notification.
   action()->OnIssueUpdated(fake_issue_notification());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since the issue is a warning.
   action()->OnIssueUpdated(fake_issue_warning());
-  EXPECT_TRUE(gfx::test::IsEqual(warning_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      warning_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since the issue is fatal.
   action()->OnIssueUpdated(fake_issue_fatal());
-  EXPECT_TRUE(gfx::test::IsEqual(error_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      error_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Clear the issue.
   action()->OnIssueUpdated(nullptr);
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
+  EXPECT_TRUE(gfx::test::AreImagesEqual(idle_icon(),
                                  action()->GetIcon(nullptr, gfx::Size())));
 }
 
@@ -220,28 +220,28 @@
       new std::vector<media_router::MediaRoute>());
 
   // Initially, there are no routes.
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since there is a local route.
   routes->push_back(fake_route_local());
   routes->push_back(fake_route_remote());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(active_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      active_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since there are no more local routes.
   routes->clear();
   routes->push_back(fake_route_remote());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // |current_icon_| stays the same if there are no local routes or no routes.
   routes->clear();
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 }
 
 // Tests the MediaRouterAction icon based on updates to both issues and routes.
@@ -250,67 +250,67 @@
       new std::vector<media_router::MediaRoute>());
 
   // Initially, there are no issues or routes.
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // There is no change in |current_icon_| since notification issues do not
   // update the state.
   action()->OnIssueUpdated(fake_issue_notification());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Non-local routes also do not have an effect on |current_icon_|.
   routes->push_back(fake_route_remote());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since there is a local route.
   routes->clear();
   routes->push_back(fake_route_local());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(active_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      active_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_|, with a priority to reflect the warning issue
   // rather than the local route.
   action()->OnIssueUpdated(fake_issue_warning());
-  EXPECT_TRUE(gfx::test::IsEqual(warning_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      warning_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Swapping the local route for a non-local one makes no difference to the
   // |current_icon_|.
   routes->clear();
   routes->push_back(fake_route_remote());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(warning_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      warning_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| since the issue has been updated to fatal.
   action()->OnIssueUpdated(fake_issue_fatal());
-  EXPECT_TRUE(gfx::test::IsEqual(error_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      error_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Fatal issues still take precedent over local routes.
   routes->clear();
   routes->push_back(fake_route_local());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(error_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      error_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // When the fatal issue is dismissed, |current_icon_| reflects the existing
   // local route.
   action()->OnIssueUpdated(nullptr);
-  EXPECT_TRUE(gfx::test::IsEqual(active_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      active_icon(), action()->GetIcon(nullptr, gfx::Size())));
 
   // Update |current_icon_| when the local route is swapped out for a non-local
   // route.
   routes->clear();
   routes->push_back(fake_route_remote());
   action()->OnRoutesUpdated(*routes.get());
-  EXPECT_TRUE(gfx::test::IsEqual(idle_icon(),
-                                 action()->GetIcon(nullptr, gfx::Size())));
+  EXPECT_TRUE(gfx::test::AreImagesEqual(
+      idle_icon(), action()->GetIcon(nullptr, gfx::Size())));
 }
 
 TEST_F(MediaRouterActionUnitTest, IconPressedState) {
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 8ff9240..cdb15065 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/sync/profile_sync_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/browser_live_tab_context.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
 #include "chrome/grit/generated_resources.h"
@@ -288,8 +288,8 @@
 
   sessions::TabRestoreService* service =
       TabRestoreServiceFactory::GetForProfile(browser_->profile());
-  sessions::TabRestoreServiceDelegate* delegate =
-      BrowserTabRestoreServiceDelegate::FindDelegateForWebContents(
+  sessions::LiveTabContext* context =
+      BrowserLiveTabContext::FindContextForWebContents(
           browser_->tab_strip_model()->GetActiveWebContents());
   if (IsTabModelCommandId(command_id)) {
     TabNavigationItems* tab_items = NULL;
@@ -298,12 +298,12 @@
     DCHECK(item.tab_id > -1 && item.url.is_valid());
 
     if (item.session_tag.empty()) {  // Restore tab of local session.
-      if (service && delegate) {
+      if (service && context) {
         content::RecordAction(
             base::UserMetricsAction("WrenchMenu_OpenRecentTabFromLocal"));
         UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu",
                                   LOCAL_SESSION_TAB, LIMIT_RECENT_TAB_ACTION);
-        service->RestoreEntryById(delegate, item.tab_id,
+        service->RestoreEntryById(context, item.tab_id,
                                   browser_->host_desktop_type(), disposition);
       }
     } else {  // Restore tab of session from other devices.
@@ -325,7 +325,7 @@
     }
   } else {
     DCHECK(IsWindowModelCommandId(command_id));
-    if (service && delegate) {
+    if (service && context) {
       int window_items_idx = CommandIdToWindowVectorIndex(command_id);
       DCHECK(window_items_idx >= 0 &&
              window_items_idx < static_cast<int>(local_window_items_.size()));
@@ -333,7 +333,7 @@
           base::UserMetricsAction("WrenchMenu_OpenRecentWindow"));
       UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", RESTORE_WINDOW,
                                 LIMIT_RECENT_TAB_ACTION);
-      service->RestoreEntryById(delegate, local_window_items_[window_items_idx],
+      service->RestoreEntryById(context, local_window_items_[window_items_idx],
                                 browser_->host_desktop_type(), disposition);
     }
   }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index 4db2bed..8a5c2b2e 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -463,7 +463,6 @@
     return;
   }
 
-  is_drag_in_progress_ = false;
   int delta = 0;
   if (drag_type == DRAG_TO_OVERFLOW)
     delta = -1;
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index 805c906..7bbdb3c 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -898,6 +898,8 @@
 
   CreateZoomMenu();
   AddItemWithStringId(IDC_PRINT, IDS_PRINT);
+  if (switches::MediaRouterEnabled() && !browser()->profile()->IsOffTheRecord())
+    AddItemWithStringId(IDC_ROUTE_MEDIA, IDS_MEDIA_ROUTER_MENU_ITEM_TITLE);
   AddItemWithStringId(IDC_FIND, IDS_FIND);
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableDomDistiller))
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
index 4302a966..f4131a1 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h"
 
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 2cc9c3d..dbe7120f 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index c659c617..56449a6 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
index 82e3dd9..255e7e2 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/bookmarks/bookmark_bubble_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
index f3a9d6e..f247947d 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
index 092c1ef7..802d9f29 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/locale_settings.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index 3c17088..832b6ff 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
 #include "chrome/browser/ui/views/event_utils.h"
@@ -399,7 +400,7 @@
   // to support different parents, but this would need to prune any nodes whose
   // parent has been removed. As all nodes currently have the same parent, there
   // is the DCHECK.
-  DCHECK(changed_parent_menus.size() <= 1);
+  DCHECK_LE(changed_parent_menus.size(), 1U);
 
   // Remove any descendants of the removed nodes in |node_to_menu_map_|.
   for (NodeToMenuMap::iterator i(node_to_menu_map_.begin());
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index da76670..ee54a22 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -68,6 +68,9 @@
 static const int kVerticalTextPadding = 2;    // Pixels
 static const int kTooltipMaxWidth = 800;      // Pixels
 
+// Padding around progress indicator, on all sides.
+static const int kProgressPadding = 7;
+
 // We add some padding before the left image so that the progress animation icon
 // hides the corners of the left image.
 static const int kLeftPadding = 0;  // Pixels.
@@ -206,10 +209,9 @@
                                   normal_body_image_set_.top_left->height() +
                                   normal_body_image_set_.bottom_left->height());
 
-  if (DownloadShelf::kProgressIndicatorSize > box_height_)
-    box_y_ = (DownloadShelf::kProgressIndicatorSize - box_height_) / 2;
-  else
-    box_y_ = 0;
+  box_y_ = std::max(0, (2 * kProgressPadding +
+                        DownloadShelf::kProgressIndicatorSize - box_height_) /
+                           2);
 
   body_hover_animation_.reset(new gfx::SlideAnimation(this));
   drop_hover_animation_.reset(new gfx::SlideAnimation(this));
@@ -381,7 +383,8 @@
   height = 2 * kVerticalPadding + 2 * font_list_.GetHeight() +
       kVerticalTextPadding;
   // Then we increase the size if the progress icon doesn't fit.
-  height = std::max<int>(height, DownloadShelf::kProgressIndicatorSize);
+  height = std::max<int>(
+      height, DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding);
 
   if (IsShowingWarningDialog()) {
     const BodyImageSet* body_image_set =
@@ -404,7 +407,7 @@
       width += normal_drop_down_image_set_.top->width();
   } else {
     width = kLeftPadding + normal_body_image_set_.top_left->width();
-    width += DownloadShelf::kProgressIndicatorSize;
+    width += DownloadShelf::kProgressIndicatorSize + 2 * kProgressPadding;
     width += kTextWidth;
     width += normal_body_image_set_.top_right->width();
     width += normal_drop_down_image_set_.top->width();
@@ -700,7 +703,8 @@
   if (!IsShowingWarningDialog()) {
     if (!status_text_.empty()) {
       int mirrored_x = GetMirroredXWithWidthInView(
-          DownloadShelf::kProgressIndicatorSize, kTextWidth);
+          2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize,
+          kTextWidth);
       // Add font_list_.height() to compensate for title, which is drawn later.
       int y = box_y_ + kVerticalPadding + font_list_.GetHeight() +
               kVerticalTextPadding;
@@ -826,7 +830,8 @@
     }
 
     int mirrored_x = GetMirroredXWithWidthInView(
-        DownloadShelf::kProgressIndicatorSize, kTextWidth);
+        2 * kProgressPadding + DownloadShelf::kProgressIndicatorSize,
+        kTextWidth);
     SkColor file_name_color = GetThemeProvider()->GetColor(
         ThemeProperties::COLOR_BOOKMARK_TEXT);
     int y =
@@ -856,13 +861,17 @@
   // loaded, in which case LookupIcon will always be NULL. The loading will be
   // triggered only when we think the status might change.
   if (icon) {
-    if (!IsShowingWarningDialog()) {
-      DownloadItem::DownloadState state = download()->GetState();
-      canvas->Save();
-      if (base::i18n::IsRTL())
-        canvas->Translate(
-            gfx::Vector2d(width() - DownloadShelf::kProgressIndicatorSize, 0));
+    int progress_x =
+        base::i18n::IsRTL()
+            ? width() - kProgressPadding - DownloadShelf::kProgressIndicatorSize
+            : kProgressPadding;
+    int progress_y = kProgressPadding;
 
+    if (!IsShowingWarningDialog()) {
+      canvas->Save();
+      canvas->Translate(gfx::Vector2d(progress_x, progress_y));
+
+      DownloadItem::DownloadState state = download()->GetState();
       if (state == DownloadItem::IN_PROGRESS) {
         base::TimeDelta progress_time = previous_progress_elapsed_;
         if (!download()->IsPaused())
@@ -891,12 +900,12 @@
 
     if (IsShowingWarningDialog()) {
       icon_x = kLeftPadding + body_image_set->top_left->width();
+      icon_x = GetMirroredXWithWidthInView(icon_x, icon->width());
       icon_y = (height() - icon->height()) / 2;
     } else {
-      icon_x = DownloadShelf::kFiletypeIconOffset;
-      icon_y = DownloadShelf::kFiletypeIconOffset;
+      icon_x = progress_x + DownloadShelf::kFiletypeIconOffset;
+      icon_y = progress_y + DownloadShelf::kFiletypeIconOffset;
     }
-    icon_x = GetMirroredXWithWidthInView(icon_x, icon->width());
     if (enabled()) {
       canvas->DrawImageInt(*icon, icon_x, icon_y);
     } else {
diff --git a/chrome/browser/ui/views/download/download_item_view_md.cc b/chrome/browser/ui/views/download/download_item_view_md.cc
index fafc331..44947d5 100644
--- a/chrome/browser/ui/views/download/download_item_view_md.cc
+++ b/chrome/browser/ui/views/download/download_item_view_md.cc
@@ -72,23 +72,28 @@
 const int kDangerousTextWidth = 200;
 
 // The normal height of the item which may be exceeded if text is large.
-const int kDefaultHeight = 36;
+const int kDefaultHeight = 48;
+
+// The vertical distance between the item's visual upper bound (as delineated by
+// the separator on the right) and the edge of the shelf.
+const int kTopBottomPadding = 6;
 
 // The minimum vertical padding above and below contents of the download item.
 // This is only used when the text size is large.
-const int kMinimumVerticalPadding = 2;
+const int kMinimumVerticalPadding = 2 + kTopBottomPadding;
 
 // Vertical padding between filename and status text.
 const int kVerticalTextPadding = 1;
 
 const int kTooltipMaxWidth = 800;
 
-// Padding before the icon and at end of the item. TODO(estade): this needs to
-// be used when drawing the non-warning dialog state. Currently we just use the
-// built in padding for the progress indicator.
+// Padding before the icon and at end of the item.
 const int kStartPadding = 12;
 const int kEndPadding = 19;
 
+// Horizontal padding between progress indicator and filename/status text.
+const int kProgressTextPadding = 8;
+
 // The space between the Save and Discard buttons when prompting for a dangerous
 // download.
 const int kButtonPadding = 5;
@@ -108,6 +113,31 @@
 // downloaded item.
 const int kDisabledOnOpenDuration = 3000;
 
+// The separator is drawn as a border. It's one dp wide.
+class SeparatorBorder : public views::Border {
+ public:
+  explicit SeparatorBorder(SkColor color) : color_(color) {}
+  ~SeparatorBorder() override {}
+
+  void Paint(const views::View& view, gfx::Canvas* canvas) override {
+    int end_x = base::i18n::IsRTL() ? 0 : view.width() - 1;
+    canvas->DrawLine(gfx::Point(end_x, kTopBottomPadding),
+                     gfx::Point(end_x, view.height() - kTopBottomPadding),
+                     color_);
+  }
+
+  gfx::Insets GetInsets() const override { return gfx::Insets(0, 0, 0, 1); }
+
+  gfx::Size GetMinimumSize() const override {
+    return gfx::Size(1, 2 * kTopBottomPadding + 1);
+  }
+
+ private:
+  SkColor color_;
+
+  DISALLOW_COPY_AND_ASSIGN(SeparatorBorder);
+};
+
 }  // namespace
 
 DownloadItemViewMd::DownloadItemViewMd(DownloadItem* download_item,
@@ -323,8 +353,6 @@
   height = std::max(kDefaultHeight,
                     2 * kMinimumVerticalPadding + font_list_.GetBaseline() +
                         kVerticalTextPadding + status_font_list_.GetHeight());
-  // Then we increase the size if the progress icon doesn't fit.
-  height = std::max<int>(height, DownloadShelf::kProgressIndicatorSize);
 
   if (IsShowingWarningDialog()) {
     width = kStartPadding + warning_icon_->width() + kLabelPadding +
@@ -340,8 +368,8 @@
       width += button_size.width() + kButtonPadding;
     width += button_size.width() + kEndPadding;
   } else {
-    width = kStartPadding + DownloadShelf::kProgressIndicatorSize + kTextWidth +
-            kEndPadding;
+    width = kStartPadding + DownloadShelf::kProgressIndicatorSize +
+            kProgressTextPadding + kTextWidth + kEndPadding;
   }
   return gfx::Size(width, height);
 }
@@ -554,7 +582,9 @@
     return;
 
   int mirrored_x = GetMirroredXWithWidthInView(
-      DownloadShelf::kProgressIndicatorSize, kTextWidth);
+      kStartPadding + DownloadShelf::kProgressIndicatorSize +
+          kProgressTextPadding,
+      kTextWidth);
   int y =
       GetYForFilenameText() + font_list_.GetBaseline() + kVerticalTextPadding;
   SkColor file_name_color = SkColorSetA(
@@ -590,7 +620,9 @@
   }
 
   int mirrored_x = GetMirroredXWithWidthInView(
-      DownloadShelf::kProgressIndicatorSize, kTextWidth);
+      kStartPadding + DownloadShelf::kProgressIndicatorSize +
+          kProgressTextPadding,
+      kTextWidth);
   SkColor file_name_color =
       GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT);
 
@@ -602,7 +634,9 @@
 
 void DownloadItemViewMd::DrawIcon(gfx::Canvas* canvas) {
   if (IsShowingWarningDialog()) {
-    int icon_x = kStartPadding;
+    int icon_x = base::i18n::IsRTL()
+                     ? width() - warning_icon_->width() - kStartPadding
+                     : kStartPadding;
     int icon_y = (height() - warning_icon_->height()) / 2;
     canvas->DrawImageInt(*warning_icon_, icon_x, icon_y);
     return;
@@ -611,10 +645,12 @@
   // Paint download progress.
   DownloadItem::DownloadState state = download()->GetState();
   canvas->Save();
-  if (base::i18n::IsRTL()) {
-    canvas->Translate(
-        gfx::Vector2d(width() - DownloadShelf::kProgressIndicatorSize, 0));
-  }
+  int progress_x =
+      base::i18n::IsRTL()
+          ? width() - kStartPadding - DownloadShelf::kProgressIndicatorSize
+          : kStartPadding;
+  int progress_y = (height() - DownloadShelf::kProgressIndicatorSize) / 2;
+  canvas->Translate(gfx::Vector2d(progress_x, progress_y));
 
   if (state == DownloadItem::IN_PROGRESS) {
     base::TimeDelta progress_time = previous_progress_elapsed_;
@@ -642,10 +678,8 @@
     return;
 
   // Draw the icon image.
-  int icon_x = DownloadShelf::kFiletypeIconOffset;
-  icon_x = GetMirroredXWithWidthInView(icon_x, icon->Width());
-  int icon_y = DownloadShelf::kFiletypeIconOffset;
-
+  int icon_x = progress_x + DownloadShelf::kFiletypeIconOffset;
+  int icon_y = progress_y + DownloadShelf::kFiletypeIconOffset;
   SkPaint paint;
   // Use an alpha to make the image look disabled.
   if (!enabled())
@@ -729,9 +763,8 @@
     dangerous_download_label_->SetEnabledColor(
         GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
   }
-  SetBorder(views::Border::CreateSolidSidedBorder(
-      0, 0, 0, 1,
-      GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR)));
+  SetBorder(make_scoped_ptr(new SeparatorBorder(
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_SEPARATOR))));
 }
 
 void DownloadItemViewMd::ShowContextMenuImpl(const gfx::Rect& rect,
diff --git a/chrome/browser/ui/views/download/download_item_view_md.h b/chrome/browser/ui/views/download/download_item_view_md.h
index a16b938..03b51229 100644
--- a/chrome/browser/ui/views/download/download_item_view_md.h
+++ b/chrome/browser/ui/views/download/download_item_view_md.h
@@ -55,8 +55,7 @@
 }
 
 // The DownloadItemView in MD style. This is copied from DownloadItemView,
-// which it should eventually replace. TODO(estade): crop out all the
-// unnecessary bits like the body image sets.
+// which it should eventually replace.
 class DownloadItemViewMd : public views::ButtonListener,
                            public views::View,
                            public views::ContextMenuController,
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index 724a36e..59ae5ce7 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -29,9 +29,14 @@
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icons_public.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/background.h"
+#include "ui/views/border.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/link.h"
 #include "ui/views/mouse_watcher_view_host.h"
@@ -54,13 +59,13 @@
 
 // Padding between the show all link and close button.
 const int kCloseAndLinkPadding = 14;
+const int kCloseAndLinkPaddingMd = 6;
 
 // Padding between the download views.
 const int kDownloadPadding = 10;
 
 // Padding between the top/bottom and the content.
 const int kTopBottomPadding = 2;
-const int kTopBottomPaddingMd = 6;
 
 // Padding between the icon and 'show all downloads' link
 const int kDownloadsTitlePadding = 4;
@@ -91,13 +96,17 @@
                                                         : kRightPadding;
 }
 
+int GetCloseAndLinkPadding() {
+  return ui::MaterialDesignController::IsModeMaterial() ? kCloseAndLinkPaddingMd
+                                                        : kCloseAndLinkPadding;
+}
+
 int GetBetweenItemPadding() {
   return ui::MaterialDesignController::IsModeMaterial() ? 0 : kDownloadPadding;
 }
 
 int GetTopBottomPadding() {
-  return ui::MaterialDesignController::IsModeMaterial() ? kTopBottomPaddingMd
-                                                        : kTopBottomPadding;
+  return ui::MaterialDesignController::IsModeMaterial() ? 0 : kTopBottomPadding;
 }
 
 // Sets size->width() to view's preferred width + size->width().s
@@ -117,9 +126,11 @@
 
 DownloadShelfView::DownloadShelfView(Browser* browser, BrowserView* parent)
     : browser_(browser),
-      arrow_image_(NULL),
-      show_all_view_(NULL),
-      close_button_(NULL),
+      new_item_animation_(this),
+      shelf_animation_(this),
+      arrow_image_(nullptr),
+      show_all_view_(nullptr),
+      close_button_(nullptr),
       parent_(parent),
       mouse_watcher_(new views::MouseWatcherViewHost(this, gfx::Insets()),
                      this) {
@@ -127,6 +138,49 @@
       base::TimeDelta::FromMilliseconds(kNotifyOnExitTimeMS));
   set_id(VIEW_ID_DOWNLOAD_SHELF);
   parent->AddChildView(this);
+
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+
+  arrow_image_ = new views::ImageView();
+  AddChildView(arrow_image_);
+  close_button_ = new views::ImageButton(this);
+  close_button_->SetAccessibleName(
+      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
+  if (!ui::MaterialDesignController::IsModeMaterial()) {
+    arrow_image_->SetImage(rb.GetImageSkiaNamed(IDR_DOWNLOADS_FAVICON));
+
+    views::Link* show_all_view =
+        new views::Link(l10n_util::GetStringUTF16(IDS_SHOW_ALL_DOWNLOADS));
+    show_all_view->set_listener(this);
+    show_all_view_ = show_all_view;
+
+    close_button_->SetImage(views::CustomButton::STATE_NORMAL,
+                            rb.GetImageSkiaNamed(IDR_CLOSE_1));
+    close_button_->SetImage(views::CustomButton::STATE_HOVERED,
+                            rb.GetImageSkiaNamed(IDR_CLOSE_1_H));
+    close_button_->SetImage(views::CustomButton::STATE_PRESSED,
+                            rb.GetImageSkiaNamed(IDR_CLOSE_1_P));
+  } else {
+    views::LabelButton* show_all_view = new views::LabelButton(
+        this, l10n_util::GetStringUTF16(IDS_SHOW_ALL_DOWNLOADS_MD));
+    show_all_view->SetFocusable(true);
+    show_all_view->SetStyle(views::Button::STYLE_BUTTON);
+    show_all_view_ = show_all_view;
+
+    // TODO(estade): share this button init code with the find in page bar;
+    // also fix theming.
+    close_button_->SetBorder(views::Border::CreateEmptyBorder(4, 4, 4, 4));
+    close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
+                                     views::ImageButton::ALIGN_MIDDLE);
+    gfx::ImageSkia image = gfx::CreateVectorIcon(gfx::VectorIconId::BAR_CLOSE,
+                                                 16, gfx::kChromeIconGrey);
+    close_button_->SetImage(views::CustomButton::STATE_NORMAL, &image);
+  }
+  AddChildView(show_all_view_);
+  AddChildView(close_button_);
+
+  new_item_animation_.SetSlideDuration(kNewItemAnimationDurationMs);
+  shelf_animation_.SetSlideDuration(kShelfAnimationDurationMs);
 }
 
 DownloadShelfView::~DownloadShelfView() {
@@ -146,8 +200,8 @@
   if (download_views_.size() > kMaxDownloadViews)
     RemoveDownloadView(*download_views_.begin());
 
-  new_item_animation_->Reset();
-  new_item_animation_->Show();
+  new_item_animation_.Reset();
+  new_item_animation_.Show();
 }
 
 void DownloadShelfView::DoAddDownload(DownloadItem* download) {
@@ -177,8 +231,7 @@
 }
 
 views::View* DownloadShelfView::GetDefaultFocusableChild() {
-  return download_views_.empty() ?
-      static_cast<View*>(show_all_view_) : download_views_.back();
+  return download_views_.empty() ? show_all_view_ : download_views_.back();
 }
 
 void DownloadShelfView::OnPaintBorder(gfx::Canvas* canvas) {
@@ -195,8 +248,8 @@
 }
 
 gfx::Size DownloadShelfView::GetPreferredSize() const {
-  gfx::Size prefsize(GetEndPadding() + GetStartPadding() + kCloseAndLinkPadding,
-                     0);
+  gfx::Size prefsize(
+      GetEndPadding() + GetStartPadding() + GetCloseAndLinkPadding(), 0);
   AdjustSize(close_button_, &prefsize);
   AdjustSize(show_all_view_, &prefsize);
   // Add one download view to the preferred size.
@@ -205,33 +258,33 @@
     prefsize.Enlarge(GetBetweenItemPadding(), 0);
   }
   prefsize.Enlarge(0, 2 * GetTopBottomPadding());
-  if (shelf_animation_->is_animating()) {
-    prefsize.set_height(static_cast<int>(
-        static_cast<double>(prefsize.height()) *
-                            shelf_animation_->GetCurrentValue()));
+  if (shelf_animation_.is_animating()) {
+    prefsize.set_height(
+        static_cast<int>(static_cast<double>(prefsize.height()) *
+                         shelf_animation_.GetCurrentValue()));
   }
   return prefsize;
 }
 
-void DownloadShelfView::AnimationProgressed(const gfx::Animation *animation) {
-  if (animation == new_item_animation_.get()) {
+void DownloadShelfView::AnimationProgressed(const gfx::Animation* animation) {
+  if (animation == &new_item_animation_) {
     Layout();
     SchedulePaint();
-  } else if (animation == shelf_animation_.get()) {
+  } else if (animation == &shelf_animation_) {
     // Force a re-layout of the parent, which will call back into
     // GetPreferredSize, where we will do our animation. In the case where the
     // animation is hiding, we do a full resize - the fast resizing would
     // otherwise leave blank white areas where the shelf was and where the
     // user's eye is. Thankfully bottom-resizing is a lot faster than
     // top-resizing.
-    parent_->ToolbarSizeChanged(shelf_animation_->IsShowing());
+    parent_->ToolbarSizeChanged(shelf_animation_.IsShowing());
   }
 }
 
 void DownloadShelfView::AnimationEnded(const gfx::Animation *animation) {
-  if (animation == shelf_animation_.get()) {
-    parent_->SetDownloadShelfVisible(shelf_animation_->IsShowing());
-    if (!shelf_animation_->IsShowing())
+  if (animation == &shelf_animation_) {
+    parent_->SetDownloadShelfVisible(shelf_animation_.IsShowing());
+    if (!shelf_animation_.IsShowing())
       Closed();
   }
 }
@@ -250,7 +303,7 @@
   gfx::Size show_all_size = show_all_view_->GetPreferredSize();
   int max_download_x =
       std::max<int>(0, width() - GetEndPadding() - close_button_size.width() -
-                           kCloseAndLinkPadding - show_all_size.width() -
+                           GetCloseAndLinkPadding() - show_all_size.width() -
                            kDownloadsTitlePadding - image_size.width() -
                            GetBetweenItemPadding());
   int next_x = show_link_only ? GetStartPadding()
@@ -264,7 +317,7 @@
                             CenterPosition(show_all_size.height(), height()),
                             show_all_size.width(),
                             show_all_size.height());
-  next_x += show_all_size.width() + kCloseAndLinkPadding;
+  next_x += show_all_size.width() + GetCloseAndLinkPadding();
   // If the window is maximized, we want to expand the hitbox of the close
   // button to the right and bottom to make it easier to click.
   bool is_maximized = browser_->window()->IsMaximized();
@@ -287,9 +340,9 @@
 
     // Figure out width of item.
     int item_width = view_size.width();
-    if (new_item_animation_->is_animating() && ri == download_views_.rbegin()) {
-       item_width = static_cast<int>(static_cast<double>(view_size.width()) *
-                     new_item_animation_->GetCurrentValue());
+    if (new_item_animation_.is_animating() && ri == download_views_.rbegin()) {
+      item_width = static_cast<int>(static_cast<double>(view_size.width()) *
+                                    new_item_animation_.GetCurrentValue());
     }
 
     next_x += item_width;
@@ -308,37 +361,8 @@
 void DownloadShelfView::ViewHierarchyChanged(
     const ViewHierarchyChangedDetails& details) {
   View::ViewHierarchyChanged(details);
-
-  if (details.is_add && (details.child == this)) {
-    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-    arrow_image_ = new views::ImageView();
-    arrow_image_->SetImage(rb.GetImageSkiaNamed(IDR_DOWNLOADS_FAVICON));
-    AddChildView(arrow_image_);
-
-    show_all_view_ = new views::Link(
-        l10n_util::GetStringUTF16(IDS_SHOW_ALL_DOWNLOADS));
-    show_all_view_->set_listener(this);
-    AddChildView(show_all_view_);
-
-    close_button_ = new views::ImageButton(this);
-    close_button_->SetImage(views::CustomButton::STATE_NORMAL,
-                            rb.GetImageSkiaNamed(IDR_CLOSE_1));
-    close_button_->SetImage(views::CustomButton::STATE_HOVERED,
-                            rb.GetImageSkiaNamed(IDR_CLOSE_1_H));
-    close_button_->SetImage(views::CustomButton::STATE_PRESSED,
-                            rb.GetImageSkiaNamed(IDR_CLOSE_1_P));
-    close_button_->SetAccessibleName(
-        l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
-    AddChildView(close_button_);
-
+  if (details.is_add)
     UpdateColorsFromTheme();
-
-    new_item_animation_.reset(new gfx::SlideAnimation(this));
-    new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs);
-
-    shelf_animation_.reset(new gfx::SlideAnimation(this));
-    shelf_animation_->SetSlideDuration(kShelfAnimationDurationMs);
-  }
 }
 
 bool DownloadShelfView::CanFitFirstDownloadItem() {
@@ -353,7 +377,7 @@
   // of the shelf minus the "Show all downloads" link, arrow and close button
   // and the padding.
   int available_width = width() - GetEndPadding() - close_button_size.width() -
-                        kCloseAndLinkPadding - show_all_size.width() -
+                        GetCloseAndLinkPadding() - show_all_size.width() -
                         kDownloadsTitlePadding - image_size.width() -
                         GetBetweenItemPadding() - GetStartPadding();
   if (available_width <= 0)
@@ -365,12 +389,19 @@
 
 void DownloadShelfView::UpdateColorsFromTheme() {
   if (show_all_view_ && close_button_ && GetThemeProvider()) {
+    set_background(views::Background::CreateSolidBackground(
+        GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR)));
+
+    if (!ui::MaterialDesignController::IsModeMaterial()) {
+      views::Link* show_all_view = static_cast<views::Link*>(show_all_view_);
+      show_all_view->SetBackgroundColor(background()->get_color());
+      show_all_view->SetEnabledColor(
+          GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
+    }
+
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     set_background(views::Background::CreateSolidBackground(
         GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR)));
-    show_all_view_->SetBackgroundColor(background()->get_color());
-    show_all_view_->SetEnabledColor(
-        GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT));
     close_button_->SetBackground(
         GetThemeProvider()->GetColor(ThemeProperties::COLOR_TAB_TEXT),
         rb.GetImageSkiaNamed(IDR_CLOSE_1),
@@ -388,20 +419,25 @@
 
 void DownloadShelfView::ButtonPressed(
     views::Button* button, const ui::Event& event) {
-  Close(USER_ACTION);
+  if (button == close_button_)
+    Close(USER_ACTION);
+  else if (button == show_all_view_)
+    chrome::ShowDownloads(browser_);
+  else
+    NOTREACHED();
 }
 
 bool DownloadShelfView::IsShowing() const {
-  return visible() && shelf_animation_->IsShowing();
+  return visible() && shelf_animation_.IsShowing();
 }
 
 bool DownloadShelfView::IsClosing() const {
-  return shelf_animation_->IsClosing();
+  return shelf_animation_.IsClosing();
 }
 
 void DownloadShelfView::DoShow() {
   SetVisible(true);
-  shelf_animation_->Show();
+  shelf_animation_.Show();
 }
 
 void DownloadShelfView::DoClose(CloseReason reason) {
@@ -413,7 +449,7 @@
   RecordDownloadShelfClose(
       download_views_.size(), num_in_progress, reason == AUTOMATIC);
   parent_->SetDownloadShelfVisible(false);
-  shelf_animation_->Hide();
+  shelf_animation_.Hide();
 }
 
 Browser* DownloadShelfView::browser() const {
diff --git a/chrome/browser/ui/views/download/download_shelf_view.h b/chrome/browser/ui/views/download/download_shelf_view.h
index d4b8969..083f76a 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.h
+++ b/chrome/browser/ui/views/download/download_shelf_view.h
@@ -11,6 +11,7 @@
 #include "base/compiler_specific.h"
 #include "chrome/browser/download/download_shelf.h"
 #include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/slide_animation.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/link_listener.h"
@@ -24,10 +25,6 @@
 class PageNavigator;
 }
 
-namespace gfx {
-class SlideAnimation;
-}
-
 namespace views {
 class ImageButton;
 class ImageView;
@@ -131,21 +128,21 @@
   Browser* browser_;
 
   // The animation for adding new items to the shelf.
-  scoped_ptr<gfx::SlideAnimation> new_item_animation_;
+  gfx::SlideAnimation new_item_animation_;
 
   // The show/hide animation for the shelf itself.
-  scoped_ptr<gfx::SlideAnimation> shelf_animation_;
+  gfx::SlideAnimation shelf_animation_;
 
   // The download views. These are also child Views, and deleted when
   // the DownloadShelfView is deleted.
   std::vector<views::View*> download_views_;
 
   // An image displayed on the right of the "Show all downloads..." link.
+  // TODO(estade): not shown in MD; remove.
   views::ImageView* arrow_image_;
 
-  // Link for showing all downloads. This is contained as a child, and deleted
-  // by View.
-  views::Link* show_all_view_;
+  // Link for showing all downloads. For MD this is a system style button.
+  views::View* show_all_view_;
 
   // Button for closing the downloads. This is contained as a child, and
   // deleted by View.
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index 9e3886a18..798f060a 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/singleton_tabs.h"
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc
index 2dc7e250..4c723d5 100644
--- a/chrome/browser/ui/views/first_run_dialog.cc
+++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -51,7 +51,7 @@
   // If the metrics reporting is managed, we won't ask.
   const PrefService::Preference* metrics_reporting_pref =
       g_browser_process->local_state()->FindPreference(
-          prefs::kMetricsReportingEnabled);
+          metrics::prefs::kMetricsReportingEnabled);
 
   if (!metrics_reporting_pref ||
       !metrics_reporting_pref->IsManaged()) {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 0ac71030..1ba3f30 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1306,10 +1306,6 @@
       error_type, is_user_gesture);
 }
 
-bool BrowserView::ShowSessionCrashedBubble() {
-  return SessionCrashedBubbleView::Show(browser_.get());
-}
-
 bool BrowserView::IsProfileResetBubbleSupported() const {
   return true;
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index f30f2ac..65539dd0 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -320,7 +320,6 @@
                            translate::TranslateStep step,
                            translate::TranslateErrors::Type error_type,
                            bool is_user_gesture) override;
-  bool ShowSessionCrashedBubble() override;
   bool IsProfileResetBubbleSupported() const override;
   GlobalErrorBubbleViewBase* ShowProfileResetBubble(
       const base::WeakPtr<ProfileResetGlobalError>& global_error) override;
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 8968cb0..13087157 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -25,7 +25,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
+#include "chrome/browser/ui/browser_live_tab_context.h"
 #include "chrome/browser/ui/views/frame/browser_desktop_window_tree_host_x11.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h"
@@ -851,9 +851,8 @@
   sessions::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);
+    service->RestoreEntryById(browser_->live_tab_context(), item->session_id,
+                              browser_->host_desktop_type(), UNKNOWN);
   } else {
     DCHECK(item->url.is_valid());
     browser_->OpenURL(content::OpenURLParams(
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 b0ef71c..02c1de32 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -187,7 +187,7 @@
         IMAGE_GRID(IDR_OMNIBOX_POPUP_BORDER_AND_SHADOW);
     border_painter_.reset(
         views::Painter::CreateImageGridPainter(kOmniboxPopupBorderImages));
-  } else {
+  } else if (!ui::MaterialDesignController::IsModeMaterial()) {
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     const gfx::Insets omnibox_border_insets(14, 9, 14, 9);
     border_painter_.reset(views::Painter::CreateImagePainter(
@@ -528,11 +528,13 @@
 
 gfx::Size LocationBarView::GetPreferredSize() const {
   // Compute minimum height.
-  gfx::Size min_size(border_painter_->GetMinimumSize());
+  gfx::Size min_size;
   // For non-material the size of the asset determines the size of the
   // LocationBarView.
   if (ui::MaterialDesignController::IsModeMaterial())
     min_size.set_height(GetLayoutConstant(LOCATION_BAR_HEIGHT));
+  else
+    min_size = border_painter_->GetMinimumSize();
 
   if (!IsInitialized())
     return min_size;
@@ -1273,8 +1275,34 @@
   gfx::Rect border_rect(GetContentsBounds());
   if (is_popup_mode_ && (GetHorizontalEdgeThickness() == 0))
     border_rect.Inset(-kPopupEdgeThickness, 0);
-  views::Painter::PaintPainterAt(recorder.canvas(), border_painter_.get(),
-                                 border_rect);
+
+  if (ui::MaterialDesignController::IsModeMaterial()) {
+    gfx::Canvas* canvas = recorder.canvas();
+    const float display_scale = canvas->image_scale();
+    canvas->Save();
+    SkScalar scale_factor = 1.0f / display_scale;
+    canvas->sk_canvas()->scale(scale_factor, scale_factor);
+
+    SkPaint paint;
+    paint.setStyle(SkPaint::Style::kStroke_Style);
+    paint.setColor(SkColorSetARGB(0x40, 0x00, 0x00, 0x00));
+    paint.setStrokeWidth(1);
+    paint.setAntiAlias(true);
+
+    const float kOffset = 0.5f;
+    gfx::RectF border_rect_f(border_rect);
+    border_rect_f.Scale(display_scale);
+    gfx::InsetsF insets(kOffset, kOffset, kOffset, kOffset);
+    border_rect_f.Inset(insets);
+
+    const SkScalar kCornerRadius = SkDoubleToScalar(2.5f * display_scale);
+    canvas->sk_canvas()->drawRoundRect(gfx::RectFToSkRect(border_rect_f),
+                                       kCornerRadius, kCornerRadius, paint);
+    recorder.canvas()->Restore();
+  } else {
+    views::Painter::PaintPainterAt(recorder.canvas(), border_painter_.get(),
+                                   border_rect);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
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 b98df63..a5d1127 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -402,7 +402,7 @@
   // Our delegate.
   Delegate* delegate_;
 
-  // Object used to paint the border.
+  // Object used to paint the border. Not used for material design.
   scoped_ptr<views::Painter> border_painter_;
 
   // An icon to the left of the edit field.
diff --git a/chrome/browser/ui/views/new_task_manager_view.cc b/chrome/browser/ui/views/new_task_manager_view.cc
index fc4eeeea..7f75b7ef 100644
--- a/chrome/browser/ui/views/new_task_manager_view.cc
+++ b/chrome/browser/ui/views/new_task_manager_view.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_window.h"
 #include "chrome/browser/task_management/task_manager_observer.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/task_manager/task_manager_columns.h"
 #include "chrome/browser/ui/user_manager.h"
 #include "chrome/common/pref_names.h"
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 8f708ab..696ccbae 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -155,6 +155,10 @@
   }
 }
 
+void OmniboxPopupContentsView::OnLineSelected(size_t line) {
+  result_view_at(line)->OnSelected();
+}
+
 void OmniboxPopupContentsView::UpdatePopupAppearance() {
   if (model_->result().empty() || omnibox_view_->IsImeShowingPopup()) {
     // No matches or the IME is showing a popup window which may overlap
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
index 73d00339..b2510b9e 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -43,6 +43,7 @@
   // OmniboxPopupView:
   bool IsOpen() const override;
   void InvalidateLine(size_t line) override;
+  void OnLineSelected(size_t line) override;
   void UpdatePopupAppearance() override;
   gfx::Rect GetTargetBounds() override;
   void PaintUpdatesNow() override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index fb513d0..9a640a68 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -24,6 +24,7 @@
 #include "grit/components_scaled_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_view_state.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -291,6 +292,17 @@
   SchedulePaint();
 }
 
+void OmniboxResultView::OnSelected() {
+  DCHECK_EQ(SELECTED, GetState());
+
+  // Notify assistive technology when results with answers attached are
+  // selected. The non-answer text is already accessible as a consequence of
+  // updating the text in the omnibox but this alert and GetAccessibleState
+  // below make the answer contents accessible.
+  if (match_.answer)
+    NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
+}
+
 gfx::Size OmniboxResultView::GetPreferredSize() const {
   if (!match_.answer)
     return gfx::Size(0, GetContentLineHeight());
@@ -298,6 +310,14 @@
   return gfx::Size(0, GetContentLineHeight() + GetAnswerLineHeight());
 }
 
+void OmniboxResultView::GetAccessibleState(ui::AXViewState* state) {
+  state->name = match_.answer
+                    ? l10n_util::GetStringFUTF16(
+                          IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents,
+                          match_.answer->second_line().AccessibleText())
+                    : match_.contents;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // OmniboxResultView, protected:
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.h b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
index a7a6fc5..b79ce298 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
@@ -63,8 +63,12 @@
 
   void Invalidate();
 
+  // Invoked when this result view has been selected.
+  void OnSelected();
+
   // views::View:
   gfx::Size GetPreferredSize() const override;
+  void GetAccessibleState(ui::AXViewState* state) override;
 
   ResultViewState GetState() const;
 
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index 28a03e5..7aa16991 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc
index 5d16692..905d5ed08 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -138,7 +138,7 @@
 };
 
 // static
-bool SessionCrashedBubbleView::Show(Browser* browser) {
+bool SessionCrashedBubble::Show(Browser* browser) {
   if (!IsBubbleUIEnabled())
     return false;
 
@@ -147,8 +147,8 @@
     return true;
 
   // Observes browser removal event and will be deallocated in ShowForReal.
-  scoped_ptr<BrowserRemovalObserver> browser_observer(
-      new BrowserRemovalObserver(browser));
+  scoped_ptr<SessionCrashedBubbleView::BrowserRemovalObserver> browser_observer(
+      new SessionCrashedBubbleView::BrowserRemovalObserver(browser));
 
 // Stats collection only applies to Google Chrome builds.
 #if defined(GOOGLE_CHROME_BUILD)
@@ -179,8 +179,10 @@
 
 #if defined(GOOGLE_CHROME_BUILD)
   if (!uma_opted_in_already) {
-    offer_uma_optin = g_browser_process->local_state()->FindPreference(
-        prefs::kMetricsReportingEnabled)->IsUserModifiable();
+    offer_uma_optin =
+        g_browser_process->local_state()
+            ->FindPreference(metrics::prefs::kMetricsReportingEnabled)
+            ->IsUserModifiable();
   }
 #endif  // defined(GOOGLE_CHROME_BUILD)
 
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.h b/chrome/browser/ui/views/session_crashed_bubble_view.h
index 09086d0..6e7e5c02 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.h
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_SESSION_CRASHED_BUBBLE_VIEW_H_
 
 #include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/session_crashed_bubble.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -32,31 +33,30 @@
 // crashed. It also presents an option to enable metrics reporting, if it not
 // enabled already.
 class SessionCrashedBubbleView
-    : public views::BubbleDelegateView,
+    : public SessionCrashedBubble,
+      public views::BubbleDelegateView,
       public views::ButtonListener,
       public views::StyledLabelListener,
       public content::WebContentsObserver,
       public content::NotificationObserver,
       public TabStripModelObserver {
  public:
-  static bool Show(Browser* browser);
-
- private:
   // A helper class that listens to browser removal event.
   class BrowserRemovalObserver;
 
-  SessionCrashedBubbleView(views::View* anchor_view,
-                           Browser* browser,
-                           content::WebContents* web_contents,
-                           bool offer_uma_optin);
-  ~SessionCrashedBubbleView() override;
-
   // Creates and shows the session crashed bubble, with |uma_opted_in_already|
   // indicating whether the user has already opted-in to UMA. It will be called
   // by Show. It takes ownership of |browser_observer|.
   static void ShowForReal(scoped_ptr<BrowserRemovalObserver> browser_observer,
                           bool uma_opted_in_already);
 
+ private:
+  SessionCrashedBubbleView(views::View* anchor_view,
+                           Browser* browser,
+                           content::WebContents* web_contents,
+                           bool offer_uma_optin);
+  ~SessionCrashedBubbleView() override;
+
   // WidgetDelegateView methods.
   views::View* GetInitiallyFocusedView() override;
   base::string16 GetWindowTitle() const override;
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc
index 0b560bdb..a87eec1 100644
--- a/chrome/browser/ui/views/status_icons/status_tray_win.cc
+++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/threading/thread.h"
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
index eda8fa5..53d28f6 100644
--- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
+++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -9,6 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index d0ec616..47db562c 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_menu_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index cff8c2f5..3e142b44 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -28,6 +28,7 @@
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/controls/menu/menu_controller.h"
 #include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/mouse_constants.h"
 #include "ui/views/resources/grit/views_resources.h"
 
 using views::LabelButtonBorder;
@@ -53,7 +54,7 @@
     ToolbarActionViewController* view_controller,
     Profile* profile,
     ToolbarActionView::Delegate* delegate)
-    : MenuButton(this, base::string16(), nullptr, false),
+    : MenuButton(nullptr, base::string16(), this, false),
       view_controller_(view_controller),
       profile_(profile),
       delegate_(delegate),
@@ -117,22 +118,17 @@
   state->role = ui::AX_ROLE_BUTTON;
 }
 
-void ToolbarActionView::ButtonPressed(views::Button* sender,
-                                      const ui::Event& event) {
-  gfx::Point menu_point;
-  ui::MenuSourceType type = ui::MENU_SOURCE_NONE;
-  if (event.IsMouseEvent()) {
-    menu_point = static_cast<const ui::MouseEvent&>(event).location();
-    type = ui::MENU_SOURCE_MOUSE;
-  } else if (event.IsKeyEvent()) {
-    menu_point = GetKeyboardContextMenuLocation();
-    type = ui::MENU_SOURCE_KEYBOARD;
-  } else if (event.IsGestureEvent()) {
-    menu_point = static_cast<const ui::GestureEvent&>(event).location();
-    type = ui::MENU_SOURCE_TOUCH;
+void ToolbarActionView::OnMenuButtonClicked(views::View* sender,
+                                            const gfx::Point& point) {
+  if (!view_controller_->IsEnabled(GetCurrentWebContents())) {
+    // We should only get a button pressed event with a non-enabled action if
+    // the left-click behavior should open the menu.
+    DCHECK(view_controller_->DisabledClickOpensMenu());
+    context_menu_controller()->ShowContextMenuForView(this, point,
+                                                      ui::MENU_SOURCE_NONE);
+  } else {
+    view_controller_->ExecuteAction(true);
   }
-
-  HandleActivation(menu_point, type);
 }
 
 void ToolbarActionView::UpdateState() {
@@ -175,66 +171,15 @@
   UpdateState();
 }
 
-bool ToolbarActionView::Activate() {
-  if (!view_controller_->HasPopup(GetCurrentWebContents()))
-    return true;
-
-  // Unfortunately, we don't get any of the event points for this call. Since
-  // these are only used for showing a context menu when an action is disabled,
-  // it's not that big a deal. Fake it.
-  // TODO(devlin): This could obviously be improved.
-  HandleActivation(GetKeyboardContextMenuLocation(), ui::MENU_SOURCE_KEYBOARD);
-
-  // TODO(erikkay): Run a nested modal loop while the mouse is down to
-  // enable menu-like drag-select behavior.
-
-  // The return value of this method is returned via OnMousePressed.
-  // We need to return false here since we're handing off focus to another
-  // widget/view, and true will grab it right back and try to send events
-  // to us.
-  return false;
-}
-
 void ToolbarActionView::OnMouseEntered(const ui::MouseEvent& event) {
   delegate_->OnMouseEnteredToolbarActionView();
   views::MenuButton::OnMouseEntered(event);
 }
 
-bool ToolbarActionView::OnMousePressed(const ui::MouseEvent& event) {
-  if (!event.IsRightMouseButton()) {
-    return view_controller_->HasPopup(GetCurrentWebContents()) ?
-        MenuButton::OnMousePressed(event) : LabelButton::OnMousePressed(event);
-  }
-  return false;
-}
-
-void ToolbarActionView::OnMouseReleased(const ui::MouseEvent& event) {
-  if (view_controller_->HasPopup(GetCurrentWebContents()) || IsMenuRunning()) {
-    // TODO(erikkay) this never actually gets called (probably because of the
-    // loss of focus).
-    MenuButton::OnMouseReleased(event);
-  } else {
-    LabelButton::OnMouseReleased(event);
-  }
-}
-
-void ToolbarActionView::OnMouseExited(const ui::MouseEvent& event) {
-  if (view_controller_->HasPopup(GetCurrentWebContents()) || IsMenuRunning())
-    MenuButton::OnMouseExited(event);
-  else
-    LabelButton::OnMouseExited(event);
-}
-
-bool ToolbarActionView::OnKeyReleased(const ui::KeyEvent& event) {
-  return view_controller_->HasPopup(GetCurrentWebContents()) ?
-      MenuButton::OnKeyReleased(event) : LabelButton::OnKeyReleased(event);
-}
-
-void ToolbarActionView::OnGestureEvent(ui::GestureEvent* event) {
-  if (view_controller_->HasPopup(GetCurrentWebContents()))
-    MenuButton::OnGestureEvent(event);
-  else
-    LabelButton::OnGestureEvent(event);
+bool ToolbarActionView::ShouldEnterPushedState(const ui::Event& event) {
+  return views::MenuButton::ShouldEnterPushedState(event) &&
+         (base::TimeTicks::Now() - popup_closed_time_).InMilliseconds() >
+             views::kMinimumMsBetweenButtonClicks;
 }
 
 scoped_ptr<LabelButtonBorder> ToolbarActionView::CreateDefaultBorder() const {
@@ -244,12 +189,6 @@
   return border.Pass();
 }
 
-bool ToolbarActionView::ShouldEnterPushedState(const ui::Event& event) {
-  return view_controller_->HasPopup(GetCurrentWebContents()) ?
-      MenuButton::ShouldEnterPushedState(event) :
-      LabelButton::ShouldEnterPushedState(event);
-}
-
 gfx::ImageSkia ToolbarActionView::GetIconForTest() {
   return GetImage(views::Button::STATE_NORMAL);
 }
@@ -291,6 +230,7 @@
 }
 
 void ToolbarActionView::OnPopupClosed() {
+  popup_closed_time_ = base::TimeTicks::Now();
   pressed_lock_.reset();  // Unpress the menu button if it was pressed.
 }
 
@@ -387,16 +327,3 @@
 
   return false;
 }
-
-void ToolbarActionView::HandleActivation(const gfx::Point& menu_point,
-                                         ui::MenuSourceType source_type) {
-  if (!view_controller_->IsEnabled(GetCurrentWebContents())) {
-    // We should only get a button pressed event with a non-enabled action if
-    // the left-click behavior should open the menu.
-    DCHECK(view_controller_->DisabledClickOpensMenu());
-    context_menu_controller()->ShowContextMenuForView(
-        this, menu_point, source_type);
-  } else {
-    view_controller_->ExecuteAction(true);
-  }
-}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index bf19e1e..19db601bd 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -35,7 +35,7 @@
 // action in the BrowserActionsContainer.
 class ToolbarActionView : public views::MenuButton,
                           public ToolbarActionViewDelegateViews,
-                          public views::ButtonListener,
+                          public views::MenuButtonListener,
                           public views::ContextMenuController,
                           public content::NotificationObserver {
  public:
@@ -71,31 +71,18 @@
   // views::MenuButton:
   void GetAccessibleState(ui::AXViewState* state) override;
 
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+  // views::MenuButtonListener:
+  void OnMenuButtonClicked(views::View* sender,
+                           const gfx::Point& point) override;
 
   // content::NotificationObserver:
   void Observe(int type,
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // MenuButton behavior overrides.  These methods all default to LabelButton
-  // behavior unless this button is a popup.  In that case, it uses MenuButton
-  // behavior.  MenuButton has the notion of a child popup being shown where the
-  // button will stay in the pushed state until the "menu" (a popup in this
-  // case) is dismissed.
-  // TODO(devlin): This is a good idea, but it has some funny UI side-effects,
-  // like the fact that label buttons enter a pressed state immediately, but
-  // menu buttons only enter a pressed state on release (if they're draggable).
-  // We should probably just pick a behavior, and stick to it.
-  bool Activate() override;
-  void OnMouseEntered(const ui::MouseEvent& event) override;
-  bool OnMousePressed(const ui::MouseEvent& event) override;
-  void OnMouseReleased(const ui::MouseEvent& event) override;
-  void OnMouseExited(const ui::MouseEvent& event) override;
-  bool OnKeyReleased(const ui::KeyEvent& event) override;
-  void OnGestureEvent(ui::GestureEvent* event) override;
+  // views::MenuButton:
   scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const override;
+  void OnMouseEntered(const ui::MouseEvent& event) override;
   bool ShouldEnterPushedState(const ui::Event& event) override;
 
   // ToolbarActionViewDelegate: (public because called by others).
@@ -140,12 +127,6 @@
   // Returns true if a menu was closed, false otherwise.
   bool CloseActiveMenuIfNeeded();
 
-  // Unfortunately, due to the dual-nature of a ToolbarActionView as both a
-  // label button and a menu button, activation can happen as part of either
-  // ButtonPressed() or Activate(). Handle both in this function.
-  void HandleActivation(const gfx::Point& menu_point,
-                        ui::MenuSourceType source_type);
-
   // A lock to keep the MenuButton pressed when a menu or popup is visible.
   scoped_ptr<views::MenuButton::PressedLock> pressed_lock_;
 
@@ -172,6 +153,9 @@
   // once the current owner (this one) is done.
   base::Closure followup_context_menu_task_;
 
+  // The time the popup was last closed.
+  base::TimeTicks popup_closed_time_;
+
   content::NotificationRegistrar registrar_;
 
   base::WeakPtrFactory<ToolbarActionView> weak_factory_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
index 2aa0c99..8424ac5 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -4,6 +4,8 @@
 
 #include "base/run_loop.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/ui/extensions/extension_action_view_controller.h"
+#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h"
@@ -121,3 +123,70 @@
   // And the extension should have been activated.
   listener.WaitUntilSatisfied();
 }
+
+// Disabled on CrOS due to bounds issues.
+#if defined(OS_CHROMEOS)
+#define MAYBE_DoubleClickToolbarActionToClose DISABLED_DoubleClickToolbarActionToClose
+#else
+#define MAYBE_DoubleClickToolbarActionToClose DoubleClickToolbarActionToClose
+#endif
+// Tests that clicking on the toolbar action a second time when the action is
+// already open results in closing the popup, and doesn't re-open it.
+IN_PROC_BROWSER_TEST_F(ToolbarActionViewInteractiveUITest,
+                       MAYBE_DoubleClickToolbarActionToClose) {
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("ui").AppendASCII("browser_action_popup")));
+  base::RunLoop().RunUntilIdle();  // Ensure the extension is fully loaded.
+
+  BrowserActionsContainer* browser_actions_container =
+      BrowserView::GetBrowserViewForBrowser(browser())
+          ->toolbar()
+          ->browser_actions();
+  ToolbarActionsBar* toolbar_actions_bar =
+      browser_actions_container->toolbar_actions_bar();
+  ToolbarActionView* toolbar_action_view =
+      browser_actions_container->GetToolbarActionViewAt(0);
+
+  // When the extension is activated, it will send a message that its popup
+  // opened. Listen for the message.
+  ExtensionTestMessageListener listener("Popup opened", false);
+
+  // Click on the action, and wait for the popup to fully load.
+  EXPECT_TRUE(ui_test_utils::SendMouseMoveSync(
+      test::GetCenterInScreenCoordinates(toolbar_action_view)));
+
+  EXPECT_TRUE(ui_test_utils::SendMouseEventsSync(
+      ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP));
+  listener.WaitUntilSatisfied();
+
+  ExtensionActionViewController* view_controller =
+      static_cast<ExtensionActionViewController*>(
+          toolbar_action_view->view_controller());
+  EXPECT_EQ(view_controller, toolbar_actions_bar->popup_owner());
+  EXPECT_TRUE(view_controller->is_showing_popup());
+
+  {
+    // Click down on the action button; this should close the popup.
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+        content::NotificationService::AllSources());
+    // For reasons unbeknownst to me, SendMouseEventsSync() with only a down
+    // event will cause Windows to hang. Using SendMouseEvents() and running all
+    // pending UI tasks seems to do the trick.
+    EXPECT_TRUE(ui_controls::SendMouseEvents(ui_controls::LEFT,
+                                             ui_controls::DOWN));
+    base::RunLoop loop;
+    ui_controls::RunClosureAfterAllPendingUIEvents(loop.QuitClosure());
+    loop.Run();
+    observer.Wait();  // Wait for the popup to fully close.
+  }
+
+  EXPECT_FALSE(view_controller->is_showing_popup());
+  EXPECT_EQ(nullptr, toolbar_actions_bar->popup_owner());
+
+  // Releasing the mouse shouldn't result in the popup being shown again.
+  EXPECT_TRUE(
+      ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::UP));
+  EXPECT_FALSE(view_controller->is_showing_popup());
+  EXPECT_EQ(nullptr, toolbar_actions_bar->popup_owner());
+}
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index a1a8448..c7fbc85f 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -40,12 +40,6 @@
 
 namespace {
 
-enum DenialComboboxIndexes {
-  INDEX_NOPE = 0,
-  INDEX_NEVER_TRANSLATE_LANGUAGE = 2,
-  INDEX_NEVER_TRANSLATE_SITE = 4,
-};
-
 views::LabelButton* CreateLabelButton(views::ButtonListener* listener,
                                       const base::string16& label,
                                       int id) {
@@ -372,14 +366,15 @@
   switch (sender_id) {
     case COMBOBOX_ID_DENIAL: {
       denial_button_clicked_ = true;
-      int index = denial_combobox_->selected_index();
+      DenialComboboxIndex index =
+          static_cast<DenialComboboxIndex>(denial_combobox_->selected_index());
       switch (index) {
-        case INDEX_NOPE:
+        case DenialComboboxIndex::DONT_TRANSLATE:
           break;
-        case INDEX_NEVER_TRANSLATE_LANGUAGE:
+        case DenialComboboxIndex::NEVER_TRANSLATE_LANGUAGE:
           model_->SetNeverTranslateLanguage(true);
           break;
-        case INDEX_NEVER_TRANSLATE_SITE:
+        case DenialComboboxIndex::NEVER_TRANSLATE_SITE:
           model_->SetNeverTranslateSite(true);
           break;
         default:
@@ -426,14 +421,15 @@
   base::string16 original_language_name =
       model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
 
-  std::vector<base::string16> items;
-  items.push_back(l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY));
-  items.push_back(l10n_util::GetStringFUTF16(
-      IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
-      original_language_name));
-  items.push_back(base::string16());
-  items.push_back(l10n_util::GetStringUTF16(
-      IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
+  std::vector<base::string16> items(
+      static_cast<size_t>(DenialComboboxIndex::MENU_SIZE));
+  items[static_cast<size_t>(DenialComboboxIndex::DONT_TRANSLATE)] =
+      l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_DENY);
+  items[static_cast<size_t>(DenialComboboxIndex::NEVER_TRANSLATE_LANGUAGE)] =
+      l10n_util::GetStringFUTF16(IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
+                                 original_language_name);
+  items[static_cast<size_t>(DenialComboboxIndex::NEVER_TRANSLATE_SITE)] =
+      l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE);
 
   denial_combobox_model_.reset(new ui::SimpleComboboxModel(items));
   denial_combobox_ = new views::Combobox(denial_combobox_model_.get());
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 476aecb..5d3c189 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -42,6 +42,15 @@
                             public views::LinkListener,
                             public content::WebContentsObserver {
  public:
+  // Commands shown in the action-style combobox. The value corresponds to the
+  // position in the combobox menu. Gaps will become separators.
+  enum class DenialComboboxIndex {
+    DONT_TRANSLATE = 0,
+    NEVER_TRANSLATE_LANGUAGE = 1,
+    NEVER_TRANSLATE_SITE = 3,
+    MENU_SIZE = 4,
+  };
+
   ~TranslateBubbleView() override;
 
   // Shows the Translate bubble.
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
index ecc0eca..45be814 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
@@ -10,6 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/test/combobox_test_api.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 
@@ -155,6 +156,9 @@
     views::ViewsTestBase::TearDown();
   }
 
+  views::Combobox* denial_combobox() { return bubble_->denial_combobox_; }
+  bool denial_button_clicked() { return bubble_->denial_button_clicked_; }
+
   scoped_ptr<views::Widget> anchor_widget_;
   MockTranslateBubbleModel* mock_model_;
   TranslateBubbleView* bubble_;
@@ -168,6 +172,43 @@
   EXPECT_TRUE(mock_model_->translate_called_);
 }
 
+TEST_F(TranslateBubbleViewTest, ComboboxNope) {
+  views::test::ComboboxTestApi test_api(denial_combobox());
+  EXPECT_FALSE(denial_button_clicked());
+  EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
+
+  test_api.PerformActionAt(static_cast<int>(
+      TranslateBubbleView::DenialComboboxIndex::DONT_TRANSLATE));
+  EXPECT_TRUE(denial_button_clicked());
+  EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
+}
+
+TEST_F(TranslateBubbleViewTest, ComboboxNeverTranslateLanguage) {
+  views::test::ComboboxTestApi test_api(denial_combobox());
+  EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
+  EXPECT_FALSE(mock_model_->never_translate_language_);
+  EXPECT_FALSE(denial_button_clicked());
+
+  test_api.PerformActionAt(static_cast<int>(
+      TranslateBubbleView::DenialComboboxIndex::NEVER_TRANSLATE_LANGUAGE));
+  EXPECT_TRUE(denial_button_clicked());
+  EXPECT_TRUE(mock_model_->never_translate_language_);
+  EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
+}
+
+TEST_F(TranslateBubbleViewTest, ComboboxNeverTranslateSite) {
+  views::test::ComboboxTestApi test_api(denial_combobox());
+  EXPECT_FALSE(mock_model_->never_translate_site_);
+  EXPECT_FALSE(denial_button_clicked());
+  EXPECT_FALSE(bubble_->GetWidget()->IsClosed());
+
+  test_api.PerformActionAt(static_cast<int>(
+      TranslateBubbleView::DenialComboboxIndex::NEVER_TRANSLATE_SITE));
+  EXPECT_TRUE(denial_button_clicked());
+  EXPECT_TRUE(mock_model_->never_translate_site_);
+  EXPECT_TRUE(bubble_->GetWidget()->IsClosed());
+}
+
 TEST_F(TranslateBubbleViewTest, AdvancedLink) {
   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
             bubble_->GetViewState());
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
index f5d7232..8e9682b 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
@@ -474,35 +474,6 @@
 
 void WebsiteSettingsPopupView::SetCookieInfo(
     const CookieInfoList& cookie_info_list) {
-  site_data_content_->RemoveAllChildViews(true);
-
-  views::GridLayout* layout = new views::GridLayout(site_data_content_);
-  site_data_content_->SetLayoutManager(layout);
-
-  const int site_data_content_column = 0;
-  views::ColumnSet* column_set =
-      layout->AddColumnSet(site_data_content_column);
-  column_set->AddColumn(views::GridLayout::FILL,
-                        views::GridLayout::FILL,
-                        1,
-                        views::GridLayout::FIXED,
-                        kSiteDataIconColumnWidth,
-                        0);
-  column_set->AddPaddingColumn(0, kIconMarginLeft);
-  column_set->AddColumn(views::GridLayout::FILL,
-                        views::GridLayout::FILL,
-                        1,
-                        views::GridLayout::USE_PREF,
-                        0,
-                        0);
-  // No padding. This third column is for |third_party_label_text| (see below),
-  // and the text needs to flow naturally from the |first_party_label_text|
-  // link.
-  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
-                        views::GridLayout::USE_PREF, 0, 0);
-
-  layout->AddPaddingRow(1, 5);
-
   // |cookie_info_list| should only ever have 2 items: first- and third-party
   // cookies.
   DCHECK_EQ(cookie_info_list.size(), 2u);
@@ -520,26 +491,55 @@
     }
   }
 
-  cookie_dialog_link_ = new views::Link(first_party_label_text);
-  cookie_dialog_link_->set_listener(this);
+  if (!cookie_dialog_link_) {
+    cookie_dialog_link_ = new views::Link(first_party_label_text);
+    cookie_dialog_link_->set_listener(this);
+  } else {
+    cookie_dialog_link_->SetText(first_party_label_text);
+  }
 
-  layout->StartRow(1, site_data_content_column);
-  WebsiteSettingsUI::PermissionInfo info;
-  info.type = CONTENT_SETTINGS_TYPE_COOKIES;
-  info.setting = CONTENT_SETTING_ALLOW;
-  views::ImageView* icon = new views::ImageView();
-  const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
-  icon->SetImage(image.ToImageSkia());
-  layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
-                  views::GridLayout::CENTER);
-  layout->AddView(cookie_dialog_link_, 1, 1, views::GridLayout::CENTER,
-                  views::GridLayout::CENTER);
-  base::string16 comma = base::ASCIIToUTF16(", ");
+  views::GridLayout* layout =
+      static_cast<views::GridLayout*>(site_data_content_->GetLayoutManager());
+  if (!layout) {
+    layout = new views::GridLayout(site_data_content_);
+    site_data_content_->SetLayoutManager(layout);
 
-  layout->AddView(new views::Label(comma + third_party_label_text), 1, 1,
-                  views::GridLayout::LEADING, views::GridLayout::CENTER);
+    const int site_data_content_column = 0;
+    views::ColumnSet* column_set =
+        layout->AddColumnSet(site_data_content_column);
+    column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+                          views::GridLayout::FIXED, kSiteDataIconColumnWidth,
+                          0);
+    column_set->AddPaddingColumn(0, kIconMarginLeft);
+    column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+                          views::GridLayout::USE_PREF, 0, 0);
+    // No padding. This third column is for |third_party_label_text| (see
+    // below),
+    // and the text needs to flow naturally from the |first_party_label_text|
+    // link.
+    column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+                          views::GridLayout::USE_PREF, 0, 0);
 
-  layout->AddPaddingRow(1, 6);
+    layout->AddPaddingRow(1, 5);
+
+    layout->StartRow(1, site_data_content_column);
+    WebsiteSettingsUI::PermissionInfo info;
+    info.type = CONTENT_SETTINGS_TYPE_COOKIES;
+    info.setting = CONTENT_SETTING_ALLOW;
+    views::ImageView* icon = new views::ImageView();
+    const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
+    icon->SetImage(image.ToImageSkia());
+    layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
+                    views::GridLayout::CENTER);
+    layout->AddView(cookie_dialog_link_, 1, 1, views::GridLayout::CENTER,
+                    views::GridLayout::CENTER);
+    base::string16 comma = base::ASCIIToUTF16(", ");
+
+    layout->AddView(new views::Label(comma + third_party_label_text), 1, 1,
+                    views::GridLayout::LEADING, views::GridLayout::CENTER);
+
+    layout->AddPaddingRow(1, 6);
+  }
 
   layout->Layout(site_data_content_);
   SizeToContents();
diff --git a/chrome/browser/ui/webui/chrome_web_contents_handler.cc b/chrome/browser/ui/webui/chrome_web_contents_handler.cc
index 9b21e212..7abb9449 100644
--- a/chrome/browser/ui/webui/chrome_web_contents_handler.cc
+++ b/chrome/browser/ui/webui/chrome_web_contents_handler.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
index 260b2f6..932d7a9 100644
--- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -10,12 +10,13 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
 #include "chromeos/dbus/fake_cras_audio_client.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
 #include "content/public/browser/web_ui.h"
 #include "device/bluetooth/bluetooth_device_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
 
 namespace {
 
@@ -63,7 +64,7 @@
 namespace chromeos {
 
 class DeviceEmulatorMessageHandler::BluetoothObserver
-    : public BluetoothDeviceClient::Observer {
+    : public bluez::BluetoothDeviceClient::Observer {
  public:
   explicit BluetoothObserver(DeviceEmulatorMessageHandler* owner)
       : owner_(owner) {
@@ -179,8 +180,8 @@
 
 DeviceEmulatorMessageHandler::DeviceEmulatorMessageHandler()
     : fake_bluetooth_device_client_(
-          static_cast<chromeos::FakeBluetoothDeviceClient*>(
-              chromeos::DBusThreadManager::Get()
+          static_cast<bluez::FakeBluetoothDeviceClient*>(
+              bluez::BluezDBusManager::Get()
                   ->GetBluetoothDeviceClient())),
       fake_cras_audio_client_(static_cast<chromeos::FakeCrasAudioClient*>(
           chromeos::DBusThreadManager::Get()
@@ -208,7 +209,7 @@
   std::string path;
   CHECK(args->GetString(0, &path));
   fake_bluetooth_device_client_->RemoveDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
       dbus::ObjectPath(path));
 }
 
@@ -223,7 +224,7 @@
   // the main adapter.
   std::vector<dbus::ObjectPath> paths =
       fake_bluetooth_device_client_->GetDevicesForAdapter(
-          dbus::ObjectPath(chromeos::FakeBluetoothAdapterClient::kAdapterPath));
+          dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   base::ListValue devices;
   // Get each device's properties.
@@ -237,21 +238,21 @@
 
   base::ListValue pairing_method_options;
   pairing_method_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingMethodNone);
+      bluez::FakeBluetoothDeviceClient::kPairingMethodNone);
   pairing_method_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingMethodPinCode);
+      bluez::FakeBluetoothDeviceClient::kPairingMethodPinCode);
   pairing_method_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingMethodPassKey);
+      bluez::FakeBluetoothDeviceClient::kPairingMethodPassKey);
 
   base::ListValue pairing_action_options;
   pairing_action_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingActionDisplay);
+      bluez::FakeBluetoothDeviceClient::kPairingActionDisplay);
   pairing_action_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingActionRequest);
+      bluez::FakeBluetoothDeviceClient::kPairingActionRequest);
   pairing_action_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingActionConfirmation);
+      bluez::FakeBluetoothDeviceClient::kPairingActionConfirmation);
   pairing_action_options.AppendString(
-      FakeBluetoothDeviceClient::kPairingActionFail);
+      bluez::FakeBluetoothDeviceClient::kPairingActionFail);
 
   // Send the list of devices to the view.
   web_ui()->CallJavascriptFunction(kUpdateBluetoothInfoJSCallback,
@@ -263,7 +264,7 @@
     const base::ListValue* args) {
   // Create the device if it does not already exist.
   std::string path = CreateBluetoothDeviceFromListValue(args);
-  chromeos::FakeBluetoothDeviceClient::Properties* props =
+  bluez::FakeBluetoothDeviceClient::Properties* props =
       fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(path));
 
   // Try to pair the device with the main adapter. The device is identified
@@ -442,7 +443,7 @@
 std::string DeviceEmulatorMessageHandler::CreateBluetoothDeviceFromListValue(
     const base::ListValue* args) {
   const base::DictionaryValue* device_dict = nullptr;
-  FakeBluetoothDeviceClient::IncomingDeviceProperties props;
+  bluez::FakeBluetoothDeviceClient::IncomingDeviceProperties props;
 
   CHECK(args->GetDictionary(0, &device_dict));
   CHECK(device_dict->GetString("path", &props.device_path));
@@ -459,8 +460,7 @@
   // Create the device and store it in the FakeBluetoothDeviceClient's observed
   // list of devices.
   fake_bluetooth_device_client_->CreateDeviceWithProperties(
-      dbus::ObjectPath(chromeos::FakeBluetoothAdapterClient::kAdapterPath),
-      props);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath), props);
 
   return props.device_path;
 }
@@ -468,11 +468,11 @@
 scoped_ptr<base::DictionaryValue> DeviceEmulatorMessageHandler::GetDeviceInfo(
     const dbus::ObjectPath& object_path) {
   // Get the device's properties.
-  chromeos::FakeBluetoothDeviceClient::Properties* props =
+  bluez::FakeBluetoothDeviceClient::Properties* props =
       fake_bluetooth_device_client_->GetProperties(object_path);
   scoped_ptr<base::DictionaryValue> device(new base::DictionaryValue());
   scoped_ptr<base::ListValue> uuids(new base::ListValue);
-  chromeos::FakeBluetoothDeviceClient::SimulatedPairingOptions* options =
+  bluez::FakeBluetoothDeviceClient::SimulatedPairingOptions* options =
       fake_bluetooth_device_client_->GetPairingOptions(object_path);
 
   device->SetString("path", object_path.value());
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h
index 840111bd..882af77 100644
--- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h
+++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h
@@ -17,9 +17,12 @@
 class ObjectPath;
 }  // namespace dbus
 
+namespace bluez {
+class FakeBluetoothDeviceClient;
+}
+
 namespace chromeos {
 
-class FakeBluetoothDeviceClient;
 class FakeCrasAudioClient;
 class FakePowerManagerClient;
 
@@ -99,7 +102,7 @@
   scoped_ptr<base::DictionaryValue> GetDeviceInfo(
       const dbus::ObjectPath& object_path);
 
-  FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
+  bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
   scoped_ptr<BluetoothObserver> bluetooth_observer_;
 
   FakeCrasAudioClient* fake_cras_audio_client_;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index cca7f1d..e8500089 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/chromeos/login/screens/network_error.h"
 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
+#include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
 #include "chrome/browser/chromeos/policy/consumer_management_stage.h"
@@ -57,6 +58,8 @@
 const char kAuthIframeParentOrigin[] =
     "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/";
 
+const char kRestrictiveProxyURL[] = "https://www.google.com/generate_204";
+
 const char kGaiaSandboxUrlSwitch[] = "gaia-sandbox-url";
 const char kEndpointGen[] = "1.0";
 
@@ -77,7 +80,8 @@
 
 void UpdateAuthParams(base::DictionaryValue* params,
                       bool has_users,
-                      bool is_enrolling_consumer_management) {
+                      bool is_enrolling_consumer_management,
+                      bool is_restrictive_proxy) {
   CrosSettings* cros_settings = CrosSettings::Get();
   bool allow_new_user = true;
   cros_settings->GetBoolean(kAccountsPrefAllowNewUser, &allow_new_user);
@@ -88,7 +92,7 @@
   params->SetBoolean("guestSignin", allow_guest);
 
   // nosignup flow if new users are not allowed.
-  if (!allow_new_user)
+  if (!allow_new_user || is_restrictive_proxy)
     params->SetString("flow", "nosignup");
 
   // Allow supervised user creation only if:
@@ -176,6 +180,8 @@
 }
 
 GaiaScreenHandler::~GaiaScreenHandler() {
+  if (network_portal_detector_)
+    network_portal_detector_->RemoveObserver(this);
 }
 
 void GaiaScreenHandler::LoadGaia(const GaiaContext& context) {
@@ -208,9 +214,8 @@
                     is_enrolling_consumer_management);
   params.SetString("gapsCookie", context.gaps_cookie);
 
-  UpdateAuthParams(&params,
-                   context.has_users,
-                   is_enrolling_consumer_management);
+  UpdateAuthParams(&params, context.has_users, is_enrolling_consumer_management,
+                   IsRestrictiveProxy());
 
   if (!context.use_offline) {
     const std::string app_locale = g_browser_process->GetApplicationLocale();
@@ -300,7 +305,8 @@
 void GaiaScreenHandler::UpdateGaia(const GaiaContext& context) {
   base::DictionaryValue params;
   UpdateAuthParams(&params, context.has_users,
-                   context.is_enrolling_consumer_management);
+                   context.is_enrolling_consumer_management,
+                   IsRestrictiveProxy());
   CallJS("updateAuthExtension", params);
 }
 
@@ -401,6 +407,24 @@
   AddCallback("identifierEntered", &GaiaScreenHandler::HandleIdentifierEntered);
 }
 
+void GaiaScreenHandler::OnPortalDetectionCompleted(
+    const NetworkState* network,
+    const NetworkPortalDetector::CaptivePortalState& state) {
+  VLOG(1) << "OnPortalDetectionCompleted " << state.status;
+
+  NetworkPortalDetector::CaptivePortalStatus status = state.status;
+  if (status == captive_portal_status_)
+    return;
+
+  // Only consider online/portal status.
+  if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE ||
+      status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL) {
+    captive_portal_status_ = status;
+    LoadAuthExtension(true /* force */, true /* silent_load */,
+                      false /* offline */);
+  }
+}
+
 void GaiaScreenHandler::HandleIdentifierEntered(
     const std::string& account_identifier) {
   if (!Delegate()->IsUserWhitelisted(account_identifier))
@@ -464,6 +488,29 @@
   UpdateState(error_reason);
 }
 
+std::string GaiaScreenHandler::GetCanonicalEmail(
+    const std::string& authenticated_email,
+    const std::string& gaia_id) const {
+  const std::string sanitized_email = gaia::SanitizeEmail(authenticated_email);
+
+  const std::string canonicalized_email =
+      gaia::CanonicalizeEmail(sanitized_email);
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+  if (user_manager && !user_manager->IsKnownUser(canonicalized_email)) {
+    std::string old_canonical_email;
+    if (user_manager->GetKnownUserCanonicalEmail(gaia_id,
+                                                 &old_canonical_email)) {
+      if (old_canonical_email != canonicalized_email) {
+        LOG(WARNING) << "Existing user '" << old_canonical_email
+                     << "' authenticated by alias '" << sanitized_email << "'.";
+        return old_canonical_email;
+      }
+    }
+  }
+  // For compatibility reasons, sanitized email is used.
+  return sanitized_email;
+}
+
 void GaiaScreenHandler::HandleCompleteAuthentication(
     const std::string& gaia_id,
     const std::string& email,
@@ -478,7 +525,9 @@
   DCHECK(!gaia_id.empty());
   const std::string sanitized_email = gaia::SanitizeEmail(email);
   Delegate()->SetDisplayEmail(sanitized_email);
-  UserContext user_context(sanitized_email);
+
+  const std::string canonical_email = GetCanonicalEmail(email, gaia_id);
+  UserContext user_context(canonical_email);
   user_context.SetGaiaID(gaia_id);
   user_context.SetKey(Key(password));
   user_context.SetAuthCode(auth_code);
@@ -599,7 +648,8 @@
   DCHECK(!gaia_id.empty());
   const std::string sanitized_email = gaia::SanitizeEmail(typed_email);
   Delegate()->SetDisplayEmail(sanitized_email);
-  UserContext user_context(sanitized_email);
+  const std::string canonical_email = GetCanonicalEmail(typed_email, gaia_id);
+  UserContext user_context(canonical_email);
   user_context.SetGaiaID(gaia_id);
   user_context.SetKey(Key(password));
   user_context.SetAuthFlow(using_saml
@@ -800,6 +850,15 @@
 void GaiaScreenHandler::MaybePreloadAuthExtension() {
   VLOG(1) << "MaybePreloadAuthExtension() call.";
 
+  if (!network_portal_detector_) {
+    NetworkPortalDetectorImpl* detector = new NetworkPortalDetectorImpl(
+        g_browser_process->system_request_context(), false);
+    detector->set_portal_test_url(GURL(kRestrictiveProxyURL));
+    network_portal_detector_.reset(detector);
+    network_portal_detector_->Enable(true);
+    network_portal_detector_->AddAndFireObserver(this);
+  }
+
   // If cookies clearing was initiated or |dns_clear_task_running_| then auth
   // extension showing has already been initiated and preloading is pointless.
   if (signin_screen_handler_->ShouldLoadGaia() &&
@@ -862,4 +921,9 @@
   return signin_screen_handler_->delegate_;
 }
 
+bool GaiaScreenHandler::IsRestrictiveProxy() const {
+  return captive_portal_status_ ==
+         NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 8d493d36..fb342cbd 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/extensions/signin/scoped_gaia_auth_extension.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
+#include "chromeos/network/portal_detector/network_portal_detector.h"
 #include "net/base/net_errors.h"
 
 namespace policy {
@@ -58,7 +59,8 @@
 };
 
 // A class that handles WebUI hooks in Gaia screen.
-class GaiaScreenHandler : public BaseScreenHandler {
+class GaiaScreenHandler : public BaseScreenHandler,
+                          public NetworkPortalDetector::Observer {
  public:
   enum FrameState {
     FRAME_STATE_UNKNOWN = 0,
@@ -112,6 +114,11 @@
   // WebUIMessageHandler implementation:
   void RegisterMessages() override;
 
+  // NetworkPortalDetector::Observer implementation.
+  void OnPortalDetectionCompleted(
+      const NetworkState* network,
+      const NetworkPortalDetector::CaptivePortalState& state) override;
+
   // WebUI message handlers.
   void HandleFrameLoadingCompleted(int status);
   void HandleWebviewLoadAborted(const std::string& error_reason_str);
@@ -202,11 +209,20 @@
   void set_signin_screen_handler(SigninScreenHandler* handler) {
     signin_screen_handler_ = handler;
   }
+
+  // Are we on a restrictive proxy?
+  bool IsRestrictiveProxy() const;
+
   SigninScreenHandlerDelegate* Delegate();
 
   // Returns temporary unused device Id.
   std::string GetTemporaryDeviceId();
 
+  // Returns user canonical e-mail. Finds already used account alias, if
+  // user has already signed in.
+  std::string GetCanonicalEmail(const std::string& authenticated_email,
+                                const std::string& gaia_id) const;
+
   // Current state of Gaia frame.
   FrameState frame_state_ = FRAME_STATE_UNKNOWN;
 
@@ -258,6 +274,12 @@
   // True if Easy bootstrap is enabled.
   bool use_easy_bootstrap_ = false;
 
+  // True if proxy doesn't allow access to google.com/generate_204.
+  NetworkPortalDetector::CaptivePortalStatus captive_portal_status_ =
+      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN;
+
+  scoped_ptr<NetworkPortalDetector> network_portal_detector_;
+
   // Non-owning ptr to SigninScreenHandler instance. Should not be used
   // in dtor.
   // TODO (antrim@): GaiaScreenHandler shouldn't communicate with
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 8023002..96264dd 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
@@ -48,9 +48,10 @@
   if (!network)
     return NetworkStateInformer::OFFLINE;
 
-  if (NetworkPortalDetector::Get()->IsEnabled()) {
+  if (network_portal_detector::GetInstance()->IsEnabled()) {
     NetworkPortalDetector::CaptivePortalState state =
-        NetworkPortalDetector::Get()->GetCaptivePortalState(network->guid());
+        network_portal_detector::GetInstance()->GetCaptivePortalState(
+            network->guid());
     NetworkPortalDetector::CaptivePortalStatus status = state.status;
     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
         NetworkState::StateIsConnecting(network->connection_state())) {
@@ -96,7 +97,7 @@
     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
         this, FROM_HERE);
   }
-  NetworkPortalDetector::Get()->RemoveObserver(this);
+  network_portal_detector::GetInstance()->RemoveObserver(this);
 }
 
 void NetworkStateInformer::Init() {
@@ -104,7 +105,7 @@
   NetworkHandler::Get()->network_state_handler()->AddObserver(
       this, FROM_HERE);
 
-  NetworkPortalDetector::Get()->AddAndFireObserver(this);
+  network_portal_detector::GetInstance()->AddAndFireObserver(this);
 
   registrar_.Add(this,
                  chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
diff --git a/chrome/browser/ui/webui/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals_ui.cc
index becbe8f4..e83a27c 100644
--- a/chrome/browser/ui/webui/identity_internals_ui.cc
+++ b/chrome/browser/ui/webui/identity_internals_ui.cc
@@ -139,11 +139,17 @@
 
 void IdentityInternalsUIMessageHandler::OnTokenRevokerDone(
     IdentityInternalsTokenRevoker* token_revoker) {
+  extensions::IdentityAPI* api =
+      extensions::IdentityAPI::GetFactoryInstance()->Get(
+          Profile::FromWebUI(web_ui()));
+  // API can be null in incognito, but then we shouldn't be in this function.
+  // This case is handled because this is called from a renderer process
+  // which could conceivably be compromised.
+  CHECK(api);
+
   // Remove token from the cache.
-  extensions::IdentityAPI::GetFactoryInstance()
-      ->Get(Profile::FromWebUI(web_ui()))
-      ->EraseCachedToken(token_revoker->extension_id(),
-                         token_revoker->access_token());
+  api->EraseCachedToken(token_revoker->extension_id(),
+                        token_revoker->access_token());
 
   // Update view about the token being removed.
   base::ListValue result;
@@ -219,10 +225,13 @@
 void IdentityInternalsUIMessageHandler::GetInfoForAllTokens(
     const base::ListValue* args) {
   base::ListValue results;
-  extensions::IdentityAPI::CachedTokens tokens =
-      extensions::IdentityAPI::GetFactoryInstance()
-          ->Get(Profile::FromWebUI(web_ui()))
-          ->GetAllCachedTokens();
+  extensions::IdentityAPI::CachedTokens tokens;
+  // The API can be null in incognito.
+  extensions::IdentityAPI* api =
+      extensions::IdentityAPI::GetFactoryInstance()->Get(
+          Profile::FromWebUI(web_ui()));
+  if (api)
+    tokens = api->GetAllCachedTokens();
   for (extensions::IdentityAPI::CachedTokens::const_iterator
            iter = tokens.begin(); iter != tokens.end(); ++iter) {
     results.Append(GetInfoForToken(iter->first, iter->second));
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index f54bc34..b10ce97 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/devtools/devtools_targets_ui.h"
 #include "chrome/browser/devtools/devtools_ui_bindings.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/webui/theme_source.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 57d89df2..b85d0059 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -170,7 +170,7 @@
   if (strict_enforcement)
     options_mask |= SSLBlockingPage::STRICT_ENFORCEMENT;
   return new BadClockBlockingPage(web_contents, cert_error, ssl_info,
-                                  request_url, time_triggered_,
+                                  request_url, time_triggered_, nullptr,
                                   base::Callback<void(bool)>());
 }
 
diff --git a/chrome/browser/ui/webui/log_web_ui_url.cc b/chrome/browser/ui/webui/log_web_ui_url.cc
index 3b793a2..6f983ff 100644
--- a/chrome/browser/ui/webui/log_web_ui_url.cc
+++ b/chrome/browser/ui/webui/log_web_ui_url.cc
@@ -18,6 +18,8 @@
 
 namespace webui {
 
+const char kWebUICreatedForUrl[] = "WebUI.CreatedForUrl";
+
 bool LogWebUIUrl(const GURL& web_ui_url) {
   bool should_log = web_ui_url.SchemeIs(content::kChromeUIScheme) ||
                     web_ui_url.SchemeIs(content::kChromeDevToolsScheme);
@@ -29,7 +31,7 @@
 
   if (should_log) {
     uint32 hash = base::Hash(web_ui_url.GetOrigin().spec());
-    UMA_HISTOGRAM_SPARSE_SLOWLY("WebUI.CreatedForUrl",
+    UMA_HISTOGRAM_SPARSE_SLOWLY(kWebUICreatedForUrl,
                                 static_cast<base::HistogramBase::Sample>(hash));
   }
 
diff --git a/chrome/browser/ui/webui/log_web_ui_url.h b/chrome/browser/ui/webui/log_web_ui_url.h
index a5e5dce..5c2650a 100644
--- a/chrome/browser/ui/webui/log_web_ui_url.h
+++ b/chrome/browser/ui/webui/log_web_ui_url.h
@@ -9,6 +9,9 @@
 
 namespace webui {
 
+// Name of histogram that WebUI URLs are logged to.
+extern const char kWebUICreatedForUrl[];
+
 // Called when WebUI objects are created to get aggregate usage data (i.e. is
 // chrome://history used more than chrome://help?). Only internal (e.g.
 // chrome://) URLs are logged. Returns whether the URL was actually logged.
diff --git a/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc b/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc
new file mode 100644
index 0000000..20bed1f
--- /dev/null
+++ b/chrome/browser/ui/webui/log_web_ui_url_browsertest.cc
@@ -0,0 +1,109 @@
+// Copyright 2015 The Chromium Authors. 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/log_web_ui_url.h"
+
+#include <vector>
+
+#include "base/hash.h"
+#include "base/test/histogram_tester.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
+#include "grit/generated_resources.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
+
+using base::Bucket;
+using testing::ElementsAre;
+
+namespace webui {
+
+class LogWebUIUrlTest : public InProcessBrowserTest {
+ public:
+  LogWebUIUrlTest() {}
+  ~LogWebUIUrlTest() override {}
+
+  std::vector<Bucket> GetSamples() {
+    return histogram_tester_.GetAllSamples(webui::kWebUICreatedForUrl);
+  }
+
+ private:
+  base::HistogramTester histogram_tester_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogWebUIUrlTest);
+};
+
+IN_PROC_BROWSER_TEST_F(LogWebUIUrlTest, TestHistoryFrame) {
+  GURL history_frame_url(chrome::kChromeUIHistoryFrameURL);
+
+  ui_test_utils::NavigateToURL(browser(), history_frame_url);
+
+  uint32 history_frame_url_hash = base::Hash(history_frame_url.spec());
+  EXPECT_THAT(GetSamples(), ElementsAre(Bucket(history_frame_url_hash, 1)));
+
+  chrome::Reload(browser(), CURRENT_TAB);
+
+  EXPECT_THAT(GetSamples(), ElementsAre(Bucket(history_frame_url_hash, 2)));
+}
+
+#if defined(ENABLE_EXTENSIONS)
+IN_PROC_BROWSER_TEST_F(LogWebUIUrlTest, TestUberPage) {
+  content::WebContents* tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  base::string16 history_title = l10n_util::GetStringUTF16(IDS_HISTORY_TITLE);
+
+  {
+    content::TitleWatcher title_watcher(tab, history_title);
+    ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIHistoryURL));
+    ASSERT_EQ(history_title, title_watcher.WaitAndGetTitle());
+  }
+
+  std::string scheme(content::kChromeUIScheme);
+  GURL uber_url(scheme + "://" + chrome::kChromeUIUberHost);
+  uint32 uber_url_hash = base::Hash(uber_url.spec());
+
+  GURL history_frame_url(chrome::kChromeUIHistoryFrameURL);
+  uint32 history_frame_url_hash = base::Hash(history_frame_url.spec());
+
+  EXPECT_THAT(GetSamples(), ElementsAre(Bucket(history_frame_url_hash, 1),
+                                        Bucket(uber_url_hash, 1)));
+
+  {
+    content::TitleWatcher title_watcher(tab, history_title);
+    chrome::Reload(browser(), CURRENT_TAB);
+    ASSERT_EQ(history_title, title_watcher.WaitAndGetTitle());
+  }
+
+  EXPECT_THAT(GetSamples(), ElementsAre(Bucket(history_frame_url_hash, 2),
+                                        Bucket(uber_url_hash, 2)));
+
+  {
+    // Pretend a user clicked on "Extensions".
+    base::string16 extensions_title =
+        l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE);
+    content::TitleWatcher title_watcher(tab, extensions_title);
+    std::string javascript =
+        "uber.invokeMethodOnWindow(window, 'showPage', {pageId: 'extensions'})";
+    ASSERT_TRUE(content::ExecuteScript(tab, javascript));
+    ASSERT_EQ(extensions_title, title_watcher.WaitAndGetTitle());
+  }
+
+  GURL extensions_frame_url(chrome::kChromeUIExtensionsFrameURL);
+  uint32 extensions_frame_url_hash = base::Hash(extensions_frame_url.spec());
+
+  EXPECT_THAT(GetSamples(), ElementsAre(Bucket(extensions_frame_url_hash, 1),
+                                        Bucket(history_frame_url_hash, 2),
+                                        Bucket(uber_url_hash, 2)));
+}
+#endif
+
+}  // namespace webui
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc
index a25d8bc..5baf48d2 100644
--- a/chrome/browser/ui/webui/options/content_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -1103,7 +1103,10 @@
     patterns.push_back(pattern);
   }
 
-  std::sort(patterns.begin(), patterns.end());
+  // The patterns are shown in the UI in a reverse order defined by
+  // |ContentSettingsPattern::operator<|.
+  std::sort(
+      patterns.begin(), patterns.end(), std::greater<ContentSettingsPattern>());
 
   scoped_ptr<base::ListValue> exceptions(new base::ListValue());
   for (const ContentSettingsPattern& pattern : patterns) {
@@ -1151,8 +1154,12 @@
   for (auto& one_provider_exceptions : all_provider_exceptions)
     one_provider_exceptions = new base::ListValue();
 
-  for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
-       i != all_patterns_settings.end();
+  // |all_patterns_settings| is sorted from the lowest precedence pattern to
+  // the highest (see operator< in ContentSettingsPattern), so traverse it in
+  // reverse to show the patterns with the highest precedence (the more specific
+  // ones) on the top.
+  for (AllPatternsSettings::reverse_iterator i = all_patterns_settings.rbegin();
+       i != all_patterns_settings.rend();
        ++i) {
     const ContentSettingsPattern& primary_pattern = i->first.first;
     const OnePatternSettings& one_settings = i->second;
@@ -1207,13 +1214,21 @@
   }
 
   for (const auto& one_provider_exceptions : all_provider_exceptions) {
-    // Append the patterns in reverse order, so the ones with the highest
-    // precedence (the more specific ones) are on the top.
+    // Append |one_provider_exceptions| at the end of |exceptions|. ListValue
+    // does not support concatenation, so we must append one item at a time.
+    // Furthermore, ListValue::Remove is O(size) if we remove an item from the
+    // beginning, so we need to remove them in the reverse order.
+    ScopedVector<base::Value> reverse_helper;
     while (!one_provider_exceptions->empty()) {
       scoped_ptr<base::Value> exception;
       one_provider_exceptions->Remove(
           one_provider_exceptions->GetSize() - 1, &exception);
-      exceptions->Append(exception.release());
+      reverse_helper.push_back(exception.Pass());
+    }
+    while (!reverse_helper.empty()) {
+      ScopedVector<base::Value>::iterator back = reverse_helper.end() - 1;
+      exceptions->Append(make_scoped_ptr(*back));
+      reverse_helper.weak_erase(back);
     }
   }
 }
diff --git a/chrome/browser/ui/webui/options/sync_setup_handler.cc b/chrome/browser/ui/webui/options/sync_setup_handler.cc
index bbaa3603..8c637c6 100644
--- a/chrome/browser/ui/webui/options/sync_setup_handler.cc
+++ b/chrome/browser/ui/webui/options/sync_setup_handler.cc
@@ -29,7 +29,6 @@
 #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/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/webui/options/options_handlers_helper.h"
diff --git a/chrome/browser/ui/webui/settings/languages_handler.cc b/chrome/browser/ui/webui/settings/languages_handler.cc
index 657f109..69dd582 100644
--- a/chrome/browser/ui/webui/settings/languages_handler.cc
+++ b/chrome/browser/ui/webui/settings/languages_handler.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/values.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/web_ui.h"
 
@@ -35,6 +36,10 @@
       "setUILanguage",
       base::Bind(&LanguagesHandler::HandleSetUILanguage,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "restart",
+      base::Bind(&LanguagesHandler::HandleRestart,
+                 base::Unretained(this)));
 }
 
 void LanguagesHandler::HandleSetUILanguage(const base::ListValue* args) {
@@ -62,4 +67,12 @@
 #endif
 }
 
+void LanguagesHandler::HandleRestart(const base::ListValue* args) {
+#if defined(OS_CHROMEOS)
+  chrome::AttemptUserExit();
+#else
+  chrome::AttemptRestart();
+#endif
+}
+
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/languages_handler.h b/chrome/browser/ui/webui/settings/languages_handler.h
index 874d65f..b8e1a93 100644
--- a/chrome/browser/ui/webui/settings/languages_handler.h
+++ b/chrome/browser/ui/webui/settings/languages_handler.h
@@ -33,6 +33,9 @@
   // Changes the UI language, provided the user is allowed to do so.
   void HandleSetUILanguage(const base::ListValue* args);
 
+  // Restarts Chrome to apply a UI language change.
+  void HandleRestart(const base::ListValue* args);
+
   Profile* profile_;  // Weak pointer.
 
   DISALLOW_COPY_AND_ASSIGN(LanguagesHandler);
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 6577585f..9c59524 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -5,15 +5,21 @@
 #include "chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/google_chrome_strings.h"
 #include "chrome/grit/locale_settings.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/ui/webui/chromeos/ui_account_tweaks.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
 #endif
 
@@ -42,8 +48,10 @@
       IDS_OPTIONS_CONTROLLED_SETTING_HAS_RECOMMENDATION);
   html_source->AddLocalizedString("controlledSettingExtension",
                                   IDS_SETTINGS_CONTROLLED_SETTING_EXTENSION);
+  html_source->AddLocalizedString("learnMore", IDS_LEARN_MORE);
 }
 
+#if defined(OS_CHROMEOS)
 void AddA11yStrings(content::WebUIDataSource* html_source) {
   html_source->AddLocalizedString(
       "a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY);
@@ -84,7 +92,21 @@
       "delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG);
   html_source->AddLocalizedString(
       "onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL);
+  html_source->AddLocalizedString(
+      "a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION);
+  html_source->AddString(
+      "a11yLearnMoreUrl", chrome::kChromeAccessibilityHelpURL);
 }
+#endif
+
+#if defined(OS_CHROMEOS)
+void AddAccountUITweaksStrings(content::WebUIDataSource* html_source,
+                               Profile* profile) {
+  base::DictionaryValue localized_values;
+  chromeos::AddAccountUITweaksLocalizedValues(&localized_values, profile);
+  html_source->AddLocalizedStrings(localized_values);
+}
+#endif
 
 void AddAppearanceStrings(content::WebUIDataSource* html_source) {
   html_source->AddLocalizedString(
@@ -256,8 +278,40 @@
       "allLanguages", IDS_SETTINGS_LANGUAGES_ALL_LANGUAGES);
   html_source->AddLocalizedString(
       "enabledLanguages", IDS_SETTINGS_LANGUAGES_ENABLED_LANGUAGES);
+  html_source->AddLocalizedString(
+      "cannotBeDisplayedInThisLanguage",
+      IDS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE);
+  html_source->AddLocalizedString(
+      "isDisplayedInThisLanguage",
+      IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE);
+  html_source->AddLocalizedString(
+      "displayInThisLanguage",
+      IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE);
+  html_source->AddLocalizedString(
+      "offerToTranslateInThisLanguage",
+      IDS_OPTIONS_LANGUAGES_OFFER_TO_TRANSLATE_IN_THIS_LANGUAGE);
+  html_source->AddLocalizedString(
+      "cannotTranslateInThisLanguage",
+      IDS_OPTIONS_LANGUAGES_CANNOT_TRANSLATE_IN_THIS_LANGUAGE);
+  html_source->AddLocalizedString(
+      "restart",
+      IDS_OPTIONS_SETTINGS_LANGUAGES_RELAUNCH_BUTTON);
 }
 
+#if defined(OS_CHROMEOS)
+void AddMultiProfilesStrings(content::WebUIDataSource* html_source,
+                             Profile* profile) {
+  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+
+  const user_manager::User* user =
+      chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+  std::string primary_user_email = user_manager->GetPrimaryUser()->email();
+  html_source->AddString("primaryUserEmail", primary_user_email);
+  html_source->AddBoolean("isSecondaryUser",
+                          user && user->email() != primary_user_email);
+}
+#endif
+
 void AddOnStartupStrings(content::WebUIDataSource* html_source) {
   html_source->AddLocalizedString(
       "onStartup",
@@ -474,26 +528,34 @@
 
 namespace settings {
 
-void AddLocalizedStrings(content::WebUIDataSource* html_source) {
+void AddLocalizedStrings(content::WebUIDataSource* html_source,
+                         Profile* profile) {
   AddCommonStrings(html_source);
 
+#if defined(OS_CHROMEOS)
   AddA11yStrings(html_source);
+  AddAccountUITweaksStrings(html_source, profile);
+#endif
   AddAppearanceStrings(html_source);
   AddCertificateManagerStrings(html_source);
   AddClearBrowsingDataStrings(html_source);
-  AddDownloadsStrings(html_source);
   AddDateTimeStrings(html_source);
+  AddDownloadsStrings(html_source);
 #if defined(OS_CHROMEOS)
   AddInternetStrings(html_source);
 #endif
   AddLanguagesStrings(html_source);
+#if defined(OS_CHROMEOS)
+  AddMultiProfilesStrings(html_source, profile);
+#endif
   AddOnStartupStrings(html_source);
   AddPrivacyStrings(html_source);
-  AddSearchStrings(html_source);
   AddSearchEnginesStrings(html_source);
+  AddSearchStrings(html_source);
   AddSiteSettingsStrings(html_source);
   AddSyncStrings(html_source);
   AddUsersStrings(html_source);
+
   html_source->SetJsonPath(kLocalizedStringsFile);
 }
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h
index b9eb379e..cfa3786 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_MD_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_MD_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
 
+class Profile;
+
 namespace content {
 class WebUIDataSource;
 }
@@ -14,7 +16,8 @@
 // Adds the strings needed by the settings page to |html_source|. This function
 // causes |html_source| to expose a strings.js file from its source which
 // contains a mapping from string's name to its translated value.
-void AddLocalizedStrings(content::WebUIDataSource* html_source);
+void AddLocalizedStrings(content::WebUIDataSource* html_source,
+                         Profile* profile);
 
 }  // namespace settings
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index bd4f2af..3f01c4b 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -45,7 +45,7 @@
                                  kSettingsResources[i].value);
   }
 
-  AddLocalizedStrings(html_source);
+  AddLocalizedStrings(html_source, Profile::FromWebUI(web_ui));
   html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML);
 
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chrome/browser/ui/webui/signin/inline_login_handler.cc
index 11190a7a..5d10e93 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index 7d53c8d..5a7b0bb9 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -69,6 +69,11 @@
                             signin_metrics::HISTOGRAM_MAX);
 }
 
+// Returns true if |profile| is a system profile or created from one.
+bool IsSystemProfile(Profile* profile) {
+  return profile->GetOriginalProfile()->IsSystemProfile();
+}
+
 void RedirectToNtpOrAppsPage(content::WebContents* contents,
                              signin_metrics::Source source) {
   // Do nothing if a navigation is pending, since this call can be triggered
@@ -599,6 +604,12 @@
 void InlineLoginHandlerImpl::SetExtraInitParams(base::DictionaryValue& params) {
   params.SetString("service", "chromiumsync");
 
+  // If this was called from the user manager to reauthenticate the profile,
+  // make sure the webui is aware.
+  Profile* profile = Profile::FromWebUI(web_ui());
+  if (IsSystemProfile(profile))
+    params.SetBoolean("dontResizeNonEmbeddedPages", true);
+
   content::WebContents* contents = web_ui()->GetWebContents();
   content::WebContentsObserver::Observe(contents);
   LogHistogramValue(signin_metrics::HISTOGRAM_SHOWN);
@@ -655,7 +666,7 @@
   // find the right profile to reauthenticate.  Otherwise the profile can be
   // taken from web_ui().
   Profile* profile = Profile::FromWebUI(web_ui());
-  if (profile->GetOriginalProfile()->IsSystemProfile()) {
+  if (IsSystemProfile(profile)) {
     // Switch to the profile and finish the login.  Don't pass a handler pointer
     // since it will be destroyed before the callback runs.
     ProfileManager* manager = g_browser_process->profile_manager();
diff --git a/chrome/browser/ui/webui/signin/login_ui_service.cc b/chrome/browser/ui/webui/signin/login_ui_service.cc
index 713f62c8..2a63883 100644
--- a/chrome/browser/ui/webui/signin/login_ui_service.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_service.cc
@@ -7,7 +7,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/host_desktop.h"
diff --git a/chrome/browser/usb/web_usb_permission_provider.cc b/chrome/browser/usb/web_usb_permission_provider.cc
index f77232d..33e54597 100644
--- a/chrome/browser/usb/web_usb_permission_provider.cc
+++ b/chrome/browser/usb/web_usb_permission_provider.cc
@@ -11,10 +11,16 @@
 #include "content/public/browser/render_frame_host.h"
 #include "device/core/device_client.h"
 
+using device::usb::WebUsbDescriptorSet;
+using device::usb::WebUsbConfigurationSubsetPtr;
+using device::usb::WebUsbFunctionSubsetPtr;
+
 namespace {
 
-bool FindOriginInDescriptorSet(const device::usb::WebUsbDescriptorSet* set,
-                               const GURL& origin) {
+bool FindOriginInDescriptorSet(const WebUsbDescriptorSet* set,
+                               const GURL& origin,
+                               const uint8_t* configuration_value,
+                               const uint8_t* interface_number) {
   if (!set)
     return false;
   for (size_t i = 0; i < set->origins.size(); ++i) {
@@ -24,6 +30,9 @@
   for (size_t i = 0; i < set->configurations.size(); ++i) {
     const device::usb::WebUsbConfigurationSubsetPtr& config =
         set->configurations[i];
+    if (configuration_value &&
+        *configuration_value != config->configuration_value)
+      continue;
     for (size_t j = 0; i < config->origins.size(); ++j) {
       if (origin.spec() == config->origins[j])
         return true;
@@ -31,6 +40,10 @@
     for (size_t j = 0; j < config->functions.size(); ++j) {
       const device::usb::WebUsbFunctionSubsetPtr& function =
           config->functions[j];
+      // TODO(reillyg): Implement support for Interface Association Descriptors
+      // so that this check will match associated interfaces.
+      if (interface_number && *interface_number != function->first_interface)
+        continue;
       for (size_t k = 0; k < function->origins.size(); ++k) {
         if (origin.spec() == function->origins[k])
           return true;
@@ -54,7 +67,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(render_frame_host);
 
-  // The created object is strongly bound to (and owned by) the pipe.
+  // The created object is owned by its bindings.
   new WebUSBPermissionProvider(render_frame_host, request.Pass());
 }
 
@@ -63,8 +76,11 @@
 WebUSBPermissionProvider::WebUSBPermissionProvider(
     content::RenderFrameHost* render_frame_host,
     mojo::InterfaceRequest<PermissionProvider> request)
-    : binding_(this, request.Pass()),
-      render_frame_host_(render_frame_host) {}
+    : render_frame_host_(render_frame_host) {
+  bindings_.set_connection_error_handler(base::Bind(
+      &WebUSBPermissionProvider::OnConnectionError, base::Unretained(this)));
+  bindings_.AddBinding(this, request.Pass());
+}
 
 void WebUSBPermissionProvider::HasDevicePermission(
     mojo::Array<device::usb::DeviceInfoPtr> requested_devices,
@@ -75,10 +91,43 @@
   mojo::Array<mojo::String> allowed_guids(0);
   for (size_t i = 0; i < requested_devices.size(); ++i) {
     const device::usb::DeviceInfoPtr& device = requested_devices[i];
-    if (FindOriginInDescriptorSet(device->webusb_allowed_origins.get(),
-                                  origin) &&
+    if (FindOriginInDescriptorSet(device->webusb_allowed_origins.get(), origin,
+                                  nullptr, nullptr) &&
         EnableWebUsbOnAnyOrigin())
       allowed_guids.push_back(device->guid);
   }
   callback.Run(allowed_guids.Pass());
 }
+
+void WebUSBPermissionProvider::HasConfigurationPermission(
+    uint8_t requested_configuration_value,
+    device::usb::DeviceInfoPtr device,
+    const HasInterfacePermissionCallback& callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  callback.Run(FindOriginInDescriptorSet(
+      device->webusb_allowed_origins.get(),
+      render_frame_host_->GetLastCommittedURL().GetOrigin(),
+      &requested_configuration_value, nullptr));
+}
+
+void WebUSBPermissionProvider::HasInterfacePermission(
+    uint8_t requested_interface,
+    uint8_t configuration_value,
+    device::usb::DeviceInfoPtr device,
+    const HasInterfacePermissionCallback& callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  callback.Run(FindOriginInDescriptorSet(
+      device->webusb_allowed_origins.get(),
+      render_frame_host_->GetLastCommittedURL().GetOrigin(),
+      &configuration_value, &requested_interface));
+}
+
+void WebUSBPermissionProvider::Bind(
+    mojo::InterfaceRequest<device::usb::PermissionProvider> request) {
+  bindings_.AddBinding(this, request.Pass());
+}
+
+void WebUSBPermissionProvider::OnConnectionError() {
+  if (bindings_.empty())
+    delete this;
+}
diff --git a/chrome/browser/usb/web_usb_permission_provider.h b/chrome/browser/usb/web_usb_permission_provider.h
index e75ead2..c29329fe 100644
--- a/chrome/browser/usb/web_usb_permission_provider.h
+++ b/chrome/browser/usb/web_usb_permission_provider.h
@@ -6,9 +6,9 @@
 #define CHROME_BROWSER_USB_WEB_USB_PERMISSION_PROVIDER_H_
 
 #include "device/devices_app/usb/public/interfaces/permission_provider.mojom.h"
+#include "mojo/common/weak_binding_set.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
-#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
 
 namespace content {
 class RenderFrameHost;
@@ -30,8 +30,21 @@
   void HasDevicePermission(
       mojo::Array<device::usb::DeviceInfoPtr> requested_devices,
       const HasDevicePermissionCallback& callback) override;
+  void HasConfigurationPermission(
+      uint8_t requested_configuration,
+      device::usb::DeviceInfoPtr device,
+      const HasInterfacePermissionCallback& callback) override;
+  void HasInterfacePermission(
+      uint8_t requested_interface,
+      uint8_t configuration_value,
+      device::usb::DeviceInfoPtr device,
+      const HasInterfacePermissionCallback& callback) override;
+  void Bind(
+      mojo::InterfaceRequest<device::usb::PermissionProvider> request) override;
 
-  mojo::StrongBinding<PermissionProvider> binding_;
+  void OnConnectionError();
+
+  mojo::WeakBindingSet<PermissionProvider> bindings_;
   content::RenderFrameHost* const render_frame_host_;
 };
 
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5bd50ef..51b7015 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -407,8 +407,6 @@
       'browser/custom_handlers/protocol_handler_registry_factory.h',
       'browser/custom_handlers/register_protocol_handler_infobar_delegate.cc',
       'browser/custom_handlers/register_protocol_handler_infobar_delegate.h',
-      'browser/custom_handlers/register_protocol_handler_permission_request.cc',
-      'browser/custom_handlers/register_protocol_handler_permission_request.h',
       'browser/defaults.cc',
       'browser/defaults.h',
       'browser/dom_distiller/dom_distiller_service_factory.cc',
@@ -909,6 +907,12 @@
     # ChromeOS-sources not ending in _chromeos (which would be included in
     # other sections and filtered out for non-ChromeOS platforms.
     'chrome_browser_chromeos_sources': [
+      'browser/download/notification/download_item_notification.cc',
+      'browser/download/notification/download_item_notification.h',
+      'browser/download/notification/download_notification.cc',
+      'browser/download/notification/download_notification.h',
+      'browser/download/notification/download_notification_manager.cc',
+      'browser/download/notification/download_notification_manager.h',
       'browser/media/protected_media_identifier_infobar_delegate.cc',
       'browser/media/protected_media_identifier_infobar_delegate.h',
       'browser/media/protected_media_identifier_permission_context.cc',
@@ -1022,6 +1026,8 @@
       'browser/chrome_webusb_browser_client.h',
       'browser/component_updater/widevine_cdm_component_installer.cc',
       'browser/component_updater/widevine_cdm_component_installer.h',
+      'browser/custom_handlers/register_protocol_handler_permission_request.cc',
+      'browser/custom_handlers/register_protocol_handler_permission_request.h',
       'browser/custom_home_pages_table_model.cc',
       'browser/custom_home_pages_table_model.h',
       'browser/diagnostics/diagnostics_controller.cc',
@@ -1048,12 +1054,6 @@
       'browser/download/download_shelf.h',
       'browser/download/download_shelf_context_menu.cc',
       'browser/download/download_shelf_context_menu.h',
-      'browser/download/notification/download_item_notification.cc',
-      'browser/download/notification/download_item_notification.h',
-      'browser/download/notification/download_notification.cc',
-      'browser/download/notification/download_notification.h',
-      'browser/download/notification/download_notification_manager.cc',
-      'browser/download/notification/download_notification_manager.h',
       'browser/feedback/feedback_profile_observer.cc',
       'browser/feedback/feedback_profile_observer.h',
       'browser/feedback/show_feedback_page.cc',
@@ -1418,6 +1418,8 @@
       'browser/captive_portal/captive_portal_tab_reloader.h',
       'browser/ssl/captive_portal_blocking_page.cc',
       'browser/ssl/captive_portal_blocking_page.h',
+      'browser/ssl/captive_portal_metrics_recorder.cc',
+      'browser/ssl/captive_portal_metrics_recorder.h',
     ],
     'chrome_browser_content_settings_sources': [
       'browser/content_settings/chrome_content_settings_client.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 431728b..beabe48b 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -116,8 +116,6 @@
       'browser/ui/autofill/password_generation_popup_view.h',
       'browser/ui/autofill/popup_controller_common.cc',
       'browser/ui/autofill/popup_controller_common.h',
-      'browser/ui/blocked_content/app_modal_dialog_helper.cc',
-      'browser/ui/blocked_content/app_modal_dialog_helper.h',
       'browser/ui/blocked_content/blocked_window_params.cc',
       'browser/ui/blocked_content/blocked_window_params.h',
       'browser/ui/blocked_content/popup_blocker_tab_helper.cc',
@@ -129,8 +127,6 @@
       'browser/ui/bookmarks/bookmark_bubble_observer.h',
       'browser/ui/bookmarks/bookmark_editor.cc',
       'browser/ui/bookmarks/bookmark_editor.h',
-      'browser/ui/bookmarks/bookmark_tab_helper.cc',
-      'browser/ui/bookmarks/bookmark_tab_helper.h',
       'browser/ui/bookmarks/bookmark_utils.cc',
       'browser/ui/bookmarks/bookmark_utils.h',
       'browser/ui/bookmarks/recently_used_folders_combo_model.cc',
@@ -142,8 +138,8 @@
       'browser/ui/browser_dialogs.h',
       'browser/ui/browser_mac.cc',
       'browser/ui/browser_mac.h',
-      'browser/ui/browser_navigator.cc',
-      'browser/ui/browser_navigator.h',
+      'browser/ui/browser_navigator_params.cc',
+      'browser/ui/browser_navigator_params.h',
       'browser/ui/browser_otr_state_android.cc',
       'browser/ui/browser_ui_prefs.cc',
       'browser/ui/browser_ui_prefs.h',
@@ -231,17 +227,11 @@
       'browser/ui/search_engines/search_engine_tab_helper.h',
       'browser/ui/search_engines/template_url_table_model.cc',
       'browser/ui/search_engines/template_url_table_model.h',
-      'browser/ui/settings_window_manager.cc',
-      'browser/ui/settings_window_manager.h',
-      'browser/ui/settings_window_manager_observer.h',
+      'browser/ui/session_crashed_bubble.h',
       'browser/ui/simple_message_box.h',
       'browser/ui/simple_message_box_internal.cc',
       'browser/ui/simple_message_box_internal.h',
       'browser/ui/status_bubble.h',
-      'browser/ui/sync/browser_synced_window_delegates_getter.cc',
-      'browser/ui/sync/browser_synced_window_delegates_getter.h',
-      'browser/ui/sync/inline_login_dialog.cc',
-      'browser/ui/sync/inline_login_dialog.h',
       'browser/ui/sync/profile_signin_confirmation_helper.cc',
       'browser/ui/sync/profile_signin_confirmation_helper.h',
       'browser/ui/sync/tab_contents_synced_tab_delegate.cc',
@@ -258,16 +248,12 @@
       'browser/ui/tab_modal_confirm_dialog.h',
       'browser/ui/translate/language_combobox_model.cc',
       'browser/ui/translate/language_combobox_model.h',
-      'browser/ui/translate/translate_bubble_factory.cc',
-      'browser/ui/translate/translate_bubble_factory.h',
       'browser/ui/translate/translate_bubble_model.h',
       'browser/ui/translate/translate_bubble_model_impl.cc',
       'browser/ui/translate/translate_bubble_model_impl.h',
       'browser/ui/translate/translate_bubble_view_state_transition.cc',
       'browser/ui/translate/translate_bubble_view_state_transition.h',
       'browser/ui/uninstall_browser_prompt.h',
-      'browser/ui/user_manager.cc',
-      'browser/ui/user_manager.h',
       'browser/ui/validation_message_bubble.h',
       'browser/ui/view_ids.h',
       'browser/ui/views/platform_keys_certificate_selector_chromeos.cc',
@@ -408,8 +394,6 @@
       'browser/ui/webui/chromeos/ui_account_tweaks.h',
       'browser/ui/webui/components_ui.cc',
       'browser/ui/webui/components_ui.h',
-      'browser/ui/webui/constrained_web_dialog_delegate_base.cc',
-      'browser/ui/webui/constrained_web_dialog_delegate_base.h',
       'browser/ui/webui/constrained_web_dialog_ui.cc',
       'browser/ui/webui/constrained_web_dialog_ui.h',
       'browser/ui/webui/cookies_tree_model_util.cc',
@@ -617,6 +601,8 @@
       'browser/ui/ash/networking_config_delegate_chromeos.h',
       'browser/ui/ash/session_state_delegate_chromeos.cc',
       'browser/ui/ash/session_state_delegate_chromeos.h',
+      'browser/ui/ash/session_util.cc',
+      'browser/ui/ash/session_util.h',
       'browser/ui/ash/solid_color_user_wallpaper_delegate.cc',
       'browser/ui/ash/solid_color_user_wallpaper_delegate.h',
       'browser/ui/ash/system_tray_delegate_chromeos.cc',
@@ -728,12 +714,6 @@
       'browser/ui/webui/chromeos/emulator/device_emulator_ui.cc',
       'browser/ui/webui/chromeos/emulator/device_emulator_ui.h',
     ],
-    # Used everywhere but ChromeOS.
-    'chrome_browser_ui_non_chromeos_sources': [
-      'browser/ui/external_protocol_dialog_delegate.cc',
-      'browser/ui/external_protocol_dialog_delegate.h',
-      'browser/ui/startup/default_browser_prompt.cc',
-    ],
     # Mac sources, except when mac_views_browser==1
     'chrome_browser_ui_cocoa_sources': [
       'browser/ui/cocoa/animatable_image.h',
@@ -876,9 +856,9 @@
       'browser/ui/cocoa/browser_window_controller.mm',
       'browser/ui/cocoa/browser_window_controller_private.h',
       'browser/ui/cocoa/browser_window_controller_private.mm',
+      'browser/ui/cocoa/browser_window_factory_cocoa.mm',
       'browser/ui/cocoa/browser_window_fullscreen_transition.h',
       'browser/ui/cocoa/browser_window_fullscreen_transition.mm',
-      'browser/ui/cocoa/browser_window_factory_cocoa.mm',
       'browser/ui/cocoa/browser_window_layout.h',
       'browser/ui/cocoa/browser_window_layout.mm',
       'browser/ui/cocoa/browser_window_utils.h',
@@ -1188,6 +1168,7 @@
       'browser/ui/cocoa/rect_path_utils.mm',
       'browser/ui/cocoa/restart_browser.h',
       'browser/ui/cocoa/restart_browser.mm',
+      'browser/ui/cocoa/session_crashed_bubble.mm',
       'browser/ui/cocoa/screen_capture_notification_ui_cocoa.h',
       'browser/ui/cocoa/screen_capture_notification_ui_cocoa.mm',
       'browser/ui/cocoa/simple_message_box_mac.mm',
@@ -1298,6 +1279,9 @@
     ],
     # Files used only on desktop systems (not iOS, Android, ChromeOS).
     'chrome_browser_ui_desktop_sources': [
+      'browser/ui/startup/default_browser_prompt.cc',
+      'browser/ui/startup/default_browser_prompt.h',
+      'browser/ui/startup/default_browser_prompt_win.cc',
       'browser/ui/sync/one_click_signin_bubble_delegate.h',
       'browser/ui/sync/one_click_signin_bubble_links_delegate.cc',
       'browser/ui/sync/one_click_signin_bubble_links_delegate.h',
@@ -1495,14 +1479,20 @@
       'browser/ui/autofill/new_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/blocked_content/app_modal_dialog_helper.cc',
+      'browser/ui/blocked_content/app_modal_dialog_helper.h',
       'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.cc',
       'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate.h',
       'browser/ui/bookmarks/bookmark_context_menu_controller.cc',
       'browser/ui/bookmarks/bookmark_context_menu_controller.h',
       'browser/ui/bookmarks/bookmark_drag_drop.cc',
       'browser/ui/bookmarks/bookmark_drag_drop.h',
+      'browser/ui/bookmarks/bookmark_tab_helper.cc',
+      'browser/ui/bookmarks/bookmark_tab_helper.h',
       'browser/ui/bookmarks/bookmark_tab_helper_delegate.cc',
       'browser/ui/bookmarks/bookmark_tab_helper_delegate.h',
+      'browser/ui/bookmarks/bookmark_utils_desktop.cc',
+      'browser/ui/bookmarks/bookmark_utils_desktop.h',
       'browser/ui/bookmarks/enhanced_bookmark_key_service.cc',
       'browser/ui/bookmarks/enhanced_bookmark_key_service.h',
       'browser/ui/bookmarks/enhanced_bookmark_key_service_factory.cc',
@@ -1523,10 +1513,12 @@
       'browser/ui/browser_iterator.h',
       'browser/ui/browser_list.cc',
       'browser/ui/browser_list.h',
+      'browser/ui/browser_navigator.cc',
+      'browser/ui/browser_navigator.h',
+      'browser/ui/browser_live_tab_context.cc',
+      'browser/ui/browser_live_tab_context.h',
       'browser/ui/browser_otr_state.cc',
       'browser/ui/browser_otr_state.h',
-      'browser/ui/browser_tab_restore_service_delegate.cc',
-      'browser/ui/browser_tab_restore_service_delegate.h',
       'browser/ui/browser_tab_restorer.cc',
       'browser/ui/browser_tab_strip_model_delegate.cc',
       'browser/ui/browser_tab_strip_model_delegate.h',
@@ -1651,14 +1643,15 @@
       'browser/ui/search/search_ui.h',
       'browser/ui/search_engines/search_engine_tab_helper_delegate.cc',
       'browser/ui/search_engines/search_engine_tab_helper_delegate.h',
+      'browser/ui/settings_window_manager.cc',
+      'browser/ui/settings_window_manager.h',
+      'browser/ui/settings_window_manager_observer.h',
       'browser/ui/singleton_tabs.cc',
       'browser/ui/singleton_tabs.h',
       'browser/ui/startup/autolaunch_prompt.h',
       'browser/ui/startup/autolaunch_prompt_win.cc',
       'browser/ui/startup/bad_flags_prompt.cc',
       'browser/ui/startup/bad_flags_prompt.h',
-      'browser/ui/startup/default_browser_prompt.h',
-      'browser/ui/startup/default_browser_prompt_win.cc',
       'browser/ui/startup/google_api_keys_infobar_delegate.cc',
       'browser/ui/startup/google_api_keys_infobar_delegate.h',
       'browser/ui/startup/obsolete_system_infobar_delegate.cc',
@@ -1674,6 +1667,10 @@
       'browser/ui/startup/startup_types.h',
       'browser/ui/sync/browser_synced_window_delegate.cc',
       'browser/ui/sync/browser_synced_window_delegate.h',
+      'browser/ui/sync/browser_synced_window_delegates_getter.cc',
+      'browser/ui/sync/browser_synced_window_delegates_getter.h',
+      'browser/ui/sync/inline_login_dialog.cc',
+      'browser/ui/sync/inline_login_dialog.h',
       'browser/ui/sync/sync_promo_ui.cc',
       'browser/ui/sync/sync_promo_ui.h',
       'browser/ui/tab_contents/tab_contents_iterator.cc',
@@ -1731,10 +1728,14 @@
       'browser/ui/toolbar/wrench_menu_badge_controller.h',
       'browser/ui/toolbar/wrench_menu_model.cc',
       'browser/ui/toolbar/wrench_menu_model.h',
+      'browser/ui/translate/translate_bubble_factory.cc',
+      'browser/ui/translate/translate_bubble_factory.h',
       'browser/ui/uma_browsing_activity_observer.cc',
       'browser/ui/uma_browsing_activity_observer.h',
       'browser/ui/unload_controller.cc',
       'browser/ui/unload_controller.h',
+      'browser/ui/user_manager.cc',
+      'browser/ui/user_manager.h',
       'browser/ui/website_settings/permission_menu_model.cc',
       'browser/ui/website_settings/permission_menu_model.h',
       'browser/ui/website_settings/website_settings_infobar_delegate.cc',
@@ -1747,6 +1748,8 @@
       'browser/ui/webui/bookmarks_ui.h',
       'browser/ui/webui/chrome_web_contents_handler.cc',
       'browser/ui/webui/chrome_web_contents_handler.h',
+      'browser/ui/webui/constrained_web_dialog_delegate_base.cc',
+      'browser/ui/webui/constrained_web_dialog_delegate_base.h',
       'browser/ui/webui/copresence_ui.cc',
       'browser/ui/webui/copresence_ui.h',
       'browser/ui/webui/copresence_ui_handler.cc',
@@ -1921,9 +1924,9 @@
       'browser/ui/webui/settings/appearance_handler.cc',
       'browser/ui/webui/settings/appearance_handler.h',
       'browser/ui/webui/settings/downloads_handler.cc',
+      'browser/ui/webui/settings/downloads_handler.h',
       'browser/ui/webui/settings/languages_handler.cc',
       'browser/ui/webui/settings/languages_handler.h',
-      'browser/ui/webui/settings/downloads_handler.h',
       'browser/ui/webui/settings/md_settings_localized_strings_provider.cc',
       'browser/ui/webui/settings/md_settings_localized_strings_provider.h',
       'browser/ui/webui/settings/md_settings_ui.cc',
@@ -2024,6 +2027,8 @@
     ],
     # Views files for everywhere but ChromeOS.
     'chrome_browser_ui_views_non_chromeos_sources': [
+      'browser/ui/external_protocol_dialog_delegate.cc',
+      'browser/ui/external_protocol_dialog_delegate.h',
       'browser/ui/views/external_protocol_dialog.cc',
       'browser/ui/views/external_protocol_dialog.h',
       'browser/ui/views/frame/opaque_browser_frame_view.cc',
@@ -2394,9 +2399,9 @@
       'browser/ui/views/validation_message_bubble_delegate.h',
       'browser/ui/views/validation_message_bubble_view.cc',
       'browser/ui/views/validation_message_bubble_view.h',
+      'browser/ui/views/web_contents_modal_dialog_manager_views.cc',
       'browser/ui/views/website_settings/permissions_bubble_view.cc',
       'browser/ui/views/website_settings/permissions_bubble_view.h',
-      'browser/ui/views/web_contents_modal_dialog_manager_views.cc',
     ],
     'chrome_browser_ui_views_extensions_non_mac_sources': [
       'browser/ui/views/extensions/bookmark_app_bubble_view.cc',
@@ -2798,8 +2803,8 @@
           'sources': [
             '<@(chrome_browser_ui_non_ios_sources)',
             '<@(chrome_browser_ui_toolbar_model_sources)',
-            '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.cc',
             '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/engagement/site_engagement.mojom.cc',
+            '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.cc',
           ],
           'dependencies': [
             'chrome_web_ui_mojo_bindings.gyp:web_ui_mojo_bindings',
@@ -2833,7 +2838,6 @@
           ],
           'sources!': [
             'browser/ui/external_protocol_dialog_delegate.cc',
-            'browser/ui/startup/default_browser_prompt.cc',
           ],
           'dependencies': [
             '../net/net.gyp:net',
@@ -2887,8 +2891,6 @@
             '../ui/chromeos/ui_chromeos.gyp:ui_chromeos',
             '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_resources',
           ],
-        }, {
-          'sources': [ '<@(chrome_browser_ui_non_chromeos_sources)' ],
         }],
         ['use_cups==1', {
           'dependencies': [
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 9333890c..4fd9894 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -69,6 +69,8 @@
       'common/mac/cfbundle_blocker.mm',
       'common/mac/launchd.h',
       'common/mac/launchd.mm',
+      'common/media/media_resource_provider.cc',
+      'common/media/media_resource_provider.h',
       'common/media/webrtc_logging_message_data.cc',
       'common/media/webrtc_logging_message_data.h',
       'common/media/webrtc_logging_messages.h',
@@ -397,6 +399,7 @@
             '<(DEPTH)/components/components.gyp:visitedlink_common',
             '<(DEPTH)/extensions/extensions.gyp:extensions_common_constants',
             '<(DEPTH)/ipc/ipc.gyp:ipc',
+            '<(DEPTH)/media/media.gyp:media',
             '<(DEPTH)/third_party/re2/re2.gyp:re2',
             '<(DEPTH)/third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
           ],
@@ -410,6 +413,7 @@
             ['exclude', '^common/custom_handlers/'],
             ['exclude', '^common/extensions/'],
             ['exclude', '^common/logging_chrome\\.'],
+            ['exclude', '^common/media/media_resource_provider'],
             ['exclude', '^common/media_galleries/'],
             ['exclude', '^common/multi_process_'],
             ['exclude', '^common/profiling\\.'],
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index bd3f0b3..ec5c092 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -281,6 +281,7 @@
           'dependencies': [
             'common_net',
             '../components/components.gyp:dom_distiller_content_renderer',
+            '../media/media.gyp:media',
           ],
         }],
         ['disable_nacl!=1', {
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 2a2b16e..5d727d8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -550,6 +550,7 @@
       'browser/ui/webui/identity_internals_ui_browsertest.h',
       'browser/ui/webui/inspect_ui_browsertest.cc',
       'browser/ui/webui/interstitials/interstitial_ui_browsertest.cc',
+      'browser/ui/webui/log_web_ui_url_browsertest.cc',
       'browser/ui/webui/net_internals/net_internals_ui_browsertest.cc',
       'browser/ui/webui/net_internals/net_internals_ui_browsertest.h',
       'browser/ui/webui/ntp/new_tab_page_sync_handler_browsertest.cc',
@@ -2480,6 +2481,12 @@
           'defines': [ 'FRAME_AVATAR_BUTTON=1', ],
           'sources': [ '<@(chrome_browser_tests_views_non_cros_or_mac_sources)' ],
         }],
+        ['OS=="ios"', {
+          'sources!': [
+            # TODO(dbeam): log webui URLs on iOS and test them.
+            'browser/ui/webui/log_web_ui_url_browsertest.cc',
+          ],
+        }],
         ['OS!="android" and OS!="ios"', {
           'sources': [
             'browser/copresence/chrome_whispernet_client_browsertest.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 8540607..e7d13c6 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -202,8 +202,6 @@
       'browser/resources_util_unittest.cc',
       'browser/search/contextual_search_policy_handler_android_unittest.cc',
       'browser/search/iframe_source_unittest.cc',
-      'browser/search/instant_unittest_base.cc',
-      'browser/search/instant_unittest_base.h',
       'browser/search/thumbnail_source_unittest.cc',
       'browser/search_engines/search_provider_install_data_unittest.cc',
       'browser/service_process/service_process_control_mac_unittest.mm',
@@ -218,11 +216,13 @@
       'browser/signin/signin_manager_unittest.cc',
       'browser/signin/signin_tracker_unittest.cc',
       'browser/signin/test_signin_client_builder.cc',
+      'browser/ssl/security_state_model_unittest.cc',
       'browser/ssl/ssl_error_classification_unittest.cc',
       'browser/ssl/ssl_error_handler_unittest.cc',
       'browser/status_icons/status_icon_menu_model_unittest.cc',
       'browser/status_icons/status_icon_unittest.cc',
       'browser/status_icons/status_tray_unittest.cc',
+      'browser/storage/durable_storage_permission_context_unittest.cc',
       'browser/sync/abstract_profile_sync_service_test.cc',
       'browser/sync/abstract_profile_sync_service_test.h',
       'browser/sync/backend_migrator_unittest.cc',
@@ -275,7 +275,7 @@
       'browser/ui/autofill/test_popup_controller_common.cc',
       'browser/ui/autofill/test_popup_controller_common.h',
       'browser/ui/bookmarks/bookmark_editor_unittest.cc',
-      'browser/ui/bookmarks/bookmark_ui_utils_unittest.cc',
+      'browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc',
       'browser/ui/bookmarks/recently_used_folders_combo_model_unittest.cc',
       'browser/ui/chrome_select_file_policy_unittest.cc',
       # It is safe to list */cocoa/* files in the "common" file list
@@ -1505,6 +1505,8 @@
       'browser/profile_resetter/triggered_profile_resetter_win_unittest.cc',
       'browser/renderer_context_menu/render_view_context_menu_unittest.cc',
       'browser/search/instant_service_unittest.cc',
+      'browser/search/instant_unittest_base.cc',
+      'browser/search/instant_unittest_base.h',
       'browser/search/search_unittest.cc',
       # GCMDriverAndroid is not yet implemented.
       'browser/services/gcm/gcm_profile_service_unittest.cc',
@@ -1821,6 +1823,8 @@
         'test/base/scoped_bundle_swizzler_mac.mm',
         'test/base/scoped_testing_local_state.cc',
         'test/base/scoped_testing_local_state.h',
+        'test/base/search_test_utils.cc',
+        'test/base/search_test_utils.h',
         'test/base/test_browser_window.cc',
         'test/base/test_browser_window.h',
         'test/base/test_launcher_utils.cc',
@@ -1891,6 +1895,29 @@
             ['include', '^test/base/testing_browser_process'],
           ],
         }],
+        ['OS=="android"', {
+          'sources!': [
+            'browser/password_manager/password_manager_test_base.cc',
+            'browser/password_manager/password_manager_test_base.h',
+            'browser/sessions/session_service_test_helper.cc',
+            'browser/sessions/session_service_test_helper.h',
+            'browser/ui/exclusive_access/fullscreen_controller_state_test.cc',
+            'browser/ui/exclusive_access/fullscreen_controller_state_test.h',
+            'browser/ui/exclusive_access/fullscreen_controller_state_tests.h',
+            'browser/ui/exclusive_access/fullscreen_controller_test.cc',
+            'browser/ui/exclusive_access/fullscreen_controller_test.h',
+            'browser/ui/webui/signin/login_ui_test_utils.cc',
+            'browser/ui/webui/signin/login_ui_test_utils.h',
+            'test/base/dialog_test_browser_window.cc',
+            'test/base/dialog_test_browser_window.h',
+            'test/base/in_process_browser_test.cc',
+            'test/base/in_process_browser_test.h',
+            'test/base/test_browser_window.cc',
+            'test/base/test_browser_window.h',
+            'test/base/ui_test_utils.cc',
+            'test/base/ui_test_utils.h',
+          ],
+        }],
         ['chromeos==1', {
           'dependencies': [
             '../build/linux/system.gyp:dbus',
@@ -2618,6 +2645,7 @@
         ['OS=="android" or OS=="ios"', {
           'sources!': [
             'browser/devtools/device/webrtc/devtools_bridge_instances_request_unittest.cc',
+            'browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc',
             'browser/ui/sync/sync_promo_ui_unittest.cc',
           ],
         }, { # 'OS!="android" and OS!="ios"'
@@ -2884,10 +2912,6 @@
                   '<(PRODUCT_DIR)/unit_tests_apk/assets/natives_blob.bin',
                   '<(PRODUCT_DIR)/unit_tests_apk/assets/snapshot_blob.bin',
                 ],
-                'inputs': [
-                  '<(PRODUCT_DIR)/natives_blob.bin',
-                  '<(PRODUCT_DIR)/snapshot_blob.bin',
-                ],
               }],
             ],
           },
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index c076b710..1e7cdbe 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -107,6 +107,7 @@
       "//components/password_manager/core/common",
       "//components/signin/core/common",
       "//components/translate/content/common",
+      "//media",
       "//ipc",
       "//third_party/re2",
       "//third_party/widevine/cdm:version_h",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index b3f2d8a..4433b84d 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -266,9 +266,6 @@
 const char kDisableExtensionsHttpThrottling[] =
     "disable-extensions-http-throttling";
 
-// Comma-separated list of feature names to disable. See also kEnableFeatures.
-const char kDisableFeatures[] = "disable-features";
-
 // Disable field trial tests configured in fieldtrial_testing_config.json.
 const char kDisableFieldTrialTestingConfig[] = "disable-field-trial-config";
 
@@ -439,9 +436,6 @@
 // crbug.com/142458 .
 const char kEnableFastUnload[] = "enable-fast-unload";
 
-// Comma-separated list of feature names to enable. See also kDisableFeatures.
-const char kEnableFeatures[] = "enable-features";
-
 // Enables support for the QUIC protocol for insecure schemes (http://).
 // This is a temporary testing flag.
 const char kEnableInsecureQuic[] = "enable-insecure-quic";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 1248441..ccd0e16 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -79,7 +79,6 @@
 extern const char kDisableExtensionsFileAccessCheck[];
 extern const char kDisableExtensionsHttpThrottling[];
 extern const char kDisableExtensions[];
-extern const char kDisableFeatures[];
 extern const char kDisableFieldTrialTestingConfig[];
 extern const char kDisableJavaScriptHarmonyShipping[];
 extern const char kDisableMaterialDesignDownloads[];
@@ -129,7 +128,6 @@
 extern const char kEnableExtensionActivityLogging[];
 extern const char kEnableExtensionActivityLogTesting[];
 extern const char kEnableFastUnload[];
-extern const char kEnableFeatures[];
 extern const char kEnableInsecureQuic[];
 extern const char kEnableMaterialDesignDownloads[];
 extern const char kEnableMaterialDesignExtensions[];
diff --git a/chrome/common/extensions/api/certificate_provider.idl b/chrome/common/extensions/api/certificate_provider.idl
index 1fa9dc834..4062d04 100644
--- a/chrome/common/extensions/api/certificate_provider.idl
+++ b/chrome/common/extensions/api/certificate_provider.idl
@@ -20,7 +20,7 @@
 
     // Must be set to all hashes supported for this certificate. This extension
     // will only be asked for signatures of digests calculated with one of these
-    // hash algorithms.
+    // hash algorithms. This should be in order of decreasing hash preference.
     Hash[] supportedHashes;
   };
 
diff --git a/chrome/common/extensions/api/easy_unlock_private.idl b/chrome/common/extensions/api/easy_unlock_private.idl
index 1b1b9ce9..0359bd8 100644
--- a/chrome/common/extensions/api/easy_unlock_private.idl
+++ b/chrome/common/extensions/api/easy_unlock_private.idl
@@ -246,6 +246,12 @@
   // |status|: The status of the connection with |connection_id|.
   callback SetupConnectionStatusCallback = void(ConnectionStatus status);
 
+  // Callback for the |setupConnectionGetDeviceAddress()| method.
+  // |deviceAddress|: The bluetooth address of the connection with 
+  // |connectionId|.
+  callback SetupConnectionGetDeviceAddressCallback = void(
+      DOMString deviceAddress);
+
   interface Functions {
     // Gets localized strings required to render the API.
     //
@@ -420,6 +426,10 @@
     static void setupConnectionSend(long connectionId,
                                     ArrayBuffer data,
                                     optional EmptyCallback callback);
+
+    // Gets the Bluetooth address of the connection with |connectionId|
+    static void setupConnectionGetDeviceAddress(long connectionId,
+        SetupConnectionGetDeviceAddressCallback callback);
   };
 
   interface Events {
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/app.js b/chrome/common/extensions/docs/examples/api/desktopCapture/app.js
index 70b492a1..6445baf 100644
--- a/chrome/common/extensions/docs/examples/api/desktopCapture/app.js
+++ b/chrome/common/extensions/docs/examples/api/desktopCapture/app.js
@@ -19,10 +19,15 @@
     console.log("Access rejected.");
     return;
   }
+
   navigator.webkitGetUserMedia({
-      audio:false,
-      video: { mandatory: { chromeMediaSource: "desktop",
-                            chromeMediaSourceId: id } }
+    audio:false,
+    video: {
+      mandatory: {
+        chromeMediaSource: "desktop",
+        chromeMediaSourceId: id,
+        maxWidth:screen.width,
+        maxHeight:screen.height} }
   }, gotStream, getUserMediaError);
 }
 
diff --git a/chrome/common/extensions/docs/templates/articles/getstarted_arc.html b/chrome/common/extensions/docs/templates/articles/getstarted_arc.html
index 15b77f09..90f7528 100644
--- a/chrome/common/extensions/docs/templates/articles/getstarted_arc.html
+++ b/chrome/common/extensions/docs/templates/articles/getstarted_arc.html
@@ -11,7 +11,15 @@
 To test your app, you need three things:
 <ol>
   <li> Your APK. </li>
-  <li> PC, Mac, Linux, or Chromebook on Chrome Version 41+. </li>
+  <li> PC, Mac, Linux, or Chromebook on Chrome Version 41+.
+  <ul>
+    <li>
+      Note: ARC is no longer supported on 32-bit x86 platforms and those
+      platforms will no longer receive updates after October 13, 2015. All ARM
+      platforms will continue to work and receive updates.
+    </li>
+  </ul>
+  </li>
   <li> <a href="http://goo.gl/gAn0Xh">The ARC Welder app</a>. </li>
 </ol>
 </p>
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
index 675254b1..4561243 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
@@ -91,15 +91,15 @@
 }
 
 bool ChromePermissionMessageProvider::IsPrivilegeIncrease(
-    const PermissionSet* old_permissions,
-    const PermissionSet* new_permissions,
+    const PermissionSet& old_permissions,
+    const PermissionSet& new_permissions,
     Manifest::Type extension_type) const {
   // Things can't get worse than native code access.
-  if (old_permissions->HasEffectiveFullAccess())
+  if (old_permissions.HasEffectiveFullAccess())
     return false;
 
   // Otherwise, it's a privilege increase if the new one has full access.
-  if (new_permissions->HasEffectiveFullAccess())
+  if (new_permissions.HasEffectiveFullAccess())
     return true;
 
   if (IsHostPrivilegeIncrease(old_permissions, new_permissions, extension_type))
@@ -112,7 +112,7 @@
 }
 
 PermissionIDSet ChromePermissionMessageProvider::GetAllPermissionIDs(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type) const {
   PermissionIDSet permission_ids;
   AddAPIPermissions(permissions, &permission_ids);
@@ -122,9 +122,9 @@
 }
 
 void ChromePermissionMessageProvider::AddAPIPermissions(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     PermissionIDSet* permission_ids) const {
-  for (const APIPermission* permission : permissions->apis())
+  for (const APIPermission* permission : permissions.apis())
     permission_ids->InsertAll(permission->GetPermissions());
 
   // A special hack: The warning message for declarativeWebRequest
@@ -136,19 +136,19 @@
   // "<all_urls>" (aka APIPermission::kHostsAll), such as kTab. This would
   // happen automatically if we didn't differentiate between API/Manifest/Host
   // permissions here.
-  if (permissions->ShouldWarnAllHosts())
+  if (permissions.ShouldWarnAllHosts())
     permission_ids->erase(APIPermission::kDeclarativeWebRequest);
 }
 
 void ChromePermissionMessageProvider::AddManifestPermissions(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     PermissionIDSet* permission_ids) const {
-  for (const ManifestPermission* p : permissions->manifest_permissions())
+  for (const ManifestPermission* p : permissions.manifest_permissions())
     permission_ids->InsertAll(p->GetPermissions());
 }
 
 void ChromePermissionMessageProvider::AddHostPermissions(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     PermissionIDSet* permission_ids,
     Manifest::Type extension_type) const {
   // Since platform apps always use isolated storage, they can't (silently)
@@ -158,12 +158,12 @@
   if (extension_type == Manifest::TYPE_PLATFORM_APP)
     return;
 
-  if (permissions->ShouldWarnAllHosts()) {
+  if (permissions.ShouldWarnAllHosts()) {
     permission_ids->insert(APIPermission::kHostsAll);
   } else {
     URLPatternSet regular_hosts;
     ExtensionsClient::Get()->FilterHostPermissions(
-        permissions->effective_hosts(), &regular_hosts, permission_ids);
+        permissions.effective_hosts(), &regular_hosts, permission_ids);
 
     std::set<std::string> hosts =
         permission_message_util::GetDistinctHosts(regular_hosts, true, true);
@@ -175,8 +175,8 @@
 }
 
 bool ChromePermissionMessageProvider::IsAPIOrManifestPrivilegeIncrease(
-    const PermissionSet* old_permissions,
-    const PermissionSet* new_permissions) const {
+    const PermissionSet& old_permissions,
+    const PermissionSet& new_permissions) const {
   PermissionIDSet old_ids;
   AddAPIPermissions(old_permissions, &old_ids);
   AddManifestPermissions(old_permissions, &old_ids);
@@ -217,8 +217,8 @@
 }
 
 bool ChromePermissionMessageProvider::IsHostPrivilegeIncrease(
-    const PermissionSet* old_permissions,
-    const PermissionSet* new_permissions,
+    const PermissionSet& old_permissions,
+    const PermissionSet& new_permissions,
     Manifest::Type extension_type) const {
   // Platform apps host permission changes do not count as privilege increases.
   // Note: this must remain consistent with AddHostPermissions.
@@ -226,16 +226,16 @@
     return false;
 
   // If the old permission set can access any host, then it can't be elevated.
-  if (old_permissions->HasEffectiveAccessToAllHosts())
+  if (old_permissions.HasEffectiveAccessToAllHosts())
     return false;
 
   // Likewise, if the new permission set has full host access, then it must be
   // a privilege increase.
-  if (new_permissions->HasEffectiveAccessToAllHosts())
+  if (new_permissions.HasEffectiveAccessToAllHosts())
     return true;
 
-  const URLPatternSet& old_list = old_permissions->effective_hosts();
-  const URLPatternSet& new_list = new_permissions->effective_hosts();
+  const URLPatternSet& old_list = old_permissions.effective_hosts();
+  const URLPatternSet& new_list = new_permissions.effective_hosts();
 
   // TODO(jstritar): This is overly conservative with respect to subdomains.
   // For example, going from *.google.com to www.google.com will be
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.h b/chrome/common/extensions/permissions/chrome_permission_message_provider.h
index ff63cc5f..9a86c8c5 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider.h
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.h
@@ -27,39 +27,38 @@
   // PermissionMessageProvider implementation.
   PermissionMessages GetPermissionMessages(
       const PermissionIDSet& permissions) const override;
-  bool IsPrivilegeIncrease(const PermissionSet* old_permissions,
-                           const PermissionSet* new_permissions,
+  bool IsPrivilegeIncrease(const PermissionSet& old_permissions,
+                           const PermissionSet& new_permissions,
                            Manifest::Type extension_type) const override;
   PermissionIDSet GetAllPermissionIDs(
-      const PermissionSet* permissions,
+      const PermissionSet& permissions,
       Manifest::Type extension_type) const override;
 
  private:
   // Adds any permission IDs from API permissions to |permission_ids|.
-  void AddAPIPermissions(const PermissionSet* permissions,
+  void AddAPIPermissions(const PermissionSet& permissions,
                          PermissionIDSet* permission_ids) const;
 
   // Adds any permission IDs from manifest permissions to |permission_ids|.
-  void AddManifestPermissions(const PermissionSet* permissions,
+  void AddManifestPermissions(const PermissionSet& permissions,
                               PermissionIDSet* permission_ids) const;
 
   // Adds any permission IDs from host permissions to |permission_ids|.
-  void AddHostPermissions(const PermissionSet* permissions,
+  void AddHostPermissions(const PermissionSet& permissions,
                           PermissionIDSet* permission_ids,
                           Manifest::Type extension_type) const;
 
   // Returns true if |new_permissions| has an elevated API or manifest privilege
   // level compared to |old_permissions|.
   bool IsAPIOrManifestPrivilegeIncrease(
-      const PermissionSet* old_permissions,
-      const PermissionSet* new_permissions) const;
+      const PermissionSet& old_permissions,
+      const PermissionSet& new_permissions) const;
 
   // Returns true if |new_permissions| has more host permissions compared to
   // |old_permissions|.
-  bool IsHostPrivilegeIncrease(
-      const PermissionSet* old_permissions,
-      const PermissionSet* new_permissions,
-      Manifest::Type extension_type) const;
+  bool IsHostPrivilegeIncrease(const PermissionSet& old_permissions,
+                               const PermissionSet& new_permissions,
+                               Manifest::Type extension_type) const;
 
   DISALLOW_COPY_AND_ASSIGN(ChromePermissionMessageProvider);
 };
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
index 815cfc5..c1a39b2 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
@@ -35,20 +35,21 @@
  protected:
   PermissionMessages GetMessages(const APIPermissionSet& permissions,
                                  Manifest::Type type) {
-    PermissionSet permission_set(permissions, ManifestPermissionSet(),
-                                 URLPatternSet(), URLPatternSet());
     return message_provider_->GetPermissionMessages(
-        message_provider_->GetAllPermissionIDs(&permission_set, type));
+        message_provider_->GetAllPermissionIDs(
+            PermissionSet(permissions, ManifestPermissionSet(), URLPatternSet(),
+                          URLPatternSet()),
+            type));
   }
 
   bool IsPrivilegeIncrease(const APIPermissionSet& old_permissions,
                            const APIPermissionSet& new_permissions) {
-    PermissionSet old_set(old_permissions, ManifestPermissionSet(),
-                          URLPatternSet(), URLPatternSet());
-    PermissionSet new_set(new_permissions, ManifestPermissionSet(),
-                          URLPatternSet(), URLPatternSet());
-    return message_provider_->IsPrivilegeIncrease(&old_set, &new_set,
-                                                  Manifest::TYPE_EXTENSION);
+    return message_provider_->IsPrivilegeIncrease(
+        PermissionSet(old_permissions, ManifestPermissionSet(), URLPatternSet(),
+                      URLPatternSet()),
+        PermissionSet(new_permissions, ManifestPermissionSet(), URLPatternSet(),
+                      URLPatternSet()),
+        Manifest::TYPE_EXTENSION);
   }
 
  private:
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index c09505e..520bbb0 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -90,7 +90,7 @@
 // Check that the given |permissions| produce a single warning message,
 // identified by the set of |expected_ids|.
 testing::AssertionResult PermissionSetProducesMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const PermissionIDSet& expected_ids) {
   const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
@@ -187,83 +187,113 @@
 }
 
 TEST(PermissionsTest, EffectiveHostPermissions) {
-  scoped_refptr<Extension> extension;
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "empty.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_EQ(0u, extension->permissions_data()
+                      ->GetEffectiveHostPermissions()
+                      .patterns()
+                      .size());
+    EXPECT_FALSE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions", "empty.json");
-  const PermissionSet* permissions =
-      extension->permissions_data()->active_permissions();
-  EXPECT_EQ(0u,
-            extension->permissions_data()
-                ->GetEffectiveHostPermissions()
-                .patterns()
-                .size());
-  EXPECT_FALSE(
-      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "one_host.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_FALSE(
+        permissions.HasEffectiveAccessToURL(GURL("https://www.google.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions", "one_host.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://www.google.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(
-      GURL("https://www.google.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "one_host_wildcard.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("http://google.com")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://foo.google.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions",
-                           "one_host_wildcard.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://foo.google.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "two_hosts.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.reddit.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions", "two_hosts.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://www.google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://www.reddit.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "https_not_considered.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("http://google.com")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("https://google.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions",
-                           "https_not_considered.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://google.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "two_content_scripts.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("http://google.com")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.reddit.com")));
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(
+        GURL("http://news.ycombinator.com")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions",
-                           "two_content_scripts.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://www.reddit.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(
-      GURL("http://news.ycombinator.com")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "all_hosts.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("http://test/")));
+    EXPECT_FALSE(permissions.HasEffectiveAccessToURL(GURL("https://test/")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_TRUE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions", "all_hosts.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
-  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
-  EXPECT_TRUE(
-      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "all_hosts2.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("http://test/")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_TRUE(permissions.HasEffectiveAccessToAllHosts());
+  }
 
-  extension = LoadManifest("effective_host_permissions", "all_hosts2.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
-  EXPECT_TRUE(
-      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
-
-  extension = LoadManifest("effective_host_permissions", "all_hosts3.json");
-  permissions = extension->permissions_data()->active_permissions();
-  EXPECT_FALSE(permissions->HasEffectiveAccessToURL(GURL("http://test/")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToURL(GURL("https://test/")));
-  EXPECT_TRUE(
-      permissions->HasEffectiveAccessToURL(GURL("http://www.google.com")));
-  EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
+  {
+    scoped_refptr<const Extension> extension =
+        LoadManifest("effective_host_permissions", "all_hosts3.json");
+    const PermissionSet& permissions =
+        extension->permissions_data()->active_permissions();
+    EXPECT_FALSE(permissions.HasEffectiveAccessToURL(GURL("http://test/")));
+    EXPECT_TRUE(permissions.HasEffectiveAccessToURL(GURL("https://test/")));
+    EXPECT_TRUE(
+        permissions.HasEffectiveAccessToURL(GURL("http://www.google.com")));
+    EXPECT_TRUE(permissions.HasEffectiveAccessToAllHosts());
+  }
 }
 
 TEST(PermissionsTest, ExplicitAccessToOrigin) {
@@ -339,12 +369,12 @@
   set2.reset(new PermissionSet(apis2, manifest_permissions, explicit_hosts2,
                                scriptable_hosts2));
   union_set = PermissionSet::CreateUnion(*set1, *set2);
-  EXPECT_TRUE(set1->Contains(*set2.get()));
+  EXPECT_TRUE(set1->Contains(*set2));
   EXPECT_TRUE(set1->Contains(*union_set.get()));
-  EXPECT_FALSE(set2->Contains(*set1.get()));
+  EXPECT_FALSE(set2->Contains(*set1));
   EXPECT_FALSE(set2->Contains(*union_set.get()));
-  EXPECT_TRUE(union_set->Contains(*set1.get()));
-  EXPECT_TRUE(union_set->Contains(*set2.get()));
+  EXPECT_TRUE(union_set->Contains(*set1));
+  EXPECT_TRUE(union_set->Contains(*set2));
 
   EXPECT_FALSE(union_set->HasEffectiveFullAccess());
   EXPECT_EQ(expected_apis, union_set->apis());
@@ -396,12 +426,12 @@
                                scriptable_hosts2));
   union_set = PermissionSet::CreateUnion(*set1, *set2);
 
-  EXPECT_FALSE(set1->Contains(*set2.get()));
+  EXPECT_FALSE(set1->Contains(*set2));
   EXPECT_FALSE(set1->Contains(*union_set.get()));
-  EXPECT_FALSE(set2->Contains(*set1.get()));
+  EXPECT_FALSE(set2->Contains(*set1));
   EXPECT_FALSE(set2->Contains(*union_set.get()));
-  EXPECT_TRUE(union_set->Contains(*set1.get()));
-  EXPECT_TRUE(union_set->Contains(*set2.get()));
+  EXPECT_TRUE(union_set->Contains(*set1));
+  EXPECT_TRUE(union_set->Contains(*set2));
 
   EXPECT_TRUE(union_set->HasEffectiveFullAccess());
   EXPECT_TRUE(union_set->HasEffectiveAccessToAllHosts());
@@ -457,12 +487,12 @@
   set2.reset(new PermissionSet(apis2, manifest_permissions, explicit_hosts2,
                                scriptable_hosts2));
   new_set = PermissionSet::CreateIntersection(*set1, *set2);
-  EXPECT_TRUE(set1->Contains(*new_set.get()));
-  EXPECT_TRUE(set2->Contains(*new_set.get()));
-  EXPECT_TRUE(set1->Contains(*set2.get()));
-  EXPECT_FALSE(set2->Contains(*set1.get()));
-  EXPECT_FALSE(new_set->Contains(*set1.get()));
-  EXPECT_TRUE(new_set->Contains(*set2.get()));
+  EXPECT_TRUE(set1->Contains(*new_set));
+  EXPECT_TRUE(set2->Contains(*new_set));
+  EXPECT_TRUE(set1->Contains(*set2));
+  EXPECT_FALSE(set2->Contains(*set1));
+  EXPECT_FALSE(new_set->Contains(*set1));
+  EXPECT_TRUE(new_set->Contains(*set2));
 
   EXPECT_TRUE(new_set->IsEmpty());
   EXPECT_FALSE(new_set->HasEffectiveFullAccess());
@@ -508,12 +538,12 @@
                                scriptable_hosts2));
   new_set = PermissionSet::CreateIntersection(*set1, *set2);
 
-  EXPECT_TRUE(set1->Contains(*new_set.get()));
-  EXPECT_TRUE(set2->Contains(*new_set.get()));
-  EXPECT_FALSE(set1->Contains(*set2.get()));
-  EXPECT_FALSE(set2->Contains(*set1.get()));
-  EXPECT_FALSE(new_set->Contains(*set1.get()));
-  EXPECT_FALSE(new_set->Contains(*set2.get()));
+  EXPECT_TRUE(set1->Contains(*new_set));
+  EXPECT_TRUE(set2->Contains(*new_set));
+  EXPECT_FALSE(set1->Contains(*set2));
+  EXPECT_FALSE(set2->Contains(*set1));
+  EXPECT_FALSE(new_set->Contains(*set1));
+  EXPECT_FALSE(new_set->Contains(*set2));
 
   EXPECT_FALSE(new_set->HasEffectiveFullAccess());
   EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
@@ -569,7 +599,7 @@
   set2.reset(new PermissionSet(apis2, manifest_permissions, explicit_hosts2,
                                scriptable_hosts2));
   new_set = PermissionSet::CreateDifference(*set1, *set2);
-  EXPECT_EQ(*set1.get(), *new_set.get());
+  EXPECT_EQ(*set1, *new_set);
 
   // Now use a real second set.
   apis2.insert(APIPermission::kTab);
@@ -607,8 +637,8 @@
                                scriptable_hosts2));
   new_set = PermissionSet::CreateDifference(*set1, *set2);
 
-  EXPECT_TRUE(set1->Contains(*new_set.get()));
-  EXPECT_FALSE(set2->Contains(*new_set.get()));
+  EXPECT_TRUE(set1->Contains(*new_set));
+  EXPECT_FALSE(set2->Contains(*new_set));
 
   EXPECT_FALSE(new_set->HasEffectiveFullAccess());
   EXPECT_FALSE(new_set->HasEffectiveAccessToAllHosts());
@@ -676,9 +706,9 @@
     if (!new_extension.get())
       continue;
 
-    const PermissionSet* old_p =
+    const PermissionSet& old_p =
         old_extension->permissions_data()->active_permissions();
-    const PermissionSet* new_p =
+    const PermissionSet& new_p =
         new_extension->permissions_data()->active_permissions();
     Manifest::Type extension_type = old_extension->GetType();
 
@@ -866,7 +896,7 @@
   PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                             URLPatternSet(), URLPatternSet());
   EXPECT_TRUE(
-      PermissionSetProducesMessage(&permissions, Manifest::TYPE_PLATFORM_APP,
+      PermissionSetProducesMessage(permissions, Manifest::TYPE_PLATFORM_APP,
                                    MakePermissionIDSet(api_permissions)));
 }
 
@@ -877,7 +907,7 @@
   PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                             URLPatternSet(), URLPatternSet());
   EXPECT_TRUE(
-      PermissionSetProducesMessage(&permissions, Manifest::TYPE_PLATFORM_APP,
+      PermissionSetProducesMessage(permissions, Manifest::TYPE_PLATFORM_APP,
                                    MakePermissionIDSet(api_permissions)));
 }
 
@@ -892,7 +922,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(), hosts,
                               URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kTab, APIPermission::kFavicon)));
   }
   {
@@ -905,7 +935,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(), hosts,
                               URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHistory, APIPermission::kFavicon)));
   }
   {
@@ -917,7 +947,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(), hosts,
                               URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll, APIPermission::kTab)));
   }
   {
@@ -929,7 +959,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(), hosts,
                               URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll,
                             APIPermission::kTopSites)));
   }
@@ -942,7 +972,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(), hosts,
                               URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll)));
   }
   {
@@ -956,7 +986,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     EXPECT_TRUE(
-        PermissionSetProducesMessage(&permissions, Manifest::TYPE_EXTENSION,
+        PermissionSetProducesMessage(permissions, Manifest::TYPE_EXTENSION,
                                      MakePermissionIDSet(api_permissions)));
   }
   {
@@ -969,7 +999,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     EXPECT_TRUE(
-        PermissionSetProducesMessage(&permissions, Manifest::TYPE_EXTENSION,
+        PermissionSetProducesMessage(permissions, Manifest::TYPE_EXTENSION,
                                      MakePermissionIDSet(api_permissions)));
   }
 }
@@ -981,7 +1011,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     VerifyOnePermissionMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_SERIAL));
   }
   {
@@ -992,20 +1022,20 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     VerifyOnePermissionMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_SERIAL));
   }
   {
     scoped_refptr<Extension> extension =
         LoadManifest("permissions", "access_to_devices_bluetooth.json");
-    PermissionSet* set = const_cast<PermissionSet*>(
+    PermissionSet& set = const_cast<PermissionSet&>(
         extension->permissions_data()->active_permissions());
     VerifyOnePermissionMessage(
         set, extension->GetType(),
         l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_BLUETOOTH));
 
     // Test Bluetooth and Serial
-    set->apis_.insert(APIPermission::kSerial);
+    set.apis_.insert(APIPermission::kSerial);
     VerifyOnePermissionMessage(
         set, extension->GetType(),
         l10n_util::GetStringUTF16(
@@ -1034,21 +1064,21 @@
                                             URLPatternSet(), URLPatternSet());
 
   const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(&write_directory_permissions,
-                                             &write_permissions,
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions,
+                                             write_permissions,
                                              Manifest::TYPE_PLATFORM_APP));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(&write_directory_permissions,
-                                             &directory_permissions,
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(write_directory_permissions,
+                                             directory_permissions,
                                              Manifest::TYPE_PLATFORM_APP));
   EXPECT_TRUE(provider->IsPrivilegeIncrease(
-      &write_permissions, &directory_permissions, Manifest::TYPE_PLATFORM_APP));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(&write_permissions,
-                                            &write_directory_permissions,
+      write_permissions, directory_permissions, Manifest::TYPE_PLATFORM_APP));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(write_permissions,
+                                            write_directory_permissions,
                                             Manifest::TYPE_PLATFORM_APP));
   EXPECT_FALSE(provider->IsPrivilegeIncrease(
-      &directory_permissions, &write_permissions, Manifest::TYPE_PLATFORM_APP));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(&directory_permissions,
-                                            &write_directory_permissions,
+      directory_permissions, write_permissions, Manifest::TYPE_PLATFORM_APP));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(directory_permissions,
+                                            write_directory_permissions,
                                             Manifest::TYPE_PLATFORM_APP));
 }
 
@@ -1084,7 +1114,7 @@
   scoped_refptr<Extension> extension =
       LoadManifest("permissions", "audio-video.json");
   const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
-  PermissionSet* set = const_cast<PermissionSet*>(
+  PermissionSet& set = const_cast<PermissionSet&>(
       extension->permissions_data()->active_permissions());
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio));
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo));
@@ -1095,7 +1125,7 @@
   size_t combined_size = warnings.size();
 
   // Just audio present.
-  set->apis_.erase(APIPermission::kVideoCapture);
+  set.apis_.erase(APIPermission::kVideoCapture);
   EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio));
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo));
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kBoth));
@@ -1105,8 +1135,8 @@
   EXPECT_EQ(combined_index, IndexOf(warnings2, kAudio));
 
   // Just video present.
-  set->apis_.erase(APIPermission::kAudioCapture);
-  set->apis_.insert(APIPermission::kVideoCapture);
+  set.apis_.erase(APIPermission::kAudioCapture);
+  set.apis_.insert(APIPermission::kVideoCapture);
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio));
   EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo));
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kBoth));
@@ -1127,7 +1157,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     EXPECT_TRUE(VerifyOnePermissionMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         l10n_util::GetStringUTF16(
             IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ_AND_SESSIONS)));
   }
@@ -1142,7 +1172,7 @@
     PermissionSet permissions(api_permissions, ManifestPermissionSet(),
                               URLPatternSet(), URLPatternSet());
     EXPECT_TRUE(VerifyOnePermissionMessage(
-        &permissions, Manifest::TYPE_EXTENSION,
+        permissions, Manifest::TYPE_EXTENSION,
         l10n_util::GetStringUTF16(
             IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE_AND_SESSIONS)));
   }
@@ -1158,28 +1188,33 @@
   // on the current channel.
   ScopedCurrentChannel sc(version_info::Channel::CANARY);
 
-  // First verify that declarativeWebRequest produces a message when host
-  // permissions do not cover all hosts.
-  scoped_refptr<Extension> extension =
-      LoadManifest("permissions", "web_request_not_all_host_permissions.json");
-  const PermissionSet* set =
-      extension->permissions_data()->active_permissions();
-  EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(),
-                                         "Block parts of web pages"));
-  EXPECT_FALSE(VerifyHasPermissionMessage(
-      set, extension->GetType(),
-      "Read and change all your data on the websites you visit"));
+  {
+    // First verify that declarativeWebRequest produces a message when host
+    // permissions do not cover all hosts.
+    scoped_refptr<const Extension> extension = LoadManifest(
+        "permissions", "web_request_not_all_host_permissions.json");
+    const PermissionSet& set =
+        extension->permissions_data()->active_permissions();
+    EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(),
+                                           "Block parts of web pages"));
+    EXPECT_FALSE(VerifyHasPermissionMessage(
+        set, extension->GetType(),
+        "Read and change all your data on the websites you visit"));
+  }
 
+  {
   // Now verify that declarativeWebRequest does not produce a message when host
   // permissions do cover all hosts.
-  extension =
+  scoped_refptr<const Extension> extension =
       LoadManifest("permissions", "web_request_all_host_permissions.json");
-  set = extension->permissions_data()->active_permissions();
+  const PermissionSet& set =
+      extension->permissions_data()->active_permissions();
   EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(),
                                           "Block parts of web pages"));
   EXPECT_TRUE(VerifyHasPermissionMessage(
       set, extension->GetType(),
       "Read and change all your data on the websites you visit"));
+  }
 }
 
 TEST(PermissionsTest, GetWarningMessages_Serial) {
@@ -1567,8 +1602,8 @@
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
 
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 
   // Test that paths are ignored.
   elist2.ClearPatterns();
@@ -1576,8 +1611,8 @@
       URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com/*"));
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 
   // Test that RCDs are ignored.
   elist2.ClearPatterns();
@@ -1585,8 +1620,8 @@
       URLPattern(URLPattern::SCHEME_HTTP, "http://www.google.com.hk/*"));
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 
   // Test that subdomain wildcards are handled properly.
   elist2.ClearPatterns();
@@ -1594,7 +1629,7 @@
       URLPattern(URLPattern::SCHEME_HTTP, "http://*.google.com.hk/*"));
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(*set1, *set2, type));
   // TODO(jstritar): Does not match subdomains properly. http://crbug.com/65337
   // EXPECT_FALSE(provider->IsPrivilegeIncrease(set2, set1, type));
 
@@ -1606,8 +1641,8 @@
       URLPattern(URLPattern::SCHEME_HTTP, "http://www.example.org/path"));
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 
   // Test that different subdomains count as different hosts.
   elist2.ClearPatterns();
@@ -1615,13 +1650,13 @@
       URLPattern(URLPattern::SCHEME_HTTP, "http://mail.google.com/*"));
   set2.reset(new PermissionSet(empty_perms, empty_manifest_permissions, elist2,
                                slist2));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_TRUE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_TRUE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 
   // Test that platform apps do not have host permissions increases.
   type = Manifest::TYPE_PLATFORM_APP;
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set1.get(), set2.get(), type));
-  EXPECT_FALSE(provider->IsPrivilegeIncrease(set2.get(), set1.get(), type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set1, *set2, type));
+  EXPECT_FALSE(provider->IsPrivilegeIncrease(*set2, *set1, type));
 }
 
 TEST(PermissionsTest, GetAPIsAsStrings) {
@@ -1714,18 +1749,18 @@
                             allowed_hosts, URLPatternSet());
   PermissionMessageProvider::Get()->GetPermissionMessages(
       PermissionMessageProvider::Get()->GetAllPermissionIDs(
-          &permissions, Manifest::TYPE_EXTENSION));
+          permissions, Manifest::TYPE_EXTENSION));
 }
 
 TEST(PermissionsTest, IsPrivilegeIncrease_DeclarativeWebRequest) {
   scoped_refptr<Extension> extension(
       LoadManifest("permissions", "permissions_all_urls.json"));
-  const PermissionSet* permissions =
+  const PermissionSet& permissions =
       extension->permissions_data()->active_permissions();
 
   scoped_refptr<Extension> extension_dwr(
       LoadManifest("permissions", "web_request_all_host_permissions.json"));
-  const PermissionSet* permissions_dwr =
+  const PermissionSet& permissions_dwr =
       extension_dwr->permissions_data()->active_permissions();
 
   EXPECT_FALSE(PermissionMessageProvider::Get()->IsPrivilegeIncrease(
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index 582a77e..620fb8b 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -187,12 +187,12 @@
   EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com")));
   EXPECT_TRUE(extension->permissions_data()
                   ->active_permissions()
-                  ->HasEffectiveAccessToURL(GURL("http://www.reddit.com")));
+                  .HasEffectiveAccessToURL(GURL("http://www.reddit.com")));
   EXPECT_TRUE(hosts.MatchesURL(GURL("http://news.ycombinator.com")));
   EXPECT_TRUE(
       extension->permissions_data()
           ->active_permissions()
-          ->HasEffectiveAccessToURL(GURL("http://news.ycombinator.com")));
+          .HasEffectiveAccessToURL(GURL("http://news.ycombinator.com")));
   EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts());
 
   extension = LoadManifest("effective_host_permissions", "all_hosts.json");
diff --git a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
index 8f1fb01..7f95c1c 100644
--- a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
@@ -64,93 +64,88 @@
 
 TEST_F(SettingsOverridePermissionTest, HomePage) {
   scoped_refptr<Extension> extension(GetPermissionSet(kHomepage));
-  const PermissionSet* permission_set =
+  const PermissionSet& permission_set =
       extension->permissions_data()->active_permissions();
 
 #if defined(OS_WIN)
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kHomepage));
   VerifyOnePermissionMessage(extension->permissions_data(),
                              "Change your home page to: google.com/");
 #else
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kHomepage));
 #endif
 
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
-  EXPECT_FALSE(permission_set->HasAPIPermission(
-      APIPermission::kSearchProvider));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 }
 
 TEST_F(SettingsOverridePermissionTest, StartupPages) {
   scoped_refptr<Extension> extension(GetPermissionSet(kStartupPages));
-  const PermissionSet* permission_set =
+  const PermissionSet& permission_set =
       extension->permissions_data()->active_permissions();
 
 #if defined(OS_WIN)
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
   VerifyOnePermissionMessage(
       extension->permissions_data(),
       "Change your start page to: startup.com/startup.html");
 #else
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
 #endif
 
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_FALSE(permission_set->HasAPIPermission(
-      APIPermission::kSearchProvider));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 }
 
 TEST_F(SettingsOverridePermissionTest, SearchSettings) {
   scoped_refptr<Extension> extension(GetPermissionSet(kSearchProvider));
-  const PermissionSet* permission_set =
+  const PermissionSet& permission_set =
       extension->permissions_data()->active_permissions();
 
 #if defined(OS_WIN)
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
   VerifyOnePermissionMessage(extension->permissions_data(),
                              "Change your search settings to: google.com");
 #else
-  EXPECT_FALSE(
-      permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 #endif
 
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
 }
 
 TEST_F(SettingsOverridePermissionTest, All) {
   scoped_refptr<Extension> extension(GetPermissionSet(
       kSearchProvider | kStartupPages | kHomepage));
-  const PermissionSet* permission_set =
+  const PermissionSet& permission_set =
       extension->permissions_data()->active_permissions();
 
 #if defined(OS_WIN)
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 #else
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
-  EXPECT_FALSE(
-      permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 #endif
 }
 
 TEST_F(SettingsOverridePermissionTest, Some) {
   scoped_refptr<Extension> extension(GetPermissionSet(
       kSearchProvider | kHomepage));
-  const PermissionSet* permission_set =
+  const PermissionSet& permission_set =
       extension->permissions_data()->active_permissions();
 
 #if defined(OS_WIN)
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_TRUE(permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_TRUE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 #else
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kHomepage));
-  EXPECT_FALSE(
-      permission_set->HasAPIPermission(APIPermission::kSearchProvider));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kHomepage));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kSearchProvider));
 #endif
 
-  EXPECT_FALSE(permission_set->HasAPIPermission(APIPermission::kStartupPages));
+  EXPECT_FALSE(permission_set.HasAPIPermission(APIPermission::kStartupPages));
 }
 
 }  // namespace
diff --git a/chrome/common/media/media_resource_provider.cc b/chrome/common/media/media_resource_provider.cc
new file mode 100644
index 0000000..cc00bf5
--- /dev/null
+++ b/chrome/common/media/media_resource_provider.cc
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Authors. 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 "chrome/common/media/media_resource_provider.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chrome_common_media {
+
+int MediaMessageIdToGrdId(media::MessageId message_id) {
+  switch (message_id) {
+    case media::DEFAULT_AUDIO_DEVICE_NAME:
+      return IDS_DEFAULT_AUDIO_DEVICE_NAME;
+#if defined(OS_WIN)
+    case media::COMMUNICATIONS_AUDIO_DEVICE_NAME:
+      return IDS_COMMUNICATIONS_AUDIO_DEVICE_NAME;
+#endif
+#if defined(OS_CHROMEOS)
+    case media::BEAMFORMING_ON_DEFAULT_AUDIO_INPUT_DEVICE_NAME:
+      return IDS_BEAMFORMING_ON_DEFAULT_AUDIO_INPUT_DEVICE_NAME;
+    case media::BEAMFORMING_OFF_DEFAULT_AUDIO_INPUT_DEVICE_NAME:
+      return IDS_BEAMFORMING_OFF_DEFAULT_AUDIO_INPUT_DEVICE_NAME;
+#endif
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
+base::string16 LocalizedStringProvider(media::MessageId message_id) {
+  return l10n_util::GetStringUTF16(MediaMessageIdToGrdId(message_id));
+}
+
+}  // namespace chrome_common_media
diff --git a/chrome/common/media/media_resource_provider.h b/chrome/common/media/media_resource_provider.h
new file mode 100644
index 0000000..b1b5e76
--- /dev/null
+++ b/chrome/common/media/media_resource_provider.h
@@ -0,0 +1,18 @@
+// Copyright 2015 The Chromium Authors. 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_MEDIA_MEDIA_RESOURCE_PROVIDER_H_
+#define CHROME_COMMON_MEDIA_MEDIA_RESOURCE_PROVIDER_H_
+
+#include "base/strings/string16.h"
+#include "media/base/media_resources.h"
+
+namespace chrome_common_media {
+
+// This is called indirectly by the media layer to access resources.
+base::string16 LocalizedStringProvider(media::MessageId media_message_id);
+
+}  // namespace chrome_common_media
+
+#endif  // CHROME_COMMON_MEDIA_MEDIA_RESOURCE_PROVIDER_H_
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 544da59..aa8c219 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1252,12 +1252,6 @@
 const char kSSLVersionMax[] = "ssl.version_max";
 const char kSSLVersionFallbackMin[] = "ssl.version_fallback_min";
 const char kCipherSuiteBlacklist[] = "ssl.cipher_suites.blacklist";
-const char kDisableSSLRecordSplitting[] = "ssl.ssl_record_splitting.disabled";
-
-// Boolean that specifies whether or not crash reporting and metrics reporting
-// are sent over the network for analysis.
-const char kMetricsReportingEnabled[] =
-    "user_experience_metrics.reporting_enabled";
 
 // Boolean that specifies whether or not crash reports are sent
 // over the network for analysis.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 2eae559..5374a0825 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -425,17 +425,11 @@
 extern const char kSSLVersionMax[];
 extern const char kSSLVersionFallbackMin[];
 extern const char kCipherSuiteBlacklist[];
-extern const char kDisableSSLRecordSplitting[];
 
 extern const char kGLVendorString[];
 extern const char kGLRendererString[];
 extern const char kGLVersionString[];
 
-// For finding out whether metrics and crash reporting is enabled or not use
-// |ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled()| instead
-// of reading platform specific prefs.
-extern const char kMetricsReportingEnabled[];
-
 // Android has it's own metric / crash reporting implemented in Android
 // Java code so kMetricsReportingEnabled doesn't make sense. We use this
 // to inform crashes_ui that we have enabled crash reporting.
diff --git a/chrome/common/service_process_util_win.cc b/chrome/common/service_process_util_win.cc
index df7c039..99cb01d 100644
--- a/chrome/common/service_process_util_win.cc
+++ b/chrome/common/service_process_util_win.cc
@@ -58,7 +58,7 @@
     base::string16 event_name = GetServiceProcessTerminateEventName();
     DCHECK(event_name.length() <= MAX_PATH);
     terminate_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str()));
-    watcher_.StartWatching(terminate_event_.Get(), this);
+    watcher_.StartWatchingOnce(terminate_event_.Get(), this);
   }
 
   // base::ObjectWatcher::Delegate implementation.
diff --git a/chrome/installer/installer_tools.gyp b/chrome/installer/installer_tools.gyp
deleted file mode 100644
index 3033e218..0000000
--- a/chrome/installer/installer_tools.gyp
+++ /dev/null
@@ -1,38 +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.
-
-{
-  'variables': {
-    'version_py': '<(DEPTH)/build/util/version.py',
-    'version_path': '<(DEPTH)/chrome/VERSION',
-    'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE',
-    'branding_dir': '<(DEPTH)/chrome/app/theme/<(branding_path_component)',
-    'msvs_use_common_release': 0,
-    'msvs_use_common_linker_extras': 0,
-  },
-  'conditions': [
-    ['OS=="win"', {
-      'targets': [
-        {
-          'target_name': 'validate_installation',
-          'type': 'executable',
-          'dependencies': [
-            '<(DEPTH)/base/base.gyp:base',
-            '<(DEPTH)/chrome/chrome.gyp:installer_util',
-            '<(DEPTH)/chrome/chrome.gyp:installer_util_strings',
-            '<(DEPTH)/chrome/common_constants.gyp:common_constants',
-          ],
-          'include_dirs': [
-            '<(DEPTH)',
-          ],
-          'sources': [
-            'tools/validate_installation.rc',
-            'tools/validate_installation_main.cc',
-            'tools/validate_installation_resource.h',
-          ],
-        },
-      ],
-    }],
-  ],
-}
diff --git a/chrome/installer/linux/rpm/build.sh b/chrome/installer/linux/rpm/build.sh
index 43996448..f58799b 100755
--- a/chrome/installer/linux/rpm/build.sh
+++ b/chrome/installer/linux/rpm/build.sh
@@ -126,9 +126,11 @@
   # https://qa.mandriva.com/show_bug.cgi?id=55714
   # https://bugzilla.redhat.com/show_bug.cgi?id=538158
   # https://bugzilla.novell.com/show_bug.cgi?id=556248
+  #
+  # We want to depend on liberation-fonts as well, but there is no such package
+  # for Fedora. https://bugzilla.redhat.com/show_bug.cgi?id=1252564
   DEPENDS="lsb >= 4.0, \
   libcurl.so.4${EMPTY_VERSION}${PKG_ARCH}, \
-  liberation-fonts, \
   libnss3.so(NSS_3.14.3)${PKG_ARCH}, \
   wget, \
   xdg-utils, \
diff --git a/chrome/installer/tools/validate_installation.rc b/chrome/installer/tools/validate_installation.rc
deleted file mode 100644
index d5a34e5..0000000
--- a/chrome/installer/tools/validate_installation.rc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "validate_installation_resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#define APSTUDIO_HIDDEN_SYMBOLS
-#include "windows.h"
-#undef APSTUDIO_HIDDEN_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE 9, 1
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE  
-BEGIN
-    "validate_installation_resource.h\0"
-END
-
-2 TEXTINCLUDE  
-BEGIN
-    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
-    "#include ""windows.h""\r\n"
-    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE  
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// String Table
-//
-#include "chrome/installer/util/installer_util_strings.rc"
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/chrome/installer/tools/validate_installation_main.cc b/chrome/installer/tools/validate_installation_main.cc
deleted file mode 100644
index 74f860c..0000000
--- a/chrome/installer/tools/validate_installation_main.cc
+++ /dev/null
@@ -1,189 +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.
-
-// A command-line tool that inspects the current system, displaying information
-// about installed products.  Violations are dumped to stderr.  The process
-// exit code is 0 if there are no violations, or 1 otherwise.
-
-#include <cstdio>
-#include <cstdlib>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "chrome/installer/util/installation_validator.h"
-
-using installer::InstallationValidator;
-
-namespace {
-
-// A helper class that initializes logging and installs a log message handler to
-// direct ERROR messages to stderr.  Only one instance of this class may be live
-// at a time.
-class ConsoleLogHelper {
- public:
-  ConsoleLogHelper();
-  ~ConsoleLogHelper();
-
- private:
-  static base::FilePath GetLogFilePath();
-  static bool DumpLogMessage(int severity,
-                             const char* file,
-                             int line,
-                             size_t message_start,
-                             const std::string& str);
-
-  static const wchar_t kLogFileName_[];
-  static FILE* const kOutputStream_;
-  static const logging::LogSeverity kViolationSeverity_;
-  static logging::LogMessageHandlerFunction old_message_handler_;
-  base::FilePath log_file_path_;
-};
-
-// static
-const wchar_t ConsoleLogHelper::kLogFileName_[] = L"validate_installation.log";
-
-// Dump violations to stderr.
-// static
-FILE* const ConsoleLogHelper::kOutputStream_ = stderr;
-
-// InstallationValidator logs all violations at ERROR level.
-// static
-const logging::LogSeverity
-    ConsoleLogHelper::kViolationSeverity_ = logging::LOG_ERROR;
-
-// static
-logging::LogMessageHandlerFunction
-    ConsoleLogHelper::old_message_handler_ = NULL;
-
-ConsoleLogHelper::ConsoleLogHelper() : log_file_path_(GetLogFilePath()) {
-  LOG_ASSERT(old_message_handler_ == NULL);
-  logging::LoggingSettings settings;
-  settings.logging_dest = logging::LOG_TO_FILE;
-  settings.log_file = log_file_path_.value().c_str();
-  settings.lock_log = logging::DONT_LOCK_LOG_FILE;
-  settings.delete_old = logging::DELETE_OLD_LOG_FILE;
-  logging::InitLogging(settings);
-
-  old_message_handler_ = logging::GetLogMessageHandler();
-  logging::SetLogMessageHandler(&DumpLogMessage);
-}
-
-ConsoleLogHelper::~ConsoleLogHelper() {
-  logging::SetLogMessageHandler(old_message_handler_);
-  old_message_handler_ = NULL;
-
-  logging::CloseLogFile();
-
-  // Delete the log file if it wasn't written to (this is expected).
-  int64 file_size = 0;
-  if (base::GetFileSize(log_file_path_, &file_size) && file_size == 0)
-    base::DeleteFile(log_file_path_, false);
-}
-
-// Returns the path to the log file to create.  The file should be empty at
-// process exit since we redirect log messages to stderr.
-// static
-base::FilePath ConsoleLogHelper::GetLogFilePath() {
-  base::FilePath log_path;
-
-  if (PathService::Get(base::DIR_TEMP, &log_path))
-    return log_path.Append(kLogFileName_);
-  else
-    return base::FilePath(kLogFileName_);
-}
-
-// A logging::LogMessageHandlerFunction that sends the body of messages logged
-// at the severity of validation violations to stderr.  All other messages are
-// sent through the default logging pipeline.
-// static
-bool ConsoleLogHelper::DumpLogMessage(int severity,
-                                      const char* file,
-                                      int line,
-                                      size_t message_start,
-                                      const std::string& str) {
-  if (severity == kViolationSeverity_) {
-    fprintf(kOutputStream_, "%s", str.c_str() + message_start);
-    return true;
-  }
-
-  if (old_message_handler_ != NULL)
-    return (old_message_handler_)(severity, file, line, message_start, str);
-
-  return false;
-}
-
-const char* LevelToString(bool system_level) {
-  return system_level ? "System-level" : "User-level";
-}
-
-std::string InstallationTypeToString(
-    InstallationValidator::InstallationType type) {
-  std::string result;
-
-  static const struct ProductData {
-    int bit;
-    const char* name;
-  } kProdBitToName[] = {
-    {
-      InstallationValidator::ProductBits::CHROME_SINGLE,
-      "Chrome"
-    }, {
-      InstallationValidator::ProductBits::CHROME_MULTI,
-      "Chrome (multi)"
-    }, {
-      InstallationValidator::ProductBits::CHROME_FRAME_SINGLE,
-      "Chrome Frame"
-    }, {
-      InstallationValidator::ProductBits::CHROME_FRAME_MULTI,
-      "Chrome Frame (multi)"
-    }, {
-      InstallationValidator::ProductBits::CHROME_FRAME_READY_MODE,
-      "Ready-mode Chrome Frame"
-    },
-  };
-
-  for (size_t i = 0; i < arraysize(kProdBitToName); ++i) {
-    const ProductData& product_data = kProdBitToName[i];
-    if ((type & product_data.bit) != 0) {
-      if (!result.empty())
-        result.append(", ");
-      result.append(product_data.name);
-    }
-  }
-
-  return result;
-}
-
-}  // namespace
-
-// The main program.
-int wmain(int argc, wchar_t *argv[]) {
-  int result = EXIT_SUCCESS;
-  base::AtExitManager exit_manager;
-
-  base::CommandLine::Init(0, NULL);
-  ConsoleLogHelper log_helper;
-
-  // Check user-level and system-level for products.
-  for (int i = 0; i < 2; ++i) {
-    const bool system_level = (i != 0);
-    InstallationValidator::InstallationType type =
-        InstallationValidator::NO_PRODUCTS;
-    bool is_valid =
-        InstallationValidator::ValidateInstallationType(system_level, &type);
-    if (type != InstallationValidator::NO_PRODUCTS) {
-      FILE* stream = is_valid ? stdout : stderr;
-      fprintf(stream, "%s installations%s: %s\n", LevelToString(system_level),
-              (is_valid ? "" : " (with errors)"),
-              InstallationTypeToString(type).c_str());
-    }
-    if (!is_valid)
-      result = EXIT_FAILURE;
-  }
-
-  return result;
-}
diff --git a/chrome/installer/tools/validate_installation_resource.h b/chrome/installer/tools/validate_installation_resource.h
deleted file mode 100644
index 4998008..0000000
--- a/chrome/installer/tools/validate_installation_resource.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.
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by validate_installation.rc
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/chrome/installer/util/uninstall_metrics.cc b/chrome/installer/util/uninstall_metrics.cc
index fe2ee436..fbd1b90a 100644
--- a/chrome/installer/util/uninstall_metrics.cc
+++ b/chrome/installer/util/uninstall_metrics.cc
@@ -51,7 +51,7 @@
   // Make sure that the user wants us reporting metrics. If not, don't
   // add our uninstall metrics.
   bool metrics_reporting_enabled = false;
-  if (!root.GetBoolean(prefs::kMetricsReportingEnabled,
+  if (!root.GetBoolean(metrics::prefs::kMetricsReportingEnabled,
                        &metrics_reporting_enabled) ||
       !metrics_reporting_enabled) {
     return false;
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 7882c99..3d2c2f5 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -72,7 +72,10 @@
   ]
 
   if (!is_ios) {
-    deps += [ "//chrome/common/net" ]
+    deps += [
+      "//chrome/common/net",
+      "//media",
+    ]
   }
 
   if (enable_nacl) {
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index 98e1e0d..f9b67b29 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -36,6 +36,7 @@
   "+content/public/renderer",
   "+extensions/common",
   "+extensions/renderer",
+  "+media/base",
   "+gin",
   "+grit",  # For generated headers. TODO(thestig): Remove.
   "+ppapi/c",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 170b23f7..1a2aebd 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1670,3 +1670,15 @@
                                                                         url);
 #endif
 }
+
+// If we're in an extension, there is no need disabling multiple routes as
+// chrome.system.network.getNetworkInterfaces provides the same
+// information. Also, the enforcement of sending and binding UDP is already done
+// by chrome extension permission model.
+bool ChromeContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
+#if defined(ENABLE_EXTENSIONS)
+  return !IsStandaloneExtensionProcess();
+#else
+  return true;
+#endif
+}
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index ffb35ad..c622ee1 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -160,6 +160,7 @@
   void WillDestroyServiceWorkerContextOnWorkerThread(
       v8::Local<v8::Context> context,
       const GURL& url) override;
+  bool ShouldEnforceWebRTCRoutingPreferences() override;
 #if defined(ENABLE_EXTENSIONS)
   // Takes ownership.
   void SetExtensionDispatcherForTest(
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc
index fc8de3c..83de1543 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -52,6 +52,11 @@
 #include "chrome/renderer/extensions/extension_localization_peer.h"
 #endif
 
+#if !defined(OS_IOS)
+#include "chrome/common/media/media_resource_provider.h"
+#include "media/base/media_resources.h"
+#endif
+
 using blink::WebCache;
 using blink::WebRuntimeFeatures;
 using blink::WebSecurityPolicy;
@@ -251,6 +256,10 @@
 
   // Configure modules that need access to resources.
   net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
+#if !defined(OS_IOS)
+  media::SetLocalizedStringProvider(
+      chrome_common_media::LocalizedStringProvider);
+#endif
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(USE_OPENSSL)
   // On platforms where we use system NSS shared libraries,
diff --git a/chrome/renderer/resources/neterror.css b/chrome/renderer/resources/neterror.css
index 16c8857b..29c8dc2d 100644
--- a/chrome/renderer/resources/neterror.css
+++ b/chrome/renderer/resources/neterror.css
@@ -37,7 +37,7 @@
 
 .icon {
   -webkit-user-select: none;
-  content: '';
+  display: inline-block;
 }
 
 .icon-generic {
diff --git a/chrome/renderer/resources/neterror.html b/chrome/renderer/resources/neterror.html
index 4328951..338c30f 100644
--- a/chrome/renderer/resources/neterror.html
+++ b/chrome/renderer/resources/neterror.html
@@ -14,8 +14,8 @@
 <body id="t" i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
   <div id="main-frame-error" class="interstitial-wrapper">
     <div id="main-content">
-      <img class="icon"
-          jseval="updateIconClass(this.classList, iconClass)">
+      <div class="icon"
+          jseval="updateIconClass(this.classList, iconClass)"></div>
       <div id="main-message">
         <h1 i18n-content="heading"></h1>
         <p hidden></p>
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index e4a62626..26c56263 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -68,7 +68,7 @@
       printer_change_.Set(FindFirstPrinterChangeNotification(
           printer_.Get(), PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL));
       if (printer_change_.IsValid()) {
-        ret = watcher_.StartWatching(printer_change_.Get(), this);
+        ret = watcher_.StartWatchingOnce(printer_change_.Get(), this);
       }
     }
     if (!ret) {
@@ -106,7 +106,7 @@
         delegate_->OnJobChanged();
       }
     }
-    watcher_.StartWatching(printer_change_.Get(), this);
+    watcher_.StartWatchingOnce(printer_change_.Get(), this);
   }
 
   bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) {
@@ -361,7 +361,8 @@
         delegate_->OnJobSpoolSucceeded(job_status.jobId);
       } else {
         job_progress_watcher_.StopWatching();
-        job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
+        job_progress_watcher_.StartWatchingOnce(
+            job_progress_event_.Get(), this);
       }
     }
 
@@ -483,7 +484,8 @@
       if (FAILED(doc_stream->Close()))
         return false;
 
-      job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
+      job_progress_watcher_.StartWatchingOnce(
+          job_progress_event_.Get(), this);
       job_canceler.reset();
       return true;
     }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ea9d976..666b2aab 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -56,6 +56,8 @@
     "base/scoped_bundle_swizzler_mac.mm",
     "base/scoped_testing_local_state.cc",
     "base/scoped_testing_local_state.h",
+    "base/search_test_utils.cc",
+    "base/search_test_utils.h",
     "base/test_browser_window.cc",
     "base/test_browser_window.h",
     "base/test_launcher_utils.cc",
@@ -163,6 +165,19 @@
     ]
   }
 
+  if (is_android) {
+    sources -= [
+      "base/dialog_test_browser_window.cc",
+      "base/dialog_test_browser_window.h",
+      "base/in_process_browser_test.cc",
+      "base/in_process_browser_test.h",
+      "base/test_browser_window.cc",
+      "base/test_browser_window.h",
+      "base/ui_test_utils.cc",
+      "base/ui_test_utils.h",
+    ]
+  }
+
   if (enable_extensions) {
     deps += [
       "//chrome/common/extensions/api",
@@ -659,7 +674,9 @@
   # The _run targets exist only for compatibility w/ GYP.
   group("browser_tests_run") {
     testonly = true
-    data_deps = [ ":browser_tests" ]
+    data_deps = [
+      ":browser_tests",
+    ]
   }
 
   test("browser_tests") {
@@ -1208,7 +1225,9 @@
       "//third_party/WebKit/public:blink",
     ]
 
-    data_deps = [ "//third_party/mesa:osmesa" ]
+    data_deps = [
+      "//third_party/mesa:osmesa",
+    ]
 
     if (cld_version == 2) {
       # Language detection is irrelevant to sync, so it can depend on any
@@ -1857,6 +1876,7 @@
     if (is_android || is_ios) {
       sources -= [
         "../browser/devtools/device/webrtc/devtools_bridge_instances_request_unittest.cc",
+        "../browser/ui/bookmarks/bookmark_ui_utils_desktop_unittest.cc",
         "../browser/ui/sync/sync_promo_ui_unittest.cc",
       ]
     } else {
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index 2d596c8..2167a411 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -6,6 +6,7 @@
   "+chrome/grit",  # For generated headers
   "+chromeos",
   "+components",
+  "+device/bluetooth/dbus",
   "+extensions",
 
   # Tests under chrome/ shouldn't need to access the internals of content/ and
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
index be8b6d8..e3d2288 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationTestUtils.java
@@ -30,6 +30,8 @@
 
     private static PowerManager.WakeLock sWakeLock = null;
 
+    // TODO(jbudorick): fix deprecation warning crbug.com/537347
+    @SuppressWarnings("deprecation")
     public static void setUp(Context context, boolean clearAppData, boolean checkHttpServer)
             throws Exception {
         if (clearAppData) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java
index c351d72..7b95378 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java
@@ -160,6 +160,8 @@
     /**
      * Removes all Google accounts from the OS.
      */
+    // TODO(jbudorick): fix deprecation warnings crbug.com/537352
+    @SuppressWarnings("deprecation")
     public void removeAllGoogleAccountsFromOs() {
         for (Account acct : mAccountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE)) {
             mAccountManager.removeAccount(acct, null, null);
@@ -196,6 +198,7 @@
             }
         }
 
+        @Override
         public void run(AccountManagerFuture<Bundle> future) {
             Bundle resultBundle;
             try {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
new file mode 100644
index 0000000..b3cb33e9
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -0,0 +1,124 @@
+// Copyright 2015 The Chromium 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.test.util.browser.signin;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.preference.PreferenceManager;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.signin.AccountIdProvider;
+import org.chromium.chrome.browser.signin.AccountTrackerService;
+import org.chromium.chrome.browser.signin.OAuth2TokenService;
+import org.chromium.sync.signin.AccountManagerHelper;
+import org.chromium.sync.signin.ChromeSigninController;
+import org.chromium.sync.test.util.AccountHolder;
+import org.chromium.sync.test.util.MockAccountManager;
+
+import java.util.HashSet;
+
+/**
+ * Utility class for test signin functionality.
+ */
+public final class SigninTestUtil {
+    private static final String TAG = "cr.Signin";
+
+    private static final String DEFAULT_ACCOUNT = "test@gmail.com";
+
+    private static SigninTestUtil sInstance;
+
+    private Context mContext;
+    private MockAccountManager mAccountManager;
+
+    /**
+     * Sets up the test authentication environment.
+     *
+     * This must be called before native is loaded.
+     */
+    public static void setUpAuthForTest(Instrumentation instrumentation) {
+        assert sInstance == null;
+        sInstance = new SigninTestUtil(instrumentation);
+    }
+
+    /**
+     * Get the object created in setUpAuthForTest.
+     */
+    public static SigninTestUtil get() {
+        assert sInstance != null;
+        return sInstance;
+    }
+
+    private SigninTestUtil(Instrumentation instrumentation) {
+        mContext = instrumentation.getTargetContext();
+        mAccountManager = new MockAccountManager(mContext, instrumentation.getContext());
+        AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
+        overrideAccountIdProvider();
+        // Clear cached signed account name here or tests can flake.
+        ChromeSigninController.get(mContext).setSignedInAccountName(null);
+        // Clear cached accounts list here or tests can also flake. Needs to use the app context.
+        PreferenceManager.getDefaultSharedPreferences(mContext.getApplicationContext())
+                .edit()
+                .putStringSet(OAuth2TokenService.STORED_ACCOUNTS_KEY, new HashSet<String>())
+                .apply();
+    }
+
+    /**
+     * Add an account with the default name.
+     */
+    public Account addTestAccount() {
+        Account account = createTestAccount(DEFAULT_ACCOUNT);
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                AccountTrackerService.get(mContext).forceRefresh();
+            }
+        });
+        return account;
+    }
+
+    /**
+     * Add and sign in an account with the default name.
+     */
+    public Account addAndSignInTestAccount() {
+        Account account = createTestAccount(DEFAULT_ACCOUNT);
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ChromeSigninController.get(mContext).setSignedInAccountName(DEFAULT_ACCOUNT);
+                AccountTrackerService.get(mContext).forceRefresh();
+            }
+        });
+        return account;
+    }
+
+    private Account createTestAccount(String accountName) {
+        Account account = AccountManagerHelper.createAccountFromName(accountName);
+        AccountHolder.Builder accountHolder =
+                AccountHolder.create().account(account).alwaysAccept(true);
+        mAccountManager.addAccountHolderExplicitly(accountHolder.build());
+        return account;
+    }
+
+    private void overrideAccountIdProvider() {
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                AccountIdProvider.setInstanceForTest(new AccountIdProvider() {
+                    @Override
+                    public String getAccountId(Context ctx, String accountName) {
+                        return "gaia-id-" + accountName;
+                    }
+
+                    @Override
+                    public boolean canBeUsed(Context ctx, Activity activity) {
+                        return true;
+                    }
+                });
+            }
+        });
+    }
+}
diff --git a/chrome/test/android/unit_tests_apk/AndroidManifest.xml b/chrome/test/android/unit_tests_apk/AndroidManifest.xml
index 3fdebe57..fc0124c 100644
--- a/chrome/test/android/unit_tests_apk/AndroidManifest.xml
+++ b/chrome/test/android/unit_tests_apk/AndroidManifest.xml
@@ -11,7 +11,6 @@
       android:versionName="1.0">
 
     <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc
index 040459a..b184e31 100644
--- a/chrome/test/base/browser_with_test_window_test.cc
+++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/profiles/profile_destroyer.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 5237471..3f75d9e5 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/host_desktop.h"
diff --git a/chrome/test/base/search_test_utils.cc b/chrome/test/base/search_test_utils.cc
new file mode 100644
index 0000000..8c52119
--- /dev/null
+++ b/chrome/test/base/search_test_utils.cc
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/base/search_test_utils.h"
+
+#include "base/memory/ref_counted.h"
+#include "components/search_engines/template_url_service.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace search_test_utils {
+
+void WaitForTemplateURLServiceToLoad(TemplateURLService* service) {
+  if (service->loaded())
+    return;
+  scoped_refptr<content::MessageLoopRunner> message_loop_runner =
+      new content::MessageLoopRunner;
+  scoped_ptr<TemplateURLService::Subscription> subscription =
+      service->RegisterOnLoadedCallback(
+          message_loop_runner->QuitClosure());
+  service->Load();
+  message_loop_runner->Run();
+
+  ASSERT_TRUE(service->loaded());
+}
+
+}  // namespace search_test_utils
diff --git a/chrome/test/base/search_test_utils.h b/chrome/test/base/search_test_utils.h
new file mode 100644
index 0000000..144f623d
--- /dev/null
+++ b/chrome/test/base/search_test_utils.h
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_BASE_SEARCH_TEST_UTILS_H_
+#define CHROME_TEST_BASE_SEARCH_TEST_UTILS_H_
+
+class TemplateURLService;
+
+namespace search_test_utils {
+
+// Blocks until |service| finishes loading.
+void WaitForTemplateURLServiceToLoad(TemplateURLService* service);
+
+}  // namespace search_test_utils
+
+#endif  // CHROME_TEST_BASE_SEARCH_TEST_UTILS_H_
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc
index 63ee1ae7..c480043 100644
--- a/chrome/test/base/test_browser_window.cc
+++ b/chrome/test/base/test_browser_window.cc
@@ -164,10 +164,6 @@
   return gfx::Rect();
 }
 
-bool TestBrowserWindow::ShowSessionCrashedBubble() {
-  return false;
-}
-
 bool TestBrowserWindow::IsProfileResetBubbleSupported() const {
   return false;
 }
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index e56511d8..4e8bf4f 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -113,7 +113,6 @@
                            translate::TranslateStep step,
                            translate::TranslateErrors::Type error_type,
                            bool is_user_gesture) override {}
-  bool ShowSessionCrashedBubble() override;
   bool IsProfileResetBubbleSupported() const override;
   GlobalErrorBubbleViewBase* ShowProfileResetBubble(
       const base::WeakPtr<ProfileResetGlobalError>& global_error) override;
diff --git a/chrome/test/base/testing_io_thread_state.cc b/chrome/test/base/testing_io_thread_state.cc
index 8ebd202b8..09b07f2 100644
--- a/chrome/test/base/testing_io_thread_state.cc
+++ b/chrome/test/base/testing_io_thread_state.cc
@@ -16,6 +16,7 @@
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #endif
 
 using content::BrowserThread;
@@ -42,6 +43,10 @@
 #if defined(OS_CHROMEOS)
   // Needed by IOThread constructor.
   chromeos::DBusThreadManager::Initialize();
+  bluez::BluezDBusManager::Initialize(
+      chromeos::DBusThreadManager::Get()->GetSystemBus(),
+      chromeos::DBusThreadManager::Get()->IsUsingStub(
+          chromeos::DBusClientBundle::BLUETOOTH));
   chromeos::NetworkHandler::Initialize();
 #endif
 
@@ -75,6 +80,7 @@
 
 #if defined(OS_CHROMEOS)
   chromeos::NetworkHandler::Shutdown();
+  bluez::BluezDBusManager::Shutdown();
   chromeos::DBusThreadManager::Shutdown();
 #endif
 }
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index 6a9f0b21..cfa6502 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ui/browser_iterator.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
@@ -47,7 +48,6 @@
 #include "components/history/core/browser/history_service_observer.h"
 #include "components/omnibox/browser/autocomplete_controller.h"
 #include "components/omnibox/browser/omnibox_view.h"
-#include "components/search_engines/template_url_service.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/geolocation_provider.h"
@@ -76,7 +76,6 @@
 #include "ui/aura/window_event_dispatcher.h"
 #endif
 
-using content::NativeWebKeyboardEvent;
 using content::NavigationController;
 using content::NavigationEntry;
 using content::OpenURLParams;
@@ -149,7 +148,6 @@
   content::WaitForLoadStop(params->target_contents);
 }
 
-
 void NavigateToURLWithPost(Browser* browser, const GURL& url) {
   chrome::NavigateParams params(browser, url,
                                 ui::PAGE_TRANSITION_FORM_SUBMIT);
@@ -326,20 +324,6 @@
   return observer.number_of_matches();
 }
 
-void WaitForTemplateURLServiceToLoad(TemplateURLService* service) {
-  if (service->loaded())
-    return;
-  scoped_refptr<content::MessageLoopRunner> message_loop_runner =
-      new content::MessageLoopRunner;
-  scoped_ptr<TemplateURLService::Subscription> subscription =
-      service->RegisterOnLoadedCallback(
-          message_loop_runner->QuitClosure());
-  service->Load();
-  message_loop_runner->Run();
-
-  ASSERT_TRUE(service->loaded());
-}
-
 void DownloadURL(Browser* browser, const GURL& download_url) {
   base::ScopedTempDir downloads_directory;
   ASSERT_TRUE(downloads_directory.CreateUniqueTempDir());
@@ -371,12 +355,12 @@
   }
 }
 
-Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers) {
+Browser* GetBrowserNotInSet(const std::set<Browser*>& excluded_browsers) {
   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
     if (excluded_browsers.find(*it) == excluded_browsers.end())
       return *it;
   }
-  return NULL;
+  return nullptr;
 }
 
 namespace {
diff --git a/chrome/test/base/ui_test_utils.h b/chrome/test/base/ui_test_utils.h
index e5a359a..cd95c4b 100644
--- a/chrome/test/base/ui_test_utils.h
+++ b/chrome/test/base/ui_test_utils.h
@@ -29,7 +29,6 @@
 class Browser;
 class LocationBar;
 class Profile;
-class TemplateURLService;
 
 namespace app_modal {
 class AppModalDialog;
@@ -143,9 +142,6 @@
                int* ordinal,
                gfx::Rect* selection_rect);
 
-// Blocks until |service| finishes loading.
-void WaitForTemplateURLServiceToLoad(TemplateURLService* service);
-
 // Blocks until the |history_service|'s history finishes loading.
 void WaitForHistoryToLoad(history::HistoryService* history_service);
 
@@ -157,7 +153,7 @@
                             const std::string& input);
 
 // Gets the first browser that is not in the specified set.
-Browser* GetBrowserNotInSet(std::set<Browser*> excluded_browsers);
+Browser* GetBrowserNotInSet(const std::set<Browser*>& excluded_browsers);
 
 // Gets the size and value of the cookie string for |url| in the given tab.
 // Can be called from any thread.
diff --git a/chrome/test/base/view_event_test_platform_part_chromeos.cc b/chrome/test/base/view_event_test_platform_part_chromeos.cc
index a73733f..37f48fb 100644
--- a/chrome/test/base/view_event_test_platform_part_chromeos.cc
+++ b/chrome/test/base/view_event_test_platform_part_chromeos.cc
@@ -13,6 +13,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
 #include "content/public/browser/browser_thread.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/message_center/message_center.h"
@@ -44,6 +45,10 @@
   // also create the message center.
   message_center::MessageCenter::Initialize();
   chromeos::DBusThreadManager::Initialize();
+  bluez::BluezDBusManager::Initialize(
+      chromeos::DBusThreadManager::Get()->GetSystemBus(),
+      chromeos::DBusThreadManager::Get()->IsUsingStub(
+          chromeos::DBusClientBundle::BLUETOOTH));
   chromeos::CrasAudioHandler::InitializeForTesting();
   chromeos::NetworkHandler::Initialize();
 
@@ -66,6 +71,7 @@
 
   chromeos::NetworkHandler::Shutdown();
   chromeos::CrasAudioHandler::Shutdown();
+  bluez::BluezDBusManager::Shutdown();
   chromeos::DBusThreadManager::Shutdown();
   // Ash Shell can't just live on its own without a browser process, we need to
   // also shut down the message center.
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc
index a5de5924..0651dc4 100644
--- a/chrome/test/base/web_ui_browser_test.cc
+++ b/chrome/test/base/web_ui_browser_test.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/web_ui_test_handler.h"
 #include "chrome/common/chrome_paths.h"
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index 667d5e99..bedca63 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -89,7 +89,7 @@
   (*session_remaining_count)--;
 
   scoped_ptr<base::DictionaryValue> session(new base::DictionaryValue());
-  session->Set("sessionId", new base::StringValue(session_id));
+  session->Set("id", new base::StringValue(session_id));
   session->Set("capabilities", value->DeepCopy());
   session_list->Append(session.release());
 
diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc
index a0e0a5e..ba36d1e6 100644
--- a/chrome/test/chromedriver/commands_unittest.cc
+++ b/chrome/test/chromedriver/commands_unittest.cc
@@ -93,8 +93,8 @@
   base::DictionaryValue* session1_capabilities;
   base::DictionaryValue* session2_capabilities;
 
-  ASSERT_TRUE(session1->GetString("sessionId", &session1_id));
-  ASSERT_TRUE(session2->GetString("sessionId", &session2_id));
+  ASSERT_TRUE(session1->GetString("id", &session1_id));
+  ASSERT_TRUE(session2->GetString("id", &session2_id));
   ASSERT_TRUE(session1->GetDictionary("capabilities", &session1_capabilities));
   ASSERT_TRUE(session2->GetDictionary("capabilities", &session2_capabilities));
 
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index d802bdd..d84d3ed 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -486,6 +486,14 @@
     # Test clicking element in the sub frame.
     self.testClickElement()
 
+  def testClickElementAfterNavigation(self):
+    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/link_nav.html'))
+    link = self._driver.FindElement('id', 'l1')
+    link.Click()
+    alert_button = self._driver.FindElement('id', 'aa1')
+    alert_button.Click()
+    self.assertTrue(self._driver.IsAlertOpen())
+
   def testClearElement(self):
     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
     text = self._driver.ExecuteScript(
@@ -534,6 +542,15 @@
     self._driver.GoForward()
     self.assertEquals('about:blank', self._driver.GetCurrentUrl())
 
+  def testBackNavigationAfterClickElement(self):
+    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/link_nav.html'))
+    link = self._driver.FindElement('id', 'l1')
+    link.Click()
+    self._driver.GoBack()
+    self.assertNotEqual('data:,', self._driver.GetCurrentUrl())
+    self.assertEquals(self.GetHttpUrlForFile('/chromedriver/link_nav.html'),
+                      self._driver.GetCurrentUrl())
+
   def testRefresh(self):
     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
     self._driver.Refresh()
diff --git a/chrome/test/data/autofill/heuristics/output/01_autocomplete_attribute_advanced.out b/chrome/test/data/autofill/heuristics/output/01_autocomplete_attribute_advanced.out
index 6d7e7437..5c8f2b4b 100644
--- a/chrome/test/data/autofill/heuristics/output/01_autocomplete_attribute_advanced.out
+++ b/chrome/test/data/autofill/heuristics/output/01_autocomplete_attribute_advanced.out
@@ -1,9 +1,3 @@
-PHONE_HOME_WHOLE_NUMBER | 4.phone |  |  | 4.phone_1-default
-EMAIL_ADDRESS | 4.email |  |  | 4.phone_1-default
-UNKNOWN_TYPE | 4.a |  |  | 4.phone_1-default
-UNKNOWN_TYPE | 4.b |  |  | 4.phone_1-default
-UNKNOWN_TYPE | 4.c |  |  | 4.phone_1-default
-ADDRESS_HOME_CITY | 4.city |  |  | 4.phone_1-default
 HTML_TYPE_NAME | 1.n |  |  | -default-default
 HTML_TYPE_EMAIL | 1.e |  |  | -default-default
 HTML_TYPE_ADDRESS_LINE1 | 1.a |  |  | one-shipping-default
@@ -15,3 +9,9 @@
 UNKNOWN_TYPE | 3.email |  |  | 3.name_1-default
 UNKNOWN_TYPE | 3.o |  |  | 3.name_1-default
 UNKNOWN_TYPE | 3.address |  |  | 3.name_1-default
+PHONE_HOME_WHOLE_NUMBER | 4.phone |  |  | 4.phone_1-default
+EMAIL_ADDRESS | 4.email |  |  | 4.phone_1-default
+UNKNOWN_TYPE | 4.a |  |  | 4.phone_1-default
+UNKNOWN_TYPE | 4.b |  |  | 4.phone_1-default
+UNKNOWN_TYPE | 4.c |  |  | 4.phone_1-default
+ADDRESS_HOME_CITY | 4.city |  |  | 4.phone_1-default
diff --git a/chrome/test/data/chromedriver/link_nav.html b/chrome/test/data/chromedriver/link_nav.html
new file mode 100644
index 0000000..d2cf1cd
--- /dev/null
+++ b/chrome/test/data/chromedriver/link_nav.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title>Link Navigation Page</title>
+  </head>
+  <body>
+    <nav>
+      <a id ="l1" href="subpage_linknav.html">Link</a>
+    </nav>
+  </body>
+</html>
diff --git a/chrome/test/data/chromedriver/subpage_linknav.html b/chrome/test/data/chromedriver/subpage_linknav.html
new file mode 100644
index 0000000..aa9b57dd
--- /dev/null
+++ b/chrome/test/data/chromedriver/subpage_linknav.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title>Sub Page of Link Navigation</title>
+  </head>
+  <body>
+    <iframe width="200" height="200" src="frame_test.html"></iframe>
+    <button id="aa1" onclick="alert('Hi')"> alert</button>
+  </body>
+</html>
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/app_main.html b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/app_main.html
new file mode 100644
index 0000000..002e8d9
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/app_main.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h1>Test Kiosk App, version: 24.0.0</h1>
+</body>
+<hmtl>
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-128.png b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-128.png
new file mode 100644
index 0000000..5c226f3
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-128.png
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-16.png b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-16.png
new file mode 100644
index 0000000..c7510d38
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/icon-16.png
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/main.js b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/main.js
new file mode 100644
index 0000000..15cb92d
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/main.js
@@ -0,0 +1,11 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.app.runtime.onLaunched.addListener(function(launchData) {
+  chrome.app.window.create('app_main.html',
+      { 'width': 1920,
+        'height': 1080 },
+      function(window) {
+  });
+});
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/manifest.json b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/manifest.json
new file mode 100644
index 0000000..cb698e6
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/primary_app/v24/manifest.json
@@ -0,0 +1,20 @@
+{
+  "manifest_version": 2,
+  "name": "Test Kiosk App for multi-apps",
+  "minimum_chrome_version": "24.0.1307.0",
+  "version": "24.0.0",
+  "icons": {
+    "128": "icon-128.png",
+    "16": "icon-16.png"
+  },
+  "app": {
+    "background": {
+      "scripts": ["main.js"]
+    }
+  },
+  "kiosk_enabled": true,
+  "offline_enabled": true,
+  "kiosk_secondary_apps": [
+    {"id": "imlgadjgphbjkaceoiapiephhgeofhic"}
+  ]
+}
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-128.png b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-128.png
new file mode 100644
index 0000000..5c226f3
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-128.png
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-16.png b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-16.png
new file mode 100644
index 0000000..c7510d38
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/icon-16.png
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/main.js b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/main.js
new file mode 100644
index 0000000..3357a5e
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/main.js
@@ -0,0 +1,12 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.runtime.onMessageExternal.addListener(
+  function(request, sender, sendResponse) {
+    if (sender.id != 'ceobkcclegcliomogfoeoheahogoecgl')
+      return;
+
+    if (request.ping)
+      sendResponse({pingResponse: 'true'});
+});
diff --git a/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/manifest.json b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/manifest.json
new file mode 100644
index 0000000..93e183c
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/multi_app_kiosk/src/secondary_extension_1/manifest.json
@@ -0,0 +1,15 @@
+{
+  "manifest_version": 2,
+  "name": "Kiosk secondary extension for testing",
+  "minimum_chrome_version": "24.0.1307.0",
+  "version": "1.0.0",
+  "icons": {
+    "128": "icon-128.png",
+    "16": "icon-16.png"
+  },
+  "background": {
+     "scripts": ["main.js"]
+  },
+  "kiosk_enabled": true,
+  "offline_enabled": true
+}
diff --git a/chrome/test/data/chromeos/app_mode/webstore/downloads/ceobkcclegcliomogfoeoheahogoecgl-24.0.0.crx b/chrome/test/data/chromeos/app_mode/webstore/downloads/ceobkcclegcliomogfoeoheahogoecgl-24.0.0.crx
new file mode 100644
index 0000000..df8d87b
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/webstore/downloads/ceobkcclegcliomogfoeoheahogoecgl-24.0.0.crx
Binary files differ
diff --git a/chrome/test/data/chromeos/app_mode/webstore/downloads/imlgadjgphbjkaceoiapiephhgeofhic-1.0.0.crx b/chrome/test/data/chromeos/app_mode/webstore/downloads/imlgadjgphbjkaceoiapiephhgeofhic-1.0.0.crx
new file mode 100644
index 0000000..23d0e6a3
--- /dev/null
+++ b/chrome/test/data/chromeos/app_mode/webstore/downloads/imlgadjgphbjkaceoiapiephhgeofhic-1.0.0.crx
Binary files differ
diff --git a/chrome/test/data/downloads/iframe-src-is-a-download.htm b/chrome/test/data/downloads/iframe-src-is-a-download.htm
new file mode 100644
index 0000000..008ba93
--- /dev/null
+++ b/chrome/test/data/downloads/iframe-src-is-a-download.htm
@@ -0,0 +1,18 @@
+<html>
+<body>
+This tests that we can serialize a page that has a downloaded url in an iframe without crashing.
+
+<!-- iframe.src points to non-existing resource.
+     in 45.0.2454.85 save-as-complete-html points the saved frame to
+     a local/saved copy in foo_files/saved_resource.html which contains
+     serialized contents of the built-in "The file or directory could
+     not be found" page. -->
+<iframe src="no-such-file.exe"></iframe>
+
+<!-- iframe.src points to a "download".
+     in 45.0.2454.85 save-as-complete-html points the saved frame to
+     about:blank -->
+<iframe src="thisdayinhistory.xls"></iframe>
+
+</body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
index 33740bf..bcba371 100644
--- a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
@@ -483,6 +483,7 @@
             Carrier: 'Cellular1_Carrier',
             Family: 'GSM',
             HomeProvider: {
+              Code: '000000',
               Country: 'us',
               Name: 'Cellular1_Provider'
             },
diff --git a/chrome/test/data/extensions/api_test/preference/data_reduction_proxy/test.js b/chrome/test/data/extensions/api_test/preference/data_reduction_proxy/test.js
index bfda107e..ffcaabff 100644
--- a/chrome/test/data/extensions/api_test/preference/data_reduction_proxy/test.js
+++ b/chrome/test/data/extensions/api_test/preference/data_reduction_proxy/test.js
@@ -130,20 +130,30 @@
           }));
     });
   },
-  // DISABLED: crbug.com/535618
-  // Flaky on Mac 10.8, Mac 64 ASAN, and other Mac bots.
-  /*
   function dataUsageReporting() {
     dataReductionProxy.dataUsageReportingEnabled.set({ 'value': true });
 
-    setTimeout(function() {
-      dataReductionProxy.getDataUsage(chrome.test.callbackPass(
+    // Data usage reporting takes some time to initialize before a call to
+    // |getDataUsage| is successful. If |getDataUsage| gives us an empty array,
+    // we retry after some delay. Test will report failure if the expected
+    // data usage is not returned after 20 retries.
+    var verifyDataUsage = function(numRetries) {
+      chrome.test.assertTrue(numRetries != 0);
+
+      setTimeout(chrome.test.callbackPass(function() {
+        dataReductionProxy.getDataUsage(chrome.test.callbackPass(
           function(data_usage) {
             chrome.test.assertTrue('data_usage_buckets' in data_usage);
-            chrome.test.assertEq(17280,
-                                 data_usage['data_usage_buckets'].length);
-      }));
-    }, 1000);
+            if (data_usage['data_usage_buckets'].length == 0) {
+              verifyDataUsage(numRetries - 1);
+            } else {
+              chrome.test.assertEq(17280,
+                                   data_usage['data_usage_buckets'].length);
+            }
+        }));
+      }), 1000);
+    };
+
+    verifyDataUsage(20);
   }
-  */
 ]);
diff --git a/chrome/test/data/extensions/platform_apps/launch_file/test.js b/chrome/test/data/extensions/platform_apps/launch_file/test.js
index b4ff0c8..90eb6de 100644
--- a/chrome/test/data/extensions/platform_apps/launch_file/test.js
+++ b/chrome/test/data/extensions/platform_apps/launch_file/test.js
@@ -3,13 +3,15 @@
 // found in the LICENSE file.
 
 chrome.app.runtime.onLaunched.addListener(function (launchData) {
-  // Test that the isKioskSession field is |false| and the id and items fields
-  // can be read in the launch data.
+  // Test that the isKioskSession field and isPublicSession are |false| and the
+  // id and items fields can be read in the launch data.
   chrome.test.runTests([
     function testFileHandler() {
       chrome.test.assertFalse(!launchData, "No launchData");
       chrome.test.assertFalse(launchData.isKioskSession,
           "launchData.isKioskSession incorrect");
+      chrome.test.assertFalse(launchData.isPublicSession,
+          "launchData.isPublicSesion incorrect");
       chrome.test.assertEq(launchData.id, "text",
           "launchData.id incorrect");
       chrome.test.assertEq(launchData.items.length, 1);
diff --git a/chrome/test/data/extensions/platform_apps/launch_whitelisted_ext_with_file/test.js b/chrome/test/data/extensions/platform_apps/launch_whitelisted_ext_with_file/test.js
index 82fc0793..45d7955f 100644
--- a/chrome/test/data/extensions/platform_apps/launch_whitelisted_ext_with_file/test.js
+++ b/chrome/test/data/extensions/platform_apps/launch_whitelisted_ext_with_file/test.js
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 chrome.app.runtime.onLaunched.addListener(function (launchData) {
-  // Test that the isKioskSession field is |false| and the id and items fields
-  // can be read in the launch data.
+  // Test that the isKioskSession field and isPublicSession fields are |false|
+  // and the id and items fields can be read in the launch data.
   chrome.test.runTests([
     function checkNoChromeApp() {
       chrome.test.assertEq(undefined, chrome.app.getIsInstalled);
@@ -15,6 +15,8 @@
       chrome.test.assertFalse(!launchData, "No launchData");
       chrome.test.assertFalse(launchData.isKioskSession,
           "launchData.isKioskSession incorrect");
+      chrome.test.assertFalse(launchData.isPublicSession,
+          "launchData.isPublicSession incorrect");
       chrome.test.assertEq(launchData.id, "text",
           "launchData.id incorrect");
       chrome.test.assertEq(launchData.items.length, 1);
diff --git a/chrome/test/data/extensions/ui/browser_action_popup/popup.js b/chrome/test/data/extensions/ui/browser_action_popup/popup.js
index d483fac8..73f3beb 100644
--- a/chrome/test/data/extensions/ui/browser_action_popup/popup.js
+++ b/chrome/test/data/extensions/ui/browser_action_popup/popup.js
@@ -2,4 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-chrome.test.sendMessage('Popup opened');
+// Wait for the window to fully load, since that's when the popup is shown.
+window.onload = function() {
+  window.setTimeout(function() {
+    chrome.test.sendMessage('Popup opened');
+  }, 0);
+};
diff --git a/chrome/test/data/push_messaging/push_test.js b/chrome/test/data/push_messaging/push_test.js
index 1ed8f816..eb709c8 100644
--- a/chrome/test/data/push_messaging/push_test.js
+++ b/chrome/test/data/push_messaging/push_test.js
@@ -106,12 +106,12 @@
   }).catch(sendErrorToTest);
 }
 
-function getCurve25519dh() {
+function GetP256dh() {
   navigator.serviceWorker.ready.then(function(swRegistration) {
     return swRegistration.pushManager.getSubscription()
         .then(function(subscription) {
           sendResultToTest(btoa(String.fromCharCode.apply(null,
-              new Uint8Array(subscription.getKey('curve25519dh')))));
+              new Uint8Array(subscription.getKey('p256dh')))));
         });
   }).catch(sendErrorToTest);
 }
diff --git a/chrome/test/data/save_page/iframes.htm b/chrome/test/data/save_page/iframes.htm
new file mode 100644
index 0000000..b346b7c
--- /dev/null
+++ b/chrome/test/data/save_page/iframes.htm
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head></head>
+<body>
+  <h1>Test page features</h1>
+
+  This page has two iframes: one is cross-site, the other is same-site.
+  This helps test save-page when page spans multiple renderer processes.
+
+  This page has iframes - this exercises a different link-to-local-path
+  replacement code than the one used for non-frames / for savable-resources.
+
+  This page references /save_page/1.png resource from both
+  1) the main frame and 2) the /save_page/b.htm same-site subframe
+  (same-site means that #1 and #2 refer to 1.png via the same url).
+  This helps test that savable resources are deduplicated across frames.
+
+  <h1>Test content</h1>
+
+  <iframe src="/cross-site/bar.com/save_page/a.htm"></iframe>
+  <iframe src="b.htm"></iframe>
+  <img src="1.png"/>
+</body>
+</html>
diff --git a/chrome/test/data/ssl/iframe_with_insecure_content.html b/chrome/test/data/ssl/iframe_with_insecure_content.html
new file mode 100644
index 0000000..1771240a
--- /dev/null
+++ b/chrome/test/data/ssl/iframe_with_insecure_content.html
@@ -0,0 +1,10 @@
+<html>
+<head><title>Page that runs insecure content</title></head>
+<body>
+</body>
+<script>
+var s = document.createElement("script");
+s.src = "http://" + document.location.hostname + ":" + document.location.port + "/files/ssl/randomize_hash.js";
+document.body.appendChild(s);
+</script>
+</html>
diff --git a/chrome/test/data/ssl/page_runs_and_displays_insecure_content.html b/chrome/test/data/ssl/page_runs_and_displays_insecure_content.html
new file mode 100644
index 0000000..f1dbb3f
--- /dev/null
+++ b/chrome/test/data/ssl/page_runs_and_displays_insecure_content.html
@@ -0,0 +1,9 @@
+<html>
+<head><title>Page that runs and displays insecure content</title></head>
+<body>
+This page contains an script and an image which is served over an http connection,
+causing insecure content (when this page is loaded over https).<br>
+<script src="http://REPLACE_WITH_HOST_AND_PORT/files/ssl/randomize_hash.js"></script>
+<img src="http://REPLACE_WITH_HOST_AND_PORT/files/ssl/google_files/logo.gif"/>
+</body>
+</html>
diff --git a/chrome/test/data/ssl/page_runs_insecure_content_in_iframe.html b/chrome/test/data/ssl/page_runs_insecure_content_in_iframe.html
new file mode 100644
index 0000000..95f7655
--- /dev/null
+++ b/chrome/test/data/ssl/page_runs_insecure_content_in_iframe.html
@@ -0,0 +1,8 @@
+<html>
+<head><title>Page that runs insecure content in an iframe</title></head>
+<body>
+This page contains an iframe which loads contents over an http connection,
+causing insecure content (when this page is loaded over https).<br>
+<iframe src="https://REPLACE_WITH_HOST_AND_PORT/files/ssl/iframe_with_insecure_content.html"/>
+</body>
+</html>
diff --git a/chrome/test/data/webui/print_preview.js b/chrome/test/data/webui/print_preview.js
index 4fed7233..b4f8dac 100644
--- a/chrome/test/data/webui/print_preview.js
+++ b/chrome/test/data/webui/print_preview.js
@@ -465,30 +465,6 @@
   this.waitForAnimationToEnd('other-options-collapsible');
 });
 
-// When the print scaling is disabled for the source "PDF", we show the fit
-// to page option but the state is unchecked by default.
-TEST_F('PrintPreviewWebUITest', 'PrintScalingDisabledForPlugin', function() {
-  this.initialSettings_.isDocumentModifiable_ = false;
-  this.setInitialSettings();
-  this.setLocalDestinations();
-  this.setCapabilities(getCddTemplate("FooDevice"));
-
-  // Indicate that the PDF does not support scaling by default.
-  var printPresetOptionsEvent = new Event(
-      print_preview.NativeLayer.EventType.PRINT_PRESET_OPTIONS);
-  printPresetOptionsEvent.optionsFromDocument = {disableScaling: true};
-  this.nativeLayer_.dispatchEvent(printPresetOptionsEvent);
-
-  var otherOptions = $('other-options-settings');
-  checkSectionVisible(otherOptions, true);
-  checkElementDisplayed(
-      otherOptions.querySelector('.fit-to-page-container'), true);
-  expectFalse(
-      otherOptions.querySelector('.fit-to-page-checkbox').checked);
-
-  this.waitForAnimationToEnd('other-options-collapsible');
-});
-
 // When the number of copies print preset is set for source 'PDF', we update
 // the copies value if capability is supported by printer.
 TEST_F('PrintPreviewWebUITest', 'CheckNumCopiesPrintPreset', function() {
diff --git a/chrome/test/gpu/webgl_infobar_browsertest.cc b/chrome/test/gpu/webgl_infobar_browsertest.cc
index c82736c..d62469d8 100644
--- a/chrome/test/gpu/webgl_infobar_browsertest.cc
+++ b/chrome/test/gpu/webgl_infobar_browsertest.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -48,7 +49,7 @@
   chrome::Navigate(&params);
 }
 
-} // namespace
+}  // namespace
 
 class WebGLInfoBarTest : public InProcessBrowserTest {
  protected:
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index 470afee..4a03f06 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -33,12 +33,28 @@
 // browser test resources.
 const base::FilePath::StringPieceType kResourcePath = FILE_PATH_LITERAL(
     "media_router/browser_test_resources/");
+const char kTestSinkName[] = "test-sink-1";
 // The javascript snippets.
-const std::string kCheckSessionScript = "checkSession();";
-const std::string kCheckSessionFailedScript = "checkSessionFailedToStart();";
-const std::string kStartSessionScript = "startSession();";
-const std::string kStopSessionScript = "stopSession()";
-const std::string kWaitDeviceScript = "waitUntilDeviceAvailable();";
+const char kCheckSessionScript[] = "checkSession();";
+const char kCheckSessionFailedScript[] = "checkSessionFailedToStart();";
+const char kStartSessionScript[] = "startSession();";
+const char kStopSessionScript[] = "stopSession()";
+const char kWaitDeviceScript[] = "waitUntilDeviceAvailable();";
+const char kChooseSinkScript[] =
+    "var sinks = document.getElementById('media-router-container')."
+    "  shadowRoot.getElementById('sink-list').getElementsByTagName('span');"
+    "for (var i=0; i<sinks.length; i++) {"
+    "  if(sinks[i].textContent=='%s') {"
+    "    sinks[i].click();"
+    "    break;"
+    "}}";
+const char kCloseRouteScript[] =
+    "window.document.getElementById('media-router-container').shadowRoot."
+    "  getElementById('route-details').shadowRoot.getElementById("
+    "    'close-route-button').click()";
+const char kGetRouteLengthScript[] =
+    "domAutomationController.send(window.document.getElementById("
+    "  'media-router-container').routeList.length)";
 
 std::string GetStartedSessionId(content::WebContents* web_contents) {
   std::string session_id;
@@ -120,23 +136,10 @@
 
 void MediaRouterIntegrationBrowserTest::ChooseSink(
     content::WebContents* web_contents,
-    const std::string& sink_id,
-    const std::string& current_route) {
+    const std::string& sink_name) {
   content::WebContents* dialog_contents = GetMRDialog(web_contents);
-  std::string route;
-  if (current_route.empty()) {
-    route = "null";
-  } else {
-    route = current_route;
-    std::string script = base::StringPrintf(
-        "window.document.getElementById('media-router-container')."
-        "currentRoute_ = %s", route.c_str());
-    ASSERT_TRUE(content::ExecuteScript(dialog_contents, script));
-  }
   std::string script = base::StringPrintf(
-      "window.document.getElementById('media-router-container')."
-      "showOrCreateRoute_({'id': '%s', 'name': ''}, %s)",
-      sink_id.c_str(), route.c_str());
+      kChooseSinkScript, sink_name.c_str());
   ASSERT_TRUE(content::ExecuteScript(dialog_contents, script));
 }
 
@@ -211,11 +214,8 @@
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   content::WebContents* dialog_contents = GetMRDialog(web_contents);
-  std::string script;
-  script = base::StringPrintf(
-      "domAutomationController.send(window.document.getElementById("
-      "'media-router-container').routeList.length)");
-  return ExecuteScriptAndExtractInt(dialog_contents, script) == 1;
+  return ExecuteScriptAndExtractInt(dialog_contents,
+                                    kGetRouteLengthScript) == 1;
 }
 
 void MediaRouterIntegrationBrowserTest::WaitUntilRouteCreated() {
@@ -225,6 +225,25 @@
                  base::Unretained(this))));
 }
 
+bool MediaRouterIntegrationBrowserTest::AreRoutesClosedOnUI() {
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::WebContents* dialog_contents = GetMRDialog(web_contents);
+  return ExecuteScriptAndExtractInt(dialog_contents,
+                                    kGetRouteLengthScript) == 0;
+}
+
+void MediaRouterIntegrationBrowserTest::CloseRouteOnUI() {
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::WebContents* dialog_contents = GetMRDialog(web_contents);
+  ASSERT_TRUE(content::ExecuteScript(dialog_contents, kCloseRouteScript));
+  ASSERT_TRUE(ConditionalWait(
+      base::TimeDelta::FromSeconds(10), base::TimeDelta::FromSeconds(1),
+      base::Bind(&MediaRouterIntegrationBrowserTest::AreRoutesClosedOnUI,
+                 base::Unretained(this))));
+}
+
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Basic) {
   OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
   content::WebContents* web_contents =
@@ -232,7 +251,7 @@
   ASSERT_TRUE(web_contents);
   ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript);
   StartSession(web_contents);
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   ExecuteJavaScriptAPI(web_contents, kCheckSessionScript);
   Wait(base::TimeDelta::FromSeconds(5));
 
@@ -255,7 +274,7 @@
   ASSERT_TRUE(web_contents);
   ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript);
   StartSession(web_contents);
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   ExecuteJavaScriptAPI(web_contents, kCheckSessionFailedScript);
 }
 
@@ -268,7 +287,7 @@
   ASSERT_TRUE(web_contents);
   ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript);
   StartSession(web_contents);
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   ExecuteJavaScriptAPI(web_contents, kCheckSessionFailedScript);
 }
 
@@ -280,7 +299,7 @@
   ASSERT_TRUE(web_contents);
   ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript);
   StartSession(web_contents);
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   ExecuteJavaScriptAPI(web_contents, kCheckSessionScript);
   std::string session_id(GetStartedSessionId(web_contents));
 
@@ -309,7 +328,7 @@
   ExecuteJavaScriptAPI(web_contents, kWaitDeviceScript);
   content::TestNavigationObserver test_navigation_observer(web_contents, 1);
   StartSession(web_contents);
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   ExecuteJavaScriptAPI(web_contents, kCheckSessionScript);
   std::string session_id(GetStartedSessionId(web_contents));
 
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h
index 91c3f5d2..9e68e70bf 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.h
+++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -31,10 +31,9 @@
   // Simulate user action to choose one sink in the popup dialog.
   // |web_contents|: The web contents of the test page which invokes the popup
   //                 dialog.
-  // |sink_id|: The sink id.
-  // |current_route|: The JSON string which represents current route.
+  // |sink_name|: The sink's human readable name.
   void ChooseSink(content::WebContents* web_contents,
-                  const std::string& sink_id, const std::string& current_route);
+                  const std::string& sink_name);
 
   // Execute javascript and check the return value.
   static void ExecuteJavaScriptAPI(content::WebContents* web_contents,
@@ -69,6 +68,11 @@
 
   bool IsRouteCreatedOnUI();
 
+  bool AreRoutesClosedOnUI();
+
+  // Close route through clicking 'Stop casting' button in route details dialog.
+  void CloseRouteOnUI();
+
   // Wait for the route to show up in the UI with a timeout. Fails if the
   // route did not show up before the timeout.
   void WaitUntilRouteCreated();
diff --git a/chrome/test/media_router/media_router_integration_ui_browsertest.cc b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
index b1870b3d..d4f50ed 100644
--- a/chrome/test/media_router/media_router_integration_ui_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
@@ -13,6 +13,10 @@
 
 namespace media_router {
 
+namespace {
+const char kTestSinkName[] = "test-sink-1";
+}
+
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Dialog_Basic) {
   OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
   content::WebContents* web_contents =
@@ -20,34 +24,36 @@
   content::WebContents* dialog_contents = OpenMRDialog(web_contents);
 
   // Verify the sink list.
-  std::string script;
-  script = base::StringPrintf(
-      "domAutomationController.send(window.document.getElementById("
-      "'media-router-container').sinkList.length)");
-  ASSERT_EQ(2, ExecuteScriptAndExtractInt(dialog_contents, script));
+  std::string sink_length_script = base::StringPrintf(
+      "domAutomationController.send("
+      "window.document.getElementById('media-router-container')."
+      "sinkList.length)");
+  ASSERT_EQ(2, ExecuteScriptAndExtractInt(dialog_contents, sink_length_script));
 
-  ChooseSink(web_contents, "id1", "");
+  ChooseSink(web_contents, kTestSinkName);
   WaitUntilRouteCreated();
 
-  // Verify the new route.
-  script = base::StringPrintf(
-      "domAutomationController.send(window.document.getElementById("
-      "'media-router-container').routeList[0].description)");
-  std::string route_description = ExecuteScriptAndExtractString(
-      dialog_contents, script);
-  ASSERT_EQ("Test Route", route_description);
+  // Verify the route details page.
+  std::string route_info_script = base::StringPrintf(
+      "domAutomationController.send("
+      "window.document.getElementById('media-router-container').shadowRoot."
+      "getElementById('route-details').shadowRoot.getElementById("
+      "'route-information').getElementsByTagName('span')[0].innerText)");
+  std::string route_information = ExecuteScriptAndExtractString(
+      dialog_contents, route_info_script);
+  ASSERT_EQ("Casting: Test Route", route_information);
 
-  script = base::StringPrintf(
-      "domAutomationController.send(window.document.getElementById("
-      "'media-router-container').routeList[0].id)");
-  std::string route_id = ExecuteScriptAndExtractString(dialog_contents, script);
-  std::string current_route = base::StringPrintf(
-      "{'id': '%s', 'sinkId': '%s', 'description': '%s', 'isLocal': '%s'}",
-      route_id.c_str(), "id1", route_description.c_str(), "false");
+  std::string sink_name_script = base::StringPrintf(
+      "domAutomationController.send("
+      "window.document.getElementById('media-router-container').shadowRoot."
+      "getElementById('route-details').shadowRoot.getElementById('sink-name')."
+      "innerText)");
+  std::string sink_name = ExecuteScriptAndExtractString(
+      dialog_contents, sink_name_script);
+  ASSERT_EQ(kTestSinkName, sink_name);
 
-  ChooseSink(web_contents, "id1", current_route);
-  // TODO(leilei): Verify the router details dialog, including the title and
-  // the text, also close the route.
+  // Close route.
+  CloseRouteOnUI();
 }
 
 }  // namespace media_router
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 50f0a9e..d6de8fc 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -540,6 +540,10 @@
 
 TEST_PPAPI_NACL(VarResource)
 
+#if defined(__i386__)
+TEST_PPAPI_NACL(NaClIRTStackAlignment)
+#endif
+
 // PostMessage tests.
 #define RUN_POSTMESSAGE_SUBTESTS \
   RunTestViaHTTP( \
@@ -1233,6 +1237,7 @@
     LaunchTestingApp(extension_dirname);
     EXPECT_TRUE(listener.WaitUntilSatisfied());
   }
+
  protected:
   std::string toolchain_;
 };
diff --git a/chromecast/base/BUILD.gn b/chromecast/base/BUILD.gn
index c171c1b..2b48a73 100644
--- a/chromecast/base/BUILD.gn
+++ b/chromecast/base/BUILD.gn
@@ -14,6 +14,7 @@
     "android/system_time_change_notifier_android.h",
     "cast_paths.cc",
     "cast_paths.h",
+    "cast_resource.cc",
     "cast_resource.h",
     "chromecast_switches.cc",
     "chromecast_switches.h",
diff --git a/chromecast/base/cast_resource.cc b/chromecast/base/cast_resource.cc
new file mode 100644
index 0000000..cbe9b51
--- /dev/null
+++ b/chromecast/base/cast_resource.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/cast_resource.h"
+
+namespace chromecast {
+
+void CastResource::SetCastResourceClient(Client* client) {
+  client_ = client;
+}
+
+void CastResource::NotifyResourceAcquired() {
+  if (client_)
+    client_->OnResourceAcquired(this);
+}
+
+void CastResource::NotifyResourceReleased(Resource remain) {
+  if (client_)
+    client_->OnResourceReleased(this, remain);
+}
+
+}  // namespace chromecast
diff --git a/chromecast/base/cast_resource.h b/chromecast/base/cast_resource.h
index 8836e9c..cd248d77 100644
--- a/chromecast/base/cast_resource.h
+++ b/chromecast/base/cast_resource.h
@@ -52,17 +52,21 @@
     virtual ~Client() {}
   };
 
-  CastResource() {}
-
-  virtual void SetCastResourceClient(Client* client) = 0;
+  void SetCastResourceClient(Client* client);
   // Called to release resources. Implementation should call
   // Client::OnResourceReleased when resource is released on its side.
   virtual void ReleaseResource(Resource resource) = 0;
 
  protected:
+  CastResource() : client_(nullptr) {}
   virtual ~CastResource() {}
 
+  void NotifyResourceAcquired();
+  void NotifyResourceReleased(Resource remain);
+
  private:
+  Client* client_;
+
   DISALLOW_COPY_AND_ASSIGN(CastResource);
 };
 
diff --git a/chromecast/base/chromecast_switches.cc b/chromecast/base/chromecast_switches.cc
index addc145..94186c8 100644
--- a/chromecast/base/chromecast_switches.cc
+++ b/chromecast/base/chromecast_switches.cc
@@ -12,11 +12,6 @@
 // The bitmask of codecs (media_caps.h) supported by the current HDMI sink.
 const char kHdmiSinkSupportedCodecs[] = "hdmi-sink-supported-codecs";
 
-// Enables old (VIDEO_HOLE) hole punching codepath for video plane.
-// TODO(halliwell): remove switch and old codepath once overlays
-// are well established.
-const char kEnableLegacyHolePunching[] = "enable-legacy-hole-punching";
-
 // Enable file accesses. It should not be enabled for most Cast devices.
 const char kEnableLocalFileAccesses[] = "enable-local-file-accesses";
 
diff --git a/chromecast/base/chromecast_switches.h b/chromecast/base/chromecast_switches.h
index 9f7bd34e..f811db2 100644
--- a/chromecast/base/chromecast_switches.h
+++ b/chromecast/base/chromecast_switches.h
@@ -12,7 +12,6 @@
 // Media switches
 extern const char kEnableCmaMediaPipeline[];
 extern const char kHdmiSinkSupportedCodecs[];
-extern const char kEnableLegacyHolePunching[];
 
 // Content-implementation switches
 extern const char kEnableLocalFileAccesses[];
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index b12a230..744e66d 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -224,8 +224,6 @@
 
     if (browser_command_line->HasSwitch(switches::kEnableCmaMediaPipeline))
       command_line->AppendSwitch(switches::kEnableCmaMediaPipeline);
-    if (browser_command_line->HasSwitch(switches::kEnableLegacyHolePunching))
-      command_line->AppendSwitch(switches::kEnableLegacyHolePunching);
     if (browser_command_line->HasSwitch(switches::kAllowHiddenMediaPlayback))
       command_line->AppendSwitch(switches::kAllowHiddenMediaPlayback);
   }
diff --git a/chromecast/browser/media/BUILD.gn b/chromecast/browser/media/BUILD.gn
index fc5ecbc..a562540 100644
--- a/chromecast/browser/media/BUILD.gn
+++ b/chromecast/browser/media/BUILD.gn
@@ -25,6 +25,5 @@
     "//chromecast/media",
     "//content/public/browser",
     "//media",
-    "//ui/gfx/geometry",
   ]
 }
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.cc b/chromecast/browser/media/cast_browser_cdm_factory.cc
index 956346d4..62a1df25 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.cc
+++ b/chromecast/browser/media/cast_browser_cdm_factory.cc
@@ -15,7 +15,7 @@
 namespace chromecast {
 namespace media {
 
-scoped_ptr<::media::BrowserCdm> CastBrowserCdmFactory::CreateBrowserCdm(
+::media::ScopedBrowserCdmPtr CastBrowserCdmFactory::CreateBrowserCdm(
     const std::string& key_system_name,
     bool use_hw_secure_codecs,
     const ::media::SessionMessageCB& session_message_cb,
@@ -45,12 +45,12 @@
                    ::media::BindToCurrentLoop(legacy_session_error_cb),
                    ::media::BindToCurrentLoop(session_keys_change_cb),
                    ::media::BindToCurrentLoop(session_expiration_update_cb)));
-    return make_scoped_ptr(new BrowserCdmCastUi(
+    return ::media::ScopedBrowserCdmPtr(new BrowserCdmCastUi(
         browser_cdm.Pass(), MediaMessageLoop::GetTaskRunner()));
   }
 
   LOG(INFO) << "No matching key system found.";
-  return scoped_ptr< ::media::BrowserCdm>();
+  return ::media::ScopedBrowserCdmPtr();
 }
 
 scoped_ptr<BrowserCdmCast> CastBrowserCdmFactory::CreatePlatformBrowserCdm(
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.h b/chromecast/browser/media/cast_browser_cdm_factory.h
index 5ec5417..e10858db 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.h
+++ b/chromecast/browser/media/cast_browser_cdm_factory.h
@@ -20,7 +20,7 @@
   ~CastBrowserCdmFactory() override {};
 
   // ::media::BrowserCdmFactory implementation:
-  scoped_ptr<::media::BrowserCdm> CreateBrowserCdm(
+  ::media::ScopedBrowserCdmPtr CreateBrowserCdm(
       const std::string& key_system,
       bool use_hw_secure_codecs,
       const ::media::SessionMessageCB& session_message_cb,
diff --git a/chromecast/browser/media/cma_media_pipeline_client.cc b/chromecast/browser/media/cma_media_pipeline_client.cc
index 7286c76..bca511b6 100644
--- a/chromecast/browser/media/cma_media_pipeline_client.cc
+++ b/chromecast/browser/media/cma_media_pipeline_client.cc
@@ -8,7 +8,7 @@
 namespace chromecast {
 namespace media {
 
-CmaMediaPipelineClient::CmaMediaPipelineClient() : client_(nullptr) {}
+CmaMediaPipelineClient::CmaMediaPipelineClient() {}
 
 CmaMediaPipelineClient::~CmaMediaPipelineClient() {}
 
@@ -19,13 +19,11 @@
 }
 
 void CmaMediaPipelineClient::OnMediaPipelineBackendCreated() {
-  if (client_)
-    client_->OnResourceAcquired(this);
+  NotifyResourceAcquired();
 }
 
 void CmaMediaPipelineClient::OnMediaPipelineBackendDestroyed() {
-  if (client_)
-    client_->OnResourceReleased(this, CastResource::kResourceNone);
+  NotifyResourceReleased(CastResource::kResourceNone);
 }
 
 void CmaMediaPipelineClient::ReleaseResource(CastResource::Resource resource) {
@@ -34,15 +32,8 @@
                                           CastResource::kResourceScreenPrimary);
 
   // TODO(yucliu): media pipeline need to stop audio video seperately
-  if (!(resource & audio_video_resource)) {
-    if (client_)
-      client_->OnResourceReleased(this, audio_video_resource);
-  }
-}
-
-void CmaMediaPipelineClient::SetCastResourceClient(
-    CastResource::Client* client) {
-  client_ = client;
+  if (!(resource & audio_video_resource))
+    NotifyResourceReleased(audio_video_resource);
 }
 
 }  // namespace media
diff --git a/chromecast/browser/media/cma_media_pipeline_client.h b/chromecast/browser/media/cma_media_pipeline_client.h
index 36eccb32..0d0e0950 100644
--- a/chromecast/browser/media/cma_media_pipeline_client.h
+++ b/chromecast/browser/media/cma_media_pipeline_client.h
@@ -27,13 +27,10 @@
 
   // cast::CastResource implementations
   void ReleaseResource(CastResource::Resource resource) override;
-  void SetCastResourceClient(CastResource::Client* client) override;
 
  protected:
   ~CmaMediaPipelineClient() override;
 
-  CastResource::Client* client_;
-
  private:
   friend class base::RefCounted<CmaMediaPipelineClient>;
   DISALLOW_COPY_AND_ASSIGN(CmaMediaPipelineClient);
diff --git a/chromecast/browser/media/cma_message_filter_host.cc b/chromecast/browser/media/cma_message_filter_host.cc
index 5503448d8..0a531e71 100644
--- a/chromecast/browser/media/cma_message_filter_host.cc
+++ b/chromecast/browser/media/cma_message_filter_host.cc
@@ -24,9 +24,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "media/base/bind_to_current_loop.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/quad_f.h"
-#include "ui/gfx/geometry/size.h"
 
 namespace chromecast {
 namespace media {
@@ -128,174 +125,6 @@
                  browser_cdm_cast));
 }
 
-// TODO(halliwell): remove this and the NotifyExternalSurface path once
-// VIDEO_HOLE is no longer required.
-void EstimateVideoPlaneRect(const gfx::QuadF& quad,
-                            VideoPlane::Transform* transform,
-                            RectF* rect) {
-  const gfx::PointF& p0 = quad.p1();
-  const gfx::PointF& p1 = quad.p2();
-  const gfx::PointF& p2 = quad.p3();
-  const gfx::PointF& p3 = quad.p4();
-
-  float det0 = p0.x() * p1.y() - p1.x() * p0.y();
-  float det1 = p1.x() * p2.y() - p2.x() * p1.y();
-  float det2 = p2.x() * p3.y() - p3.x() * p2.y();
-  float det3 = p3.x() * p0.y() - p0.x() * p3.y();
-
-  // Calculate the area of the quad (i.e. moment 0 of the polygon).
-  // Note: the area can here be either positive or negative
-  // depending on whether the quad is clock wise or counter clock wise.
-  float area = 0.5 * (det0 + det1 + det2 + det3);
-  if (area == 0.0) {
-    // Empty rectangle in that case.
-    *transform = VideoPlane::TRANSFORM_NONE;
-    *rect = RectF(p0.x(), p0.y(), 0.0, 0.0);
-    return;
-  }
-
-  // Calculate the center of gravity of the polygon
-  // (i.e. moment 1 of the polygon).
-  float cx = (1.0 / (6.0 * area)) *
-      ((p0.x() + p1.x()) * det0 +
-       (p1.x() + p2.x()) * det1 +
-       (p2.x() + p3.x()) * det2 +
-       (p3.x() + p0.x()) * det3);
-  float cy = (1.0 / (6.0 * area)) *
-      ((p0.y() + p1.y()) * det0 +
-       (p1.y() + p2.y()) * det1 +
-       (p2.y() + p3.y()) * det2 +
-       (p3.y() + p0.y()) * det3);
-
-  // For numerical stability, subtract the center of gravity now instead of
-  // later doing:
-  // mxx -= cx * cx;
-  // myy -= cy * cy;
-  // mxy -= cx * cy;
-  // to get the centered 2nd moments.
-  gfx::PointF p0c(p0.x() - cx, p0.y() - cy);
-  gfx::PointF p1c(p1.x() - cx, p1.y() - cy);
-  gfx::PointF p2c(p2.x() - cx, p2.y() - cy);
-  gfx::PointF p3c(p3.x() - cx, p3.y() - cy);
-
-  // Calculate the second moments of the polygon.
-  float det0c = p0c.x() * p1c.y() - p1c.x() * p0c.y();
-  float det1c = p1c.x() * p2c.y() - p2c.x() * p1c.y();
-  float det2c = p2c.x() * p3c.y() - p3c.x() * p2c.y();
-  float det3c = p3c.x() * p0c.y() - p0c.x() * p3c.y();
-  float mxx = (1.0 / (12.0 * area)) *
-      ((p0c.x() * p0c.x() + p0c.x() * p1c.x() + p1c.x() * p1c.x()) * det0c +
-       (p1c.x() * p1c.x() + p1c.x() * p2c.x() + p2c.x() * p2c.x()) * det1c +
-       (p2c.x() * p2c.x() + p2c.x() * p3c.x() + p3c.x() * p3c.x()) * det2c +
-       (p3c.x() * p3c.x() + p3c.x() * p0c.x() + p0c.x() * p0c.x()) * det3c);
-  float myy = (1.0 / (12.0 * area)) *
-      ((p0c.y() * p0c.y() + p0c.y() * p1c.y() + p1c.y() * p1c.y()) * det0c +
-       (p1c.y() * p1c.y() + p1c.y() * p2c.y() + p2c.y() * p2c.y()) * det1c +
-       (p2c.y() * p2c.y() + p2c.y() * p3c.y() + p3c.y() * p3c.y()) * det2c +
-       (p3c.y() * p3c.y() + p3c.y() * p0c.y() + p0c.y() * p0c.y()) * det3c);
-
-  // Remark: the 2nd moments of a rotated & centered rectangle are given by:
-  // mxx = (1/12) * (h^2 * s^2 + w^2 * c^2)
-  // myy = (1/12) * (h^2 * c^2 + w^2 * s^2)
-  // mxy = (1/12) * (w^2 - h^2) * c * s
-  // where w = width of the original rectangle,
-  //       h = height of the original rectangle,
-  //       c = cos(teta) with teta the angle of the rotation,
-  //       s = sin(teta)
-  //
-  // For reference, mxy can be calculated from the quad using:
-  // float mxy = (1.0 / (24.0 * area)) *
-  //    ((2.0 * p0c.x() * p0c.y() + p0c.x() * p1c.y() + p1c.x() * p0c.y() +
-  //      2.0 * p1c.x() * p1c.y()) * det0c +
-  //     (2.0 * p1c.x() * p1c.y() + p1c.x() * p2c.y() + p2c.x() * p1c.y() +
-  //      2.0 * p2c.x() * p2c.y()) * det1c +
-  //     (2.0 * p2c.x() * p2c.y() + p2c.x() * p3c.y() + p3c.x() * p2c.y() +
-  //      2.0 * p3c.x() * p3c.y()) * det2c +
-  //     (2.0 * p3c.x() * p3c.y() + p3c.x() * p0c.y() + p0c.x() * p3c.y() +
-  //      2.0 * p0c.x() * p0c.y()) * det3c);
-
-  // The rotation is assumed to be 0, 90, 180 or 270 degrees, so mxy = 0.0
-  // Using this assumption: mxx = (1/12) h^2 or (1/12) w^2 depending on the
-  // rotation. Same for myy.
-  if (mxx < 0 || myy < 0) {
-    // mxx and myy should be positive, only numerical errors can lead to a
-    // negative value.
-    LOG(WARNING) << "Numerical errors: " << mxx << " " << myy;
-    *transform = VideoPlane::TRANSFORM_NONE;
-    *rect = RectF(p0.x(), p0.y(), 0.0, 0.0);
-    return;
-  }
-  float size_x = sqrt(12.0 * mxx);
-  float size_y = sqrt(12.0 * myy);
-
-  // Estimate the parameters of the rotation since teta can only be known
-  // modulo 90 degrees. In previous equations, you can always swap w and h
-  // and subtract 90 degrees to teta to get the exact same second moment.
-  int idx_best = -1;
-  float err_best = 0.0;
-
-  // First, estimate the rotation angle assuming
-  // dist(p0,p1) is equal to |size_x|,
-  // dist(p0,p3) is equal to |size_y|.
-  gfx::PointF r1(size_x, 0);
-  gfx::PointF r2(size_x, size_y);
-  gfx::PointF r3(0, size_y);
-  for (int k = 0; k < 4; k++) {
-    float cur_err =
-        fabs((p1.x() - p0.x()) - r1.x()) + fabs((p1.y() - p0.y()) - r1.y()) +
-        fabs((p2.x() - p0.x()) - r2.x()) + fabs((p2.y() - p0.y()) - r2.y()) +
-        fabs((p3.x() - p0.x()) - r3.x()) + fabs((p3.y() - p0.y()) - r3.y());
-    if (idx_best < 0 || cur_err < err_best) {
-      idx_best = k;
-      err_best = cur_err;
-    }
-    // 90 degree rotation.
-    r1 = gfx::PointF(-r1.y(), r1.x());
-    r2 = gfx::PointF(-r2.y(), r2.x());
-    r3 = gfx::PointF(-r3.y(), r3.x());
-  }
-
-  // Then, estimate the rotation angle assuming:
-  // dist(p0,p1) is equal to |size_y|,
-  // dist(p0,p3) is equal to |size_x|.
-  r1 = gfx::PointF(size_y, 0);
-  r2 = gfx::PointF(size_y, size_x);
-  r3 = gfx::PointF(0, size_x);
-  for (int k = 0; k < 4; k++) {
-    float cur_err =
-        fabs((p1.x() - p0.x()) - r1.x()) + fabs((p1.y() - p0.y()) - r1.y()) +
-        fabs((p2.x() - p0.x()) - r2.x()) + fabs((p2.y() - p0.y()) - r2.y()) +
-        fabs((p3.x() - p0.x()) - r3.x()) + fabs((p3.y() - p0.y()) - r3.y());
-    if (idx_best < 0 || cur_err < err_best) {
-      idx_best = k;
-      err_best = cur_err;
-    }
-    // 90 degree rotation.
-    r1 = gfx::PointF(-r1.y(), r1.x());
-    r2 = gfx::PointF(-r2.y(), r2.x());
-    r3 = gfx::PointF(-r3.y(), r3.x());
-  }
-
-  *transform = static_cast<VideoPlane::Transform>(idx_best);
-  *rect = RectF(cx - size_x / 2.0, cy - size_y / 2.0, size_x, size_y);
-}
-
-void UpdateVideoSurfaceHost(int surface_id, const gfx::QuadF& quad) {
-  // Currently supports only one video plane.
-  CHECK_EQ(surface_id, 0);
-
-  // Convert quad into rect + transform
-  VideoPlane::Transform transform = VideoPlane::TRANSFORM_NONE;
-  RectF rect(0, 0, 0, 0);
-  EstimateVideoPlaneRect(quad, &transform, &rect);
-
-  VideoPlane* video_plane = CastMediaShlib::GetVideoPlane();
-  video_plane->SetGeometry(
-      rect,
-      VideoPlane::COORDINATE_TYPE_GRAPHICS_PLANE,
-      transform);
-}
-
 }  // namespace
 
 CmaMessageFilterHost::CmaMessageFilterHost(
@@ -337,8 +166,6 @@
     IPC_MESSAGE_HANDLER(CmaHostMsg_SetPlaybackRate, SetPlaybackRate)
     IPC_MESSAGE_HANDLER(CmaHostMsg_SetVolume, SetVolume)
     IPC_MESSAGE_HANDLER(CmaHostMsg_NotifyPipeWrite, NotifyPipeWrite)
-    IPC_MESSAGE_HANDLER(CmaHostMsg_NotifyExternalSurface,
-                        NotifyExternalSurface)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -638,17 +465,6 @@
   FORWARD_CALL(media_pipeline, NotifyPipeWrite, track_id);
 }
 
-void CmaMessageFilterHost::NotifyExternalSurface(
-    int surface_id,
-    const gfx::PointF& p0, const gfx::PointF& p1,
-    const gfx::PointF& p2, const gfx::PointF& p3) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&UpdateVideoSurfaceHost, surface_id,
-                 gfx::QuadF(p0, p1, p2, p3)));
-}
-
 // *** Browser to renderer messages ***
 
 void CmaMessageFilterHost::OnMediaStateChanged(
diff --git a/chromecast/browser/media/cma_message_filter_host.h b/chromecast/browser/media/cma_message_filter_host.h
index 48e95ff..c109f93 100644
--- a/chromecast/browser/media/cma_message_filter_host.h
+++ b/chromecast/browser/media/cma_message_filter_host.h
@@ -24,7 +24,6 @@
 }
 
 namespace gfx {
-class PointF;
 class Size;
 }
 
@@ -89,9 +88,6 @@
   void SetPlaybackRate(int media_id, double playback_rate);
   void SetVolume(int media_id, TrackId track_id, float volume);
   void NotifyPipeWrite(int media_id, TrackId track_id);
-  void NotifyExternalSurface(int surface_id,
-                             const gfx::PointF& p0, const gfx::PointF& p1,
-                             const gfx::PointF& p2, const gfx::PointF& p3);
 
   // Audio/Video callbacks.
   void OnMediaStateChanged(int media_id,
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index 5fe8adb..016374ab 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -22,15 +22,6 @@
   # be named "libcast_graphics_1.0".
   libcast_graphics_path = ""
 
-  # Use the stub media library in //chromecast/media. If this is true, the
-  # value of |libcast_media_path| is ignored.
-  use_default_cast_media =
-      chromecast_branding == "public" || is_chromecast_desktop_build
-
-  # The path to the cast_media shared library. Any target pointed to must be
-  # named "libcast_media_1.0".
-  libcast_media_path = ""
-
   # Use Playready CDMs.
   use_playready = false
 }
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp
index c48d00cf..67aeac1 100644
--- a/chromecast/chromecast.gyp
+++ b/chromecast/chromecast.gyp
@@ -82,6 +82,7 @@
         'base/cast_paths.cc',
         'base/cast_paths.h',
         'base/cast_resource.h',
+        'base/cast_resource.cc',
         'base/chromecast_config_android.cc',
         'base/chromecast_config_android.h',
         'base/chromecast_switches.cc',
diff --git a/chromecast/common/media/cma_messages.h b/chromecast/common/media/cma_messages.h
index 1edb982..1649cc0 100644
--- a/chromecast/common/media/cma_messages.h
+++ b/chromecast/common/media/cma_messages.h
@@ -64,13 +64,6 @@
                      int /* Media pipeline ID */,
                      chromecast::media::TrackId /* Track ID */)
 
-IPC_MESSAGE_CONTROL5(CmaHostMsg_NotifyExternalSurface,
-                     int /* Surface ID */,
-                     gfx::PointF /* Quad video top left */,
-                     gfx::PointF /* Quad video top right */,
-                     gfx::PointF /* Quad video bottim right */,
-                     gfx::PointF /* Quad video bottom left */)
-
 // Messages from the browser to the renderer process.
 
 IPC_MESSAGE_CONTROL2(CmaMsg_MediaStateChanged,
diff --git a/chromecast/media/BUILD.gn b/chromecast/media/BUILD.gn
index 52536d8..4961a3f7 100644
--- a/chromecast/media/BUILD.gn
+++ b/chromecast/media/BUILD.gn
@@ -61,18 +61,6 @@
   ]
 }
 
-group("libcast_media") {
-  if (use_default_cast_media) {
-    public_deps = [
-      "//chromecast/media/base:libcast_media_default",
-    ]
-  } else {
-    public_deps = [
-      "$libcast_media_path:libcast_media_1.0",
-    ]
-  }
-}
-
 # TODO(slan): delete this target once Chromecast M44/earlier is obsolete.
 # See: b/21639416
 shared_library("libffmpegsumo") {
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn
index aa8e7d23..a6202681 100644
--- a/chromecast/media/base/BUILD.gn
+++ b/chromecast/media/base/BUILD.gn
@@ -35,7 +35,7 @@
   configs += [ "//chromecast:config" ]
 
   deps = [
-    ":libcast_media_default",
+    ":libcast_media_1.0",
     "//base",
     "//chromecast/public",
     "//crypto",
@@ -50,9 +50,7 @@
   }
 }
 
-shared_library("libcast_media_default") {
-  output_name = "libcast_media_1.0"
-
+shared_library("libcast_media_1.0") {
   sources = [
     "cast_media_default.cc",
   ]
diff --git a/chromecast/media/cma/filters/BUILD.gn b/chromecast/media/cma/filters/BUILD.gn
index 7126bbb..003b5b19f 100644
--- a/chromecast/media/cma/filters/BUILD.gn
+++ b/chromecast/media/cma/filters/BUILD.gn
@@ -16,7 +16,6 @@
 
   deps = [
     "//base",
-    "//chromecast/base",
     "//chromecast/media/cma/base",
     "//chromecast/media/cma/pipeline",
     "//gpu/command_buffer/client:gles2_interface",
diff --git a/chromecast/media/cma/filters/hole_frame_factory.cc b/chromecast/media/cma/filters/hole_frame_factory.cc
index 5cca26a..4d4b333 100644
--- a/chromecast/media/cma/filters/hole_frame_factory.cc
+++ b/chromecast/media/cma/filters/hole_frame_factory.cc
@@ -5,9 +5,7 @@
 #include "chromecast/media/cma/filters/hole_frame_factory.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/location.h"
-#include "chromecast/base/chromecast_switches.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "media/base/video_frame.h"
@@ -21,11 +19,8 @@
     : gpu_factories_(gpu_factories),
       texture_(0),
       image_id_(0),
-      sync_point_(0),
-      use_legacy_hole_punching_(
-          base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kEnableLegacyHolePunching)) {
-  if (gpu_factories_ && !use_legacy_hole_punching_) {
+      sync_point_(0) {
+  if (gpu_factories_) {
     gpu::gles2::GLES2Interface* gl = gpu_factories_->GetGLES2Interface();
     CHECK(gl);
 
@@ -54,13 +49,6 @@
 
 scoped_refptr<::media::VideoFrame> HoleFrameFactory::CreateHoleFrame(
     const gfx::Size& size) {
-  if (use_legacy_hole_punching_) {
-#if defined(VIDEO_HOLE)
-    return ::media::VideoFrame::CreateHoleFrame(size);
-#endif
-    NOTREACHED();
-  }
-
   if (texture_) {
     scoped_refptr<::media::VideoFrame> frame =
         ::media::VideoFrame::WrapNativeTexture(
diff --git a/chromecast/media/cma/filters/hole_frame_factory.h b/chromecast/media/cma/filters/hole_frame_factory.h
index e817a3e..c77fb6b 100644
--- a/chromecast/media/cma/filters/hole_frame_factory.h
+++ b/chromecast/media/cma/filters/hole_frame_factory.h
@@ -22,9 +22,8 @@
 namespace chromecast {
 namespace media {
 
-// Creates VideoFrames for CMA - currently supports both overlay frames
-// (native textures that get turned into transparent holes in the browser
-// compositor), and legacy VIDEO_HOLE codepath.
+// Creates VideoFrames for CMA - native textures that get turned into
+// transparent holes in the browser compositor using overlay system.
 // All calls (including ctor/dtor) must be on media thread.
 class HoleFrameFactory {
  public:
@@ -40,7 +39,6 @@
   GLuint texture_;
   GLuint image_id_;
   GLuint sync_point_;
-  bool use_legacy_hole_punching_;
 
   DISALLOW_COPY_AND_ASSIGN(HoleFrameFactory);
 };
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp
index d7d25da..0b87875a 100644
--- a/chromecast/media/media.gyp
+++ b/chromecast/media/media.gyp
@@ -6,8 +6,6 @@
   'variables': {
     'chromium_code': 1,
     'chromecast_branding%': 'public',
-    'libcast_media_gyp%': '',
-    'use_default_libcast_media%': 1,
   },
   'target_defaults': {
     'include_dirs': [
@@ -41,10 +39,10 @@
       'target_name': 'media_base',
       'type': '<(component)',
       'dependencies': [
+        'libcast_media_1.0',
         '../../base/base.gyp:base',
         '../../crypto/crypto.gyp:crypto',
         '../../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
-        '<(libcast_media_gyp):libcast_media_1.0',
       ],
       'sources': [
         'base/decrypt_context_impl.cc',
@@ -140,7 +138,6 @@
       'target_name': 'default_cma_backend',
       'type': '<(component)',
       'dependencies': [
-        '../chromecast.gyp:cast_base',
         '../../base/base.gyp:base',
       ],
       'include_dirs': [
@@ -316,25 +313,21 @@
         'cma/test/run_all_unittests.cc',
       ],
     },
+    { # Target for OEM partners to override media shared library, i.e.
+      # libcast_media_1.0.so. This target is only used to build executables
+      # with correct linkage information.
+      'target_name': 'libcast_media_1.0',
+      'type': 'shared_library',
+      'dependencies': [
+        '../../chromecast/chromecast.gyp:cast_public_api',
+        'default_cma_backend'
+      ],
+      'include_dirs': [
+        '../..',
+      ],
+      'sources': [
+        'base/cast_media_default.cc',
+      ],
+    }
   ], # end of targets
-  'conditions': [
-    ['use_default_libcast_media==1', {
-      'targets': [
-        {
-          'target_name': 'libcast_media_1.0',
-          'type': 'shared_library',
-          'dependencies': [
-            '../../chromecast/chromecast.gyp:cast_public_api',
-            'default_cma_backend'
-          ],
-          'include_dirs': [
-            '../..',
-          ],
-          'sources': [
-            'base/cast_media_default.cc',
-          ],
-        }
-      ]
-    }],
-  ],
 }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 21b672ef..4a3318d7 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-7494.0.0
\ No newline at end of file
+7503.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 4ccdfca9..abda945 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -59,44 +59,6 @@
       'dbus/audio_node.h',
       'dbus/blocking_method_caller.cc',
       'dbus/blocking_method_caller.h',
-      'dbus/bluetooth_adapter_client.cc',
-      'dbus/bluetooth_adapter_client.h',
-      'dbus/bluetooth_le_advertising_manager_client.cc',
-      'dbus/bluetooth_le_advertising_manager_client.h',
-      'dbus/bluetooth_le_advertisement_service_provider.cc',
-      'dbus/bluetooth_le_advertisement_service_provider.h',
-      'dbus/bluetooth_agent_manager_client.cc',
-      'dbus/bluetooth_agent_manager_client.h',
-      'dbus/bluetooth_agent_service_provider.cc',
-      'dbus/bluetooth_agent_service_provider.h',
-      'dbus/bluetooth_device_client.cc',
-      'dbus/bluetooth_device_client.h',
-      'dbus/bluetooth_gatt_characteristic_client.cc',
-      'dbus/bluetooth_gatt_characteristic_client.h',
-      'dbus/bluetooth_gatt_characteristic_service_provider.cc',
-      'dbus/bluetooth_gatt_characteristic_service_provider.h',
-      'dbus/bluetooth_gatt_descriptor_client.cc',
-      'dbus/bluetooth_gatt_descriptor_client.h',
-      'dbus/bluetooth_gatt_descriptor_service_provider.cc',
-      'dbus/bluetooth_gatt_descriptor_service_provider.h',
-      'dbus/bluetooth_gatt_manager_client.cc',
-      'dbus/bluetooth_gatt_manager_client.h',
-      'dbus/bluetooth_gatt_service_client.cc',
-      'dbus/bluetooth_gatt_service_client.h',
-      'dbus/bluetooth_gatt_service_service_provider.cc',
-      'dbus/bluetooth_gatt_service_service_provider.h',
-      'dbus/bluetooth_input_client.cc',
-      'dbus/bluetooth_input_client.h',
-      'dbus/bluetooth_media_client.cc',
-      'dbus/bluetooth_media_client.h',
-      'dbus/bluetooth_media_endpoint_service_provider.cc',
-      'dbus/bluetooth_media_endpoint_service_provider.h',
-      'dbus/bluetooth_media_transport_client.cc',
-      'dbus/bluetooth_media_transport_client.h',
-      'dbus/bluetooth_profile_manager_client.cc',
-      'dbus/bluetooth_profile_manager_client.h',
-      'dbus/bluetooth_profile_service_provider.cc',
-      'dbus/bluetooth_profile_service_provider.h',
       'dbus/cras_audio_client.cc',
       'dbus/cras_audio_client.h',
       'dbus/cros_disks_client.cc',
@@ -120,44 +82,6 @@
       'dbus/fake_ap_manager_client.h',
       'dbus/fake_audio_dsp_client.cc',
       'dbus/fake_audio_dsp_client.h',
-      'dbus/fake_bluetooth_adapter_client.cc',
-      'dbus/fake_bluetooth_adapter_client.h',
-      'dbus/fake_bluetooth_le_advertising_manager_client.cc',
-      'dbus/fake_bluetooth_le_advertising_manager_client.h',
-      'dbus/fake_bluetooth_le_advertisement_service_provider.cc',
-      'dbus/fake_bluetooth_le_advertisement_service_provider.h',
-      'dbus/fake_bluetooth_agent_manager_client.cc',
-      'dbus/fake_bluetooth_agent_manager_client.h',
-      'dbus/fake_bluetooth_agent_service_provider.cc',
-      'dbus/fake_bluetooth_agent_service_provider.h',
-      'dbus/fake_bluetooth_device_client.cc',
-      'dbus/fake_bluetooth_device_client.h',
-      'dbus/fake_bluetooth_gatt_characteristic_client.cc',
-      'dbus/fake_bluetooth_gatt_characteristic_client.h',
-      'dbus/fake_bluetooth_gatt_characteristic_service_provider.cc',
-      'dbus/fake_bluetooth_gatt_characteristic_service_provider.h',
-      'dbus/fake_bluetooth_gatt_descriptor_client.cc',
-      'dbus/fake_bluetooth_gatt_descriptor_client.h',
-      'dbus/fake_bluetooth_gatt_descriptor_service_provider.cc',
-      'dbus/fake_bluetooth_gatt_descriptor_service_provider.h',
-      'dbus/fake_bluetooth_gatt_manager_client.cc',
-      'dbus/fake_bluetooth_gatt_manager_client.h',
-      'dbus/fake_bluetooth_gatt_service_client.cc',
-      'dbus/fake_bluetooth_gatt_service_client.h',
-      'dbus/fake_bluetooth_gatt_service_service_provider.cc',
-      'dbus/fake_bluetooth_gatt_service_service_provider.h',
-      'dbus/fake_bluetooth_input_client.cc',
-      'dbus/fake_bluetooth_input_client.h',
-      'dbus/fake_bluetooth_media_client.cc',
-      'dbus/fake_bluetooth_media_client.h',
-      'dbus/fake_bluetooth_media_endpoint_service_provider.cc',
-      'dbus/fake_bluetooth_media_endpoint_service_provider.h',
-      'dbus/fake_bluetooth_media_transport_client.cc',
-      'dbus/fake_bluetooth_media_transport_client.h',
-      'dbus/fake_bluetooth_profile_manager_client.cc',
-      'dbus/fake_bluetooth_profile_manager_client.h',
-      'dbus/fake_bluetooth_profile_service_provider.cc',
-      'dbus/fake_bluetooth_profile_service_provider.h',
       'dbus/fake_cras_audio_client.cc',
       'dbus/fake_cras_audio_client.h',
       'dbus/fake_cros_disks_client.cc',
diff --git a/chromeos/dbus/dbus_client_bundle.cc b/chromeos/dbus/dbus_client_bundle.cc
index 20b0898..87e6598 100644
--- a/chromeos/dbus/dbus_client_bundle.cc
+++ b/chromeos/dbus/dbus_client_bundle.cc
@@ -13,18 +13,6 @@
 #include "chromeos/dbus/amplifier_client.h"
 #include "chromeos/dbus/ap_manager_client.h"
 #include "chromeos/dbus/audio_dsp_client.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
-#include "chromeos/dbus/bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
-#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/cras_audio_client.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/cryptohome_client.h"
@@ -33,18 +21,6 @@
 #include "chromeos/dbus/fake_amplifier_client.h"
 #include "chromeos/dbus/fake_ap_manager_client.h"
 #include "chromeos/dbus/fake_audio_dsp_client.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
-#include "chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_transport_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/fake_cras_audio_client.h"
 #include "chromeos/dbus/fake_cryptohome_client.h"
 #include "chromeos/dbus/fake_debug_daemon_client.h"
@@ -157,47 +133,6 @@
   else
     audio_dsp_client_.reset(new FakeAudioDspClient);
 
-  if (!IsUsingStub(BLUETOOTH)) {
-    bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create());
-    bluetooth_le_advertising_manager_client_.reset(
-        BluetoothLEAdvertisingManagerClient::Create());
-    bluetooth_agent_manager_client_.reset(
-        BluetoothAgentManagerClient::Create());
-    bluetooth_device_client_.reset(BluetoothDeviceClient::Create());
-    bluetooth_input_client_.reset(BluetoothInputClient::Create());
-    bluetooth_media_client_.reset(BluetoothMediaClient::Create());
-    bluetooth_media_transport_client_.reset(
-        BluetoothMediaTransportClient::Create());
-    bluetooth_profile_manager_client_.reset(
-        BluetoothProfileManagerClient::Create());
-    bluetooth_gatt_characteristic_client_.reset(
-        BluetoothGattCharacteristicClient::Create());
-    bluetooth_gatt_descriptor_client_.reset(
-        BluetoothGattDescriptorClient::Create());
-    bluetooth_gatt_manager_client_.reset(
-        BluetoothGattManagerClient::Create());
-    bluetooth_gatt_service_client_.reset(
-        BluetoothGattServiceClient::Create());
-  } else {
-    bluetooth_adapter_client_.reset(new FakeBluetoothAdapterClient);
-    bluetooth_le_advertising_manager_client_.reset(
-        new FakeBluetoothLEAdvertisingManagerClient);
-    bluetooth_agent_manager_client_.reset(new FakeBluetoothAgentManagerClient);
-    bluetooth_device_client_.reset(new FakeBluetoothDeviceClient);
-    bluetooth_input_client_.reset(new FakeBluetoothInputClient);
-    bluetooth_media_client_.reset(new FakeBluetoothMediaClient);
-    bluetooth_media_transport_client_.reset(
-        new FakeBluetoothMediaTransportClient);
-    bluetooth_profile_manager_client_.reset(
-        new FakeBluetoothProfileManagerClient);
-    bluetooth_gatt_characteristic_client_.reset(
-        new FakeBluetoothGattCharacteristicClient);
-    bluetooth_gatt_descriptor_client_.reset(
-        new FakeBluetoothGattDescriptorClient);
-    bluetooth_gatt_manager_client_.reset(new FakeBluetoothGattManagerClient);
-    bluetooth_gatt_service_client_.reset(new FakeBluetoothGattServiceClient);
-  }
-
   if (!IsUsingStub(CRAS))
     cras_audio_client_.reset(CrasAudioClient::Create());
   else
diff --git a/chromeos/dbus/dbus_client_bundle.h b/chromeos/dbus/dbus_client_bundle.h
index a9a115b..ea39ad9 100644
--- a/chromeos/dbus/dbus_client_bundle.h
+++ b/chromeos/dbus/dbus_client_bundle.h
@@ -15,18 +15,6 @@
 class AmplifierClient;
 class ApManagerClient;
 class AudioDspClient;
-class BluetoothAdapterClient;
-class BluetoothAgentManagerClient;
-class BluetoothDeviceClient;
-class BluetoothGattCharacteristicClient;
-class BluetoothGattDescriptorClient;
-class BluetoothGattManagerClient;
-class BluetoothGattServiceClient;
-class BluetoothInputClient;
-class BluetoothLEAdvertisingManagerClient;
-class BluetoothMediaClient;
-class BluetoothMediaTransportClient;
-class BluetoothProfileManagerClient;
 class CrasAudioClient;
 class CrosDisksClient;
 class CryptohomeClient;
@@ -116,55 +104,6 @@
 
   AudioDspClient* audio_dsp_client() { return audio_dsp_client_.get(); }
 
-  BluetoothAdapterClient* bluetooth_adapter_client() {
-    return bluetooth_adapter_client_.get();
-  }
-
-  BluetoothLEAdvertisingManagerClient*
-  bluetooth_le_advertising_manager_client() {
-    return bluetooth_le_advertising_manager_client_.get();
-  }
-
-  BluetoothAgentManagerClient* bluetooth_agent_manager_client() {
-    return bluetooth_agent_manager_client_.get();
-  }
-
-  BluetoothDeviceClient* bluetooth_device_client() {
-    return bluetooth_device_client_.get();
-  }
-
-  BluetoothGattCharacteristicClient* bluetooth_gatt_characteristic_client() {
-    return bluetooth_gatt_characteristic_client_.get();
-  }
-
-  BluetoothGattDescriptorClient* bluetooth_gatt_descriptor_client() {
-    return bluetooth_gatt_descriptor_client_.get();
-  }
-
-  BluetoothGattManagerClient* bluetooth_gatt_manager_client() {
-    return bluetooth_gatt_manager_client_.get();
-  }
-
-  BluetoothGattServiceClient* bluetooth_gatt_service_client() {
-    return bluetooth_gatt_service_client_.get();
-  }
-
-  BluetoothInputClient* bluetooth_input_client() {
-    return bluetooth_input_client_.get();
-  }
-
-  BluetoothMediaClient* bluetooth_media_client() {
-    return bluetooth_media_client_.get();
-  }
-
-  BluetoothMediaTransportClient* bluetooth_media_transport_client() {
-    return bluetooth_media_transport_client_.get();
-  }
-
-  BluetoothProfileManagerClient* bluetooth_profile_manager_client() {
-    return bluetooth_profile_manager_client_.get();
-  }
-
   CrasAudioClient* cras_audio_client() {
     return cras_audio_client_.get();
   }
@@ -291,20 +230,6 @@
   scoped_ptr<AmplifierClient> amplifier_client_;
   scoped_ptr<ApManagerClient> ap_manager_client_;
   scoped_ptr<AudioDspClient> audio_dsp_client_;
-  scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_;
-  scoped_ptr<BluetoothLEAdvertisingManagerClient>
-      bluetooth_le_advertising_manager_client_;
-  scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_;
-  scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_;
-  scoped_ptr<BluetoothGattCharacteristicClient>
-      bluetooth_gatt_characteristic_client_;
-  scoped_ptr<BluetoothGattDescriptorClient> bluetooth_gatt_descriptor_client_;
-  scoped_ptr<BluetoothGattManagerClient> bluetooth_gatt_manager_client_;
-  scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_;
-  scoped_ptr<BluetoothInputClient> bluetooth_input_client_;
-  scoped_ptr<BluetoothMediaClient> bluetooth_media_client_;
-  scoped_ptr<BluetoothMediaTransportClient> bluetooth_media_transport_client_;
-  scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_;
   scoped_ptr<CrasAudioClient> cras_audio_client_;
   scoped_ptr<CrosDisksClient> cros_disks_client_;
   scoped_ptr<CryptohomeClient> cryptohome_client_;
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index fb525b5..fe590216 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -11,18 +11,6 @@
 #include "chromeos/dbus/amplifier_client.h"
 #include "chromeos/dbus/ap_manager_client.h"
 #include "chromeos/dbus/audio_dsp_client.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
-#include "chromeos/dbus/bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
-#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/cras_audio_client.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/cryptohome_client.h"
@@ -127,62 +115,6 @@
   return client_bundle_->audio_dsp_client();
 }
 
-BluetoothAdapterClient* DBusThreadManager::GetBluetoothAdapterClient() {
-  return client_bundle_->bluetooth_adapter_client();
-}
-
-BluetoothLEAdvertisingManagerClient*
-DBusThreadManager::GetBluetoothLEAdvertisingManagerClient() {
-  return client_bundle_->bluetooth_le_advertising_manager_client();
-}
-
-BluetoothAgentManagerClient*
-DBusThreadManager::GetBluetoothAgentManagerClient() {
-  return client_bundle_->bluetooth_agent_manager_client();
-}
-
-BluetoothDeviceClient* DBusThreadManager::GetBluetoothDeviceClient() {
-  return client_bundle_->bluetooth_device_client();
-}
-
-BluetoothGattCharacteristicClient*
-DBusThreadManager::GetBluetoothGattCharacteristicClient() {
-  return client_bundle_->bluetooth_gatt_characteristic_client();
-}
-
-BluetoothGattDescriptorClient*
-DBusThreadManager::GetBluetoothGattDescriptorClient() {
-  return client_bundle_->bluetooth_gatt_descriptor_client();
-}
-
-BluetoothGattManagerClient*
-DBusThreadManager::GetBluetoothGattManagerClient() {
-  return client_bundle_->bluetooth_gatt_manager_client();
-}
-
-BluetoothGattServiceClient*
-DBusThreadManager::GetBluetoothGattServiceClient() {
-  return client_bundle_->bluetooth_gatt_service_client();
-}
-
-BluetoothInputClient* DBusThreadManager::GetBluetoothInputClient() {
-  return client_bundle_->bluetooth_input_client();
-}
-
-BluetoothMediaClient* DBusThreadManager::GetBluetoothMediaClient() {
-  return client_bundle_->bluetooth_media_client();
-}
-
-BluetoothMediaTransportClient*
-DBusThreadManager::GetBluetoothMediaTransportClient() {
-  return client_bundle_->bluetooth_media_transport_client();
-}
-
-BluetoothProfileManagerClient*
-DBusThreadManager::GetBluetoothProfileManagerClient() {
-  return client_bundle_->bluetooth_profile_manager_client();
-}
-
 CrasAudioClient* DBusThreadManager::GetCrasAudioClient() {
   return client_bundle_->cras_audio_client();
 }
@@ -310,18 +242,6 @@
   GetAmplifierClient()->Init(GetSystemBus());
   GetApManagerClient()->Init(GetSystemBus());
   GetAudioDspClient()->Init(GetSystemBus());
-  GetBluetoothAdapterClient()->Init(GetSystemBus());
-  GetBluetoothAgentManagerClient()->Init(GetSystemBus());
-  GetBluetoothDeviceClient()->Init(GetSystemBus());
-  GetBluetoothGattCharacteristicClient()->Init(GetSystemBus());
-  GetBluetoothGattDescriptorClient()->Init(GetSystemBus());
-  GetBluetoothGattManagerClient()->Init(GetSystemBus());
-  GetBluetoothGattServiceClient()->Init(GetSystemBus());
-  GetBluetoothInputClient()->Init(GetSystemBus());
-  GetBluetoothLEAdvertisingManagerClient()->Init(GetSystemBus());
-  GetBluetoothMediaClient()->Init(GetSystemBus());
-  GetBluetoothMediaTransportClient()->Init(GetSystemBus());
-  GetBluetoothProfileManagerClient()->Init(GetSystemBus());
   GetCrasAudioClient()->Init(GetSystemBus());
   GetCrosDisksClient()->Init(GetSystemBus());
   GetCryptohomeClient()->Init(GetSystemBus());
@@ -476,78 +396,6 @@
   DBusThreadManager::Get()->client_bundle_->audio_dsp_client_ = client.Pass();
 }
 
-void DBusThreadManagerSetter::SetBluetoothAdapterClient(
-    scoped_ptr<BluetoothAdapterClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_adapter_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothLEAdvertisingManagerClient(
-    scoped_ptr<BluetoothLEAdvertisingManagerClient> client) {
-  DBusThreadManager::Get()->client_bundle_->
-      bluetooth_le_advertising_manager_client_ = client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothAgentManagerClient(
-    scoped_ptr<BluetoothAgentManagerClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_agent_manager_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothDeviceClient(
-    scoped_ptr<BluetoothDeviceClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_device_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothGattCharacteristicClient(
-    scoped_ptr<BluetoothGattCharacteristicClient> client) {
-  DBusThreadManager::Get()->client_bundle_->
-      bluetooth_gatt_characteristic_client_ = client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothGattDescriptorClient(
-    scoped_ptr<BluetoothGattDescriptorClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_descriptor_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothGattManagerClient(
-    scoped_ptr<BluetoothGattManagerClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_manager_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothGattServiceClient(
-    scoped_ptr<BluetoothGattServiceClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_service_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothInputClient(
-    scoped_ptr<BluetoothInputClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_input_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothMediaClient(
-    scoped_ptr<BluetoothMediaClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_media_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothMediaTransportClient(
-    scoped_ptr<BluetoothMediaTransportClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_media_transport_client_ =
-      client.Pass();
-}
-
-void DBusThreadManagerSetter::SetBluetoothProfileManagerClient(
-    scoped_ptr<BluetoothProfileManagerClient> client) {
-  DBusThreadManager::Get()->client_bundle_->bluetooth_profile_manager_client_ =
-      client.Pass();
-}
-
 void DBusThreadManagerSetter::SetCrasAudioClient(
     scoped_ptr<CrasAudioClient> client) {
   DBusThreadManager::Get()->client_bundle_->cras_audio_client_ = client.Pass();
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 322ab280..83f3c26 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -28,18 +28,6 @@
 class AmplifierClient;
 class ApManagerClient;
 class AudioDspClient;
-class BluetoothAdapterClient;
-class BluetoothLEAdvertisingManagerClient;
-class BluetoothAgentManagerClient;
-class BluetoothDeviceClient;
-class BluetoothGattCharacteristicClient;
-class BluetoothGattDescriptorClient;
-class BluetoothGattManagerClient;
-class BluetoothGattServiceClient;
-class BluetoothInputClient;
-class BluetoothMediaClient;
-class BluetoothMediaTransportClient;
-class BluetoothProfileManagerClient;
 class CrasAudioClient;
 class CrosDisksClient;
 class CryptohomeClient;
@@ -124,18 +112,6 @@
   AmplifierClient* GetAmplifierClient();
   ApManagerClient* GetApManagerClient();
   AudioDspClient* GetAudioDspClient();
-  BluetoothAdapterClient* GetBluetoothAdapterClient();
-  BluetoothLEAdvertisingManagerClient* GetBluetoothLEAdvertisingManagerClient();
-  BluetoothAgentManagerClient* GetBluetoothAgentManagerClient();
-  BluetoothDeviceClient* GetBluetoothDeviceClient();
-  BluetoothGattCharacteristicClient* GetBluetoothGattCharacteristicClient();
-  BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient();
-  BluetoothGattManagerClient* GetBluetoothGattManagerClient();
-  BluetoothGattServiceClient* GetBluetoothGattServiceClient();
-  BluetoothInputClient* GetBluetoothInputClient();
-  BluetoothMediaClient* GetBluetoothMediaClient();
-  BluetoothMediaTransportClient* GetBluetoothMediaTransportClient();
-  BluetoothProfileManagerClient* GetBluetoothProfileManagerClient();
   CrasAudioClient* GetCrasAudioClient();
   CrosDisksClient* GetCrosDisksClient();
   CryptohomeClient* GetCryptohomeClient();
@@ -210,26 +186,6 @@
 
   void SetAmplifierClient(scoped_ptr<AmplifierClient> client);
   void SetAudioDspClient(scoped_ptr<AudioDspClient> client);
-  void SetBluetoothAdapterClient(scoped_ptr<BluetoothAdapterClient> client);
-  void SetBluetoothLEAdvertisingManagerClient(
-      scoped_ptr<BluetoothLEAdvertisingManagerClient> client);
-  void SetBluetoothAgentManagerClient(
-      scoped_ptr<BluetoothAgentManagerClient> client);
-  void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client);
-  void SetBluetoothGattCharacteristicClient(
-      scoped_ptr<BluetoothGattCharacteristicClient> client);
-  void SetBluetoothGattDescriptorClient(
-      scoped_ptr<BluetoothGattDescriptorClient> client);
-  void SetBluetoothGattManagerClient(
-      scoped_ptr<BluetoothGattManagerClient> client);
-  void SetBluetoothGattServiceClient(
-      scoped_ptr<BluetoothGattServiceClient> client);
-  void SetBluetoothInputClient(scoped_ptr<BluetoothInputClient> client);
-  void SetBluetoothMediaClient(scoped_ptr<BluetoothMediaClient> client);
-  void SetBluetoothMediaTransportClient(
-      scoped_ptr<BluetoothMediaTransportClient> client);
-  void SetBluetoothProfileManagerClient(
-      scoped_ptr<BluetoothProfileManagerClient> client);
   void SetCrasAudioClient(scoped_ptr<CrasAudioClient> client);
   void SetCrosDisksClient(scoped_ptr<CrosDisksClient> client);
   void SetCryptohomeClient(scoped_ptr<CryptohomeClient> client);
diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc
index e5e4dd9f..a0545c989 100644
--- a/chromeos/network/client_cert_resolver.cc
+++ b/chromeos/network/client_cert_resolver.cc
@@ -71,6 +71,7 @@
 }
 
 // Describes a certificate which is issued by |issuer| (encoded as PEM).
+// |issuer| can be empty if no issuer certificate is found in the database.
 struct CertAndIssuer {
   CertAndIssuer(const scoped_refptr<net::X509Certificate>& certificate,
                 const std::string& issuer)
@@ -127,6 +128,33 @@
   const CertificatePattern pattern;
 };
 
+// Lookup the issuer certificate of |cert|. If it is available, return the PEM
+// encoding of that certificate. Otherwise return the empty string.
+std::string GetPEMEncodedIssuer(const net::X509Certificate& cert) {
+  net::ScopedCERTCertificate issuer_handle(
+      CERT_FindCertIssuer(cert.os_cert_handle(), PR_Now(), certUsageAnyCA));
+  if (!issuer_handle) {
+    VLOG(1) << "Couldn't find an issuer.";
+    return std::string();
+  }
+
+  scoped_refptr<net::X509Certificate> issuer =
+      net::X509Certificate::CreateFromHandle(
+          issuer_handle.get(),
+          net::X509Certificate::OSCertHandles() /* no intermediate certs */);
+  if (!issuer.get()) {
+    LOG(ERROR) << "Couldn't create issuer cert.";
+    return std::string();
+  }
+  std::string pem_encoded_issuer;
+  if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(),
+                                           &pem_encoded_issuer)) {
+    LOG(ERROR) << "Couldn't PEM-encode certificate.";
+    return std::string();
+  }
+  return pem_encoded_issuer;
+}
+
 std::vector<CertAndIssuer> CreateSortedCertAndIssuerList(
     const net::CertificateList& certs) {
   // Filter all client certs and determines each certificate's issuer, which is
@@ -140,27 +168,7 @@
         !CertLoader::IsCertificateHardwareBacked(&cert)) {
       continue;
     }
-    net::ScopedCERTCertificate issuer_handle(
-        CERT_FindCertIssuer(cert.os_cert_handle(), PR_Now(), certUsageAnyCA));
-    if (!issuer_handle) {
-      LOG(ERROR) << "Couldn't find an issuer.";
-      continue;
-    }
-    scoped_refptr<net::X509Certificate> issuer =
-        net::X509Certificate::CreateFromHandle(
-            issuer_handle.get(),
-            net::X509Certificate::OSCertHandles() /* no intermediate certs */);
-    if (!issuer.get()) {
-      LOG(ERROR) << "Couldn't create issuer cert.";
-      continue;
-    }
-    std::string pem_encoded_issuer;
-    if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(),
-                                             &pem_encoded_issuer)) {
-      LOG(ERROR) << "Couldn't PEM-encode certificate.";
-      continue;
-    }
-    client_certs.push_back(CertAndIssuer(*it, pem_encoded_issuer));
+    client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert)));
   }
 
   std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration);
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc
index 5032b63..0109b8c 100644
--- a/chromeos/network/client_cert_resolver_unittest.cc
+++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -101,25 +101,27 @@
     }
   }
 
-  // Imports a CA cert (stored as PEM in test_ca_cert_pem_) and a client
-  // certificate signed by that CA. Its PKCS#11 ID is stored in
-  // |test_cert_id_|.
-  void SetupTestCerts() {
-    // Import a CA cert.
-    net::CertificateList ca_cert_list =
-        net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
-                                           "client_1_ca.pem",
-                                           net::X509Certificate::FORMAT_AUTO);
+  // Imports a client certificate. Its PKCS#11 ID is stored in |test_cert_id_|.
+  // If |import_issuer| is true, also imports the CA cert (stored as PEM in
+  // test_ca_cert_pem_) that issued the client certificate.
+  void SetupTestCerts(bool import_issuer) {
+    // Load a CA cert.
+    net::CertificateList ca_cert_list = net::CreateCertificateListFromFile(
+        net::GetTestCertsDirectory(), "client_1_ca.pem",
+        net::X509Certificate::FORMAT_AUTO);
     ASSERT_TRUE(!ca_cert_list.empty());
-    net::NSSCertDatabase::ImportCertFailureList failures;
-    EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
-        ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
-    ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error);
-
     net::X509Certificate::GetPEMEncoded(ca_cert_list[0]->os_cert_handle(),
                                         &test_ca_cert_pem_);
     ASSERT_TRUE(!test_ca_cert_pem_.empty());
 
+    if (import_issuer) {
+      net::NSSCertDatabase::ImportCertFailureList failures;
+      EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
+          ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
+      ASSERT_TRUE(failures.empty())
+          << net::ErrorToString(failures[0].net_error);
+    }
+
     // Import a client cert signed by that CA.
     test_client_cert_ =
         net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
@@ -172,10 +174,45 @@
         ->AddManagerService(kWifiStub, true);
   }
 
-  // Setup a policy with a certificate pattern that matches any client cert that
-  // is signed by the test CA cert (stored in |test_ca_cert_pem_|). In
+  // Sets up a policy with a certificate pattern that matches any client cert
+  // with a certain Issuer CN. It will match the test client cert.
+  void SetupPolicyMatchingIssuerCN() {
+    const char* kTestPolicy =
+        "[ { \"GUID\": \"wifi_stub\","
+        "    \"Name\": \"wifi_stub\","
+        "    \"Type\": \"WiFi\","
+        "    \"WiFi\": {"
+        "      \"Security\": \"WPA-EAP\","
+        "      \"SSID\": \"wifi_ssid\","
+        "      \"EAP\": {"
+        "        \"Outer\": \"EAP-TLS\","
+        "        \"ClientCertType\": \"Pattern\","
+        "        \"ClientCertPattern\": {"
+        "          \"Issuer\": {"
+        "            \"CommonName\": \"B CA\""
+        "          }"
+        "        }"
+        "      }"
+        "    }"
+        "} ]";
+
+    std::string error;
+    scoped_ptr<base::Value> policy_value = base::JSONReader::ReadAndReturnError(
+        kTestPolicy, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error);
+    ASSERT_TRUE(policy_value) << error;
+
+    base::ListValue* policy = NULL;
+    ASSERT_TRUE(policy_value->GetAsList(&policy));
+
+    managed_config_handler_->SetPolicy(
+        onc::ONC_SOURCE_USER_POLICY, kUserHash, *policy,
+        base::DictionaryValue() /* no global network config */);
+  }
+
+  // Sets up a policy with a certificate pattern that matches any client cert
+  // that is signed by the test CA cert (stored in |test_ca_cert_pem_|). In
   // particular it will match the test client cert.
-  void SetupPolicy() {
+  void SetupPolicyMatchingIssuerPEM() {
     const char* kTestPolicyTemplate =
         "[ { \"GUID\": \"wifi_stub\","
         "    \"Name\": \"wifi_stub\","
@@ -248,12 +285,13 @@
 };
 
 TEST_F(ClientCertResolverTest, NoMatchingCertificates) {
+  SetupTestCerts(false /* do not import the issuer */);
   StartCertLoader();
   SetupWifi();
   base::RunLoop().RunUntilIdle();
   network_properties_changed_count_ = 0;
   SetupNetworkHandlers();
-  SetupPolicy();
+  SetupPolicyMatchingIssuerPEM();
   base::RunLoop().RunUntilIdle();
 
   // Verify that no client certificate was configured.
@@ -264,13 +302,34 @@
   EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning());
 }
 
-TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) {
-  SetupTestCerts();
+TEST_F(ClientCertResolverTest, MatchIssuerCNWithoutIssuerInstalled) {
+  SetupTestCerts(false /* do not import the issuer */);
   SetupWifi();
   base::RunLoop().RunUntilIdle();
 
   SetupNetworkHandlers();
-  SetupPolicy();
+  SetupPolicyMatchingIssuerCN();
+  base::RunLoop().RunUntilIdle();
+
+  network_properties_changed_count_ = 0;
+  StartCertLoader();
+  base::RunLoop().RunUntilIdle();
+
+  // Verify that the resolver positively matched the pattern in the policy with
+  // the test client cert and configured the network.
+  std::string pkcs11_id;
+  GetClientCertProperties(&pkcs11_id);
+  EXPECT_EQ(test_cert_id_, pkcs11_id);
+  EXPECT_EQ(1, network_properties_changed_count_);
+}
+
+TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) {
+  SetupTestCerts(true /* import issuer */);
+  SetupWifi();
+  base::RunLoop().RunUntilIdle();
+
+  SetupNetworkHandlers();
+  SetupPolicyMatchingIssuerPEM();
   base::RunLoop().RunUntilIdle();
 
   network_properties_changed_count_ = 0;
@@ -286,7 +345,7 @@
 }
 
 TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) {
-  SetupTestCerts();
+  SetupTestCerts(true /* import issuer */);
   SetupWifi();
   base::RunLoop().RunUntilIdle();
   StartCertLoader();
@@ -295,7 +354,7 @@
 
   // Policy application will trigger the ClientCertResolver.
   network_properties_changed_count_ = 0;
-  SetupPolicy();
+  SetupPolicyMatchingIssuerPEM();
   base::RunLoop().RunUntilIdle();
 
   // Verify that the resolver positively matched the pattern in the policy with
diff --git a/chromeos/network/portal_detector/network_portal_detector.cc b/chromeos/network/portal_detector/network_portal_detector.cc
index a9af6ac..6fcbb3b4 100644
--- a/chromeos/network/portal_detector/network_portal_detector.cc
+++ b/chromeos/network/portal_detector/network_portal_detector.cc
@@ -5,11 +5,15 @@
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 
 #include "base/logging.h"
+#include "components/device_event_log/device_event_log.h"
 
 namespace chromeos {
 
 namespace {
 
+bool set_for_testing_ = false;
+NetworkPortalDetector* network_portal_detector_ = nullptr;
+
 const char kCaptivePortalStatusUnknown[] = "Unknown";
 const char kCaptivePortalStatusOffline[] = "Offline";
 const char kCaptivePortalStatusOnline[]  = "Online";
@@ -20,16 +24,30 @@
 }  // namespace
 
 // static
-bool NetworkPortalDetector::set_for_testing_ = false;
-NetworkPortalDetector* NetworkPortalDetector::network_portal_detector_ =
-    nullptr;
+std::string NetworkPortalDetector::CaptivePortalStatusString(
+    CaptivePortalStatus status) {
+  switch (status) {
+    case CAPTIVE_PORTAL_STATUS_UNKNOWN:
+      return kCaptivePortalStatusUnknown;
+    case CAPTIVE_PORTAL_STATUS_OFFLINE:
+      return kCaptivePortalStatusOffline;
+    case CAPTIVE_PORTAL_STATUS_ONLINE:
+      return kCaptivePortalStatusOnline;
+    case CAPTIVE_PORTAL_STATUS_PORTAL:
+      return kCaptivePortalStatusPortal;
+    case CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
+      return kCaptivePortalStatusProxyAuthRequired;
+    case CAPTIVE_PORTAL_STATUS_COUNT:
+      NOTREACHED();
+  }
+  return kCaptivePortalStatusUnrecognized;
+}
 
-// static
-void NetworkPortalDetector::InitializeForTesting(
-    NetworkPortalDetector* network_portal_detector) {
+namespace network_portal_detector {
+
+void InitializeForTesting(NetworkPortalDetector* network_portal_detector) {
   if (network_portal_detector) {
-    CHECK(!set_for_testing_)
-        << "NetworkPortalDetector::InitializeForTesting is called twice";
+    CHECK(!set_for_testing_) << "InitializeForTesting is called twice";
     delete network_portal_detector_;
     network_portal_detector_ = network_portal_detector;
     set_for_testing_ = true;
@@ -39,44 +57,33 @@
   }
 }
 
-// static
-bool NetworkPortalDetector::IsInitialized() {
-  return NetworkPortalDetector::network_portal_detector_;
+bool IsInitialized() {
+  return network_portal_detector_;
 }
 
-// static
-void NetworkPortalDetector::Shutdown() {
+bool SetForTesting() {
+  return set_for_testing_;
+}
+
+void Shutdown() {
   CHECK(network_portal_detector_ || set_for_testing_)
-      << "NetworkPortalDetector::Shutdown() called without Initialize()";
+      << "Shutdown() called without Initialize()";
   delete network_portal_detector_;
   network_portal_detector_ = nullptr;
 }
 
-// static
-NetworkPortalDetector* NetworkPortalDetector::Get() {
-  CHECK(network_portal_detector_)
-      << "NetworkPortalDetector::Get() called before Initialize()";
+NetworkPortalDetector* GetInstance() {
+  CHECK(network_portal_detector_) << "GetInstance() called before Initialize()";
   return network_portal_detector_;
 }
 
-// static
-std::string NetworkPortalDetector::CaptivePortalStatusString(
-    CaptivePortalStatus status) {
-  switch (status) {
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
-      return kCaptivePortalStatusUnknown;
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
-      return kCaptivePortalStatusOffline;
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
-      return kCaptivePortalStatusOnline;
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
-      return kCaptivePortalStatusPortal;
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
-      return kCaptivePortalStatusProxyAuthRequired;
-    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
-      NOTREACHED();
-  }
-  return kCaptivePortalStatusUnrecognized;
+void SetNetworkPortalDetector(NetworkPortalDetector* network_portal_detector) {
+  CHECK(!network_portal_detector_)
+      << "NetworkPortalDetector was initialized twice.";
+  NET_LOG(EVENT) << "SetNetworkPortalDetector";
+  network_portal_detector_ = network_portal_detector;
 }
 
+}  // namespace network_portal_detector
+
 }  // namespace chromeos
diff --git a/chromeos/network/portal_detector/network_portal_detector.h b/chromeos/network/portal_detector/network_portal_detector.h
index 38843fe8..611cb642 100644
--- a/chromeos/network/portal_detector/network_portal_detector.h
+++ b/chromeos/network/portal_detector/network_portal_detector.h
@@ -14,16 +14,16 @@
 
 class NetworkState;
 
-// This class handles all notifications about network changes from
-// NetworkStateHandler and delegates portal detection for the active
-// network to CaptivePortalService.
+// This is an interface for a chromeos portal detector that allows for
+// observation of captive portal state. It supports retries based on a portal
+// detector strategy.
 class CHROMEOS_EXPORT NetworkPortalDetector {
  public:
   enum CaptivePortalStatus {
-    CAPTIVE_PORTAL_STATUS_UNKNOWN  = 0,
-    CAPTIVE_PORTAL_STATUS_OFFLINE  = 1,
-    CAPTIVE_PORTAL_STATUS_ONLINE   = 2,
-    CAPTIVE_PORTAL_STATUS_PORTAL   = 3,
+    CAPTIVE_PORTAL_STATUS_UNKNOWN = 0,
+    CAPTIVE_PORTAL_STATUS_OFFLINE = 1,
+    CAPTIVE_PORTAL_STATUS_ONLINE = 2,
+    CAPTIVE_PORTAL_STATUS_PORTAL = 3,
     CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED = 4,
     CAPTIVE_PORTAL_STATUS_COUNT
   };
@@ -31,8 +31,7 @@
   struct CaptivePortalState {
     CaptivePortalState()
         : status(CAPTIVE_PORTAL_STATUS_UNKNOWN),
-          response_code(net::URLFetcher::RESPONSE_CODE_INVALID) {
-    }
+          response_code(net::URLFetcher::RESPONSE_CODE_INVALID) {}
 
     bool operator==(const CaptivePortalState& o) const {
       return status == o.status && response_code == o.response_code;
@@ -60,6 +59,8 @@
     virtual ~Observer() {}
   };
 
+  virtual ~NetworkPortalDetector() {}
+
   // Adds |observer| to the observers list.
   virtual void AddObserver(Observer* observer) = 0;
 
@@ -107,44 +108,40 @@
   // Returns non-localized string representation of |status|.
   static std::string CaptivePortalStatusString(CaptivePortalStatus status);
 
-  // Initializes network portal detector for testing. The
-  // |network_portal_detector| will be owned by the internal pointer
-  // and deleted by Shutdown().
-  static void InitializeForTesting(
-      NetworkPortalDetector* network_portal_detector);
-
-  // Returns |true| if NetworkPortalDetector was Initialized and it is safe to
-  // call Get.
-  static bool IsInitialized();
-
-  // Deletes the instance of the NetworkPortalDetector.
-  static void Shutdown();
-
-  // Gets the instance of the NetworkPortalDetector. Return value should
-  // be used carefully in tests, because it can be changed "on the fly"
-  // by calls to InitializeForTesting().
-  static NetworkPortalDetector* Get();
-
  protected:
   NetworkPortalDetector() {}
-  virtual ~NetworkPortalDetector() {}
-
-  static bool set_for_testing() { return set_for_testing_; }
-  static NetworkPortalDetector* network_portal_detector() {
-    return network_portal_detector_;
-  }
-  static void set_network_portal_detector(
-      NetworkPortalDetector* network_portal_detector) {
-    network_portal_detector_ = network_portal_detector;
-  }
 
  private:
-  static bool set_for_testing_;
-  static NetworkPortalDetector* network_portal_detector_;
-
   DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetector);
 };
 
+// Manages a global NetworkPortalDetector instance that can be accessed across
+// all ChromeOS components.
+namespace network_portal_detector {
+// Gets the instance of the NetworkPortalDetector. Return value should
+// be used carefully in tests, because it can be changed "on the fly"
+// by calls to InitializeForTesting().
+CHROMEOS_EXPORT NetworkPortalDetector* GetInstance();
+
+// Returns |true| if NetworkPortalDetector was Initialized and it is safe to
+// call GetInstance.
+CHROMEOS_EXPORT bool IsInitialized();
+
+// Deletes the instance of the NetworkPortalDetector.
+CHROMEOS_EXPORT void Shutdown();
+
+CHROMEOS_EXPORT void SetNetworkPortalDetector(
+    NetworkPortalDetector* network_portal_detector);
+
+// Initializes network portal detector for testing. The
+// |network_portal_detector| will be owned by the internal pointer
+// and deleted by Shutdown().
+CHROMEOS_EXPORT void InitializeForTesting(
+    NetworkPortalDetector* network_portal_detector);
+CHROMEOS_EXPORT bool SetForTesting();
+
+}  // namespace network_portal_detector
+
 }  // namespace chromeos
 
 #endif  // CHROMEOS_NETWORK_PORTAL_DETECTOR_NETWORK_PORTAL_DETECTOR_H_
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 2eb98f5..83b3d475 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -30,6 +30,10 @@
     "//components/google/core/browser",
     "//components/search",
     "//components/search_engines",
+    "//components/undo",
+    "//components/strings",
+    "//components/leveldb_proto",
+    "//components/pref_registry",
   ]
 
   if (!is_ios) {
@@ -78,7 +82,6 @@
       "//components/json_schema",
       "//components/keyed_service/content",
       "//components/language_usage_metrics",
-      "//components/leveldb_proto",
       "//components/login",
       "//components/memory_pressure",
       "//components/metrics",
@@ -109,7 +112,6 @@
       "//components/precache/core",
       "//components/precache/content",
       "//components/proxy_config",
-      "//components/pref_registry",
       "//components/query_parser",
       "//components/rappor",
       "//components/renderer_context_menu",
@@ -119,7 +121,6 @@
       "//components/sessions",
       "//components/signin/core/browser",
       "//components/startup_metric_utils",
-      "//components/strings",
       "//components/sync_driver",
       "//components/tracing",
       "//components/tracing:startup_tracing",
@@ -129,7 +130,6 @@
       "//components/translate/core/browser",
       "//components/translate/core/common",
       "//components/ui/zoom",
-      "//components/undo",
       "//components/update_client",
       "//components/upload_list",
       "//components/url_formatter",
@@ -299,12 +299,15 @@
     "//base/test:test_support",
     "//components/bookmarks/browser:unit_tests",
     "//components/content_settings/core/common",
-    "//net",
+    "//components/google/core/browser:unit_tests",
     "//components/search:unit_tests",
+    "//components/undo:unit_tests",
+    "//net",
     "//ui/base",
     "//ui/resources:ui_test_pak",
-    "//components/google/core/browser:unit_tests",
     "//components/search_engines:unit_tests",
+    "//components/undo:unit_tests",
+    "//components/leveldb_proto:unit_tests",
   ]
 
   if (!is_ios) {
@@ -355,7 +358,6 @@
       "//components/keyed_service/content:unit_tests",
       "//components/keyed_service/core:unit_tests",
       "//components/language_usage_metrics:unit_tests",
-      "//components/leveldb_proto:unit_tests",
       "//components/login:unit_tests",
       "//components/memory_pressure:unit_tests",
       "//components/metrics:unit_tests",
@@ -384,7 +386,6 @@
       "//components/translate/core/browser:unit_tests",
       "//components/translate/core/common:unit_tests",
       "//components/translate/core/language_detection:unit_tests",
-      "//components/undo:unit_tests",
       "//components/url_formatter:unit_tests",
       "//components/url_matcher:unit_tests",
       "//components/update_client:unit_tests",
@@ -576,6 +577,8 @@
 
 test("components_perftests") {
   sources = [
+    "scheduler/base/nestable_task_runner_for_test.cc",
+    "scheduler/base/nestable_task_runner_for_test.h",
     "scheduler/base/task_queue_manager_perftest.cc",
     "visitedlink/test/visitedlink_perftest.cc",
   ]
diff --git a/components/autofill/core/browser/autofill_download_manager.h b/components/autofill/core/browser/autofill_download_manager.h
index 1c72eaf..eaf7b49 100644
--- a/components/autofill/core/browser/autofill_download_manager.h
+++ b/components/autofill/core/browser/autofill_download_manager.h
@@ -67,7 +67,7 @@
   // Starts a query request to Autofill servers. The observer is called with the
   // list of the fields of all requested forms.
   // |forms| - array of forms aggregated in this request.
-  bool StartQueryRequest(const std::vector<FormStructure*>& forms);
+  virtual bool StartQueryRequest(const std::vector<FormStructure*>& forms);
 
   // Starts an upload request for the given |form|, unless throttled by the
   // server. The probability of the request going over the wire is
@@ -82,10 +82,11 @@
   // Note that in this case, |form.FormSignature()| gives the signature for the
   // registration form on which the password was generated, rather than the
   // submitted form's signature.
-  bool StartUploadRequest(const FormStructure& form,
-                          bool form_was_autofilled,
-                          const ServerFieldTypeSet& available_field_types,
-                          const std::string& login_form_signature);
+  virtual bool StartUploadRequest(
+      const FormStructure& form,
+      bool form_was_autofilled,
+      const ServerFieldTypeSet& available_field_types,
+      const std::string& login_form_signature);
 
  private:
   friend class AutofillDownloadTest;
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 6c5948a4..5443327 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -1394,7 +1394,11 @@
 }
 
 void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
+  if (forms.empty())
+    return;
+
   std::vector<FormStructure*> non_queryable_forms;
+  std::vector<FormStructure*> queryable_forms;
   for (const FormData& form : forms) {
     scoped_ptr<FormStructure> form_structure(new FormStructure(form));
 
@@ -1408,24 +1412,26 @@
 
     form_structure->DetermineHeuristicTypes();
 
-    if (form_structure->ShouldBeCrowdsourced()) {
+    // Ownership is transferred to |form_structures_| which maintains it until
+    // the manager is Reset() or destroyed. It is safe to use references below
+    // as long as receivers don't take ownership.
+    form_structures_.push_back(form_structure.Pass());
+
+    if (form_structures_.back()->ShouldBeCrowdsourced()) {
       AutofillMetrics::LogPasswordFormQueryVolume(
           AutofillMetrics::CURRENT_QUERY);
-      form_structures_.push_back(form_structure.release());
+      queryable_forms.push_back(form_structures_.back());
     } else {
-      non_queryable_forms.push_back(form_structure.release());
+      non_queryable_forms.push_back(form_structures_.back());
     }
   }
 
-  if (!form_structures_.empty() && download_manager_) {
+  if (!queryable_forms.empty() && download_manager_) {
     // Query the server if at least one of the forms was parsed.
-    download_manager_->StartQueryRequest(form_structures_.get());
+    download_manager_->StartQueryRequest(queryable_forms);
   }
 
-  for (FormStructure* structure : non_queryable_forms)
-    form_structures_.push_back(structure);
-
-  if (!form_structures_.empty()) {
+  if (!queryable_forms.empty() || !non_queryable_forms.empty()) {
     AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::FORMS_LOADED);
 #if defined(OS_IOS)
     // Log this from same location as AutofillMetrics::FORMS_LOADED to ensure
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index c9f385f..b365e29 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -240,6 +240,11 @@
     return external_delegate_;
   }
 
+  // Exposed for testing.
+  void set_download_manager(AutofillDownloadManager* manager) {
+    download_manager_.reset(manager);
+  }
+
  private:
   // AutofillDownloadManager::Observer:
   void OnLoadedServerPredictions(const std::string& response_xml) override;
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 033328d..6f9fc2c 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -17,9 +17,11 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/histogram_tester.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/autofill/core/browser/autocomplete_history_manager.h"
+#include "components/autofill/core/browser/autofill_download_manager.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
@@ -207,6 +209,32 @@
   DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
 };
 
+class TestAutofillDownloadManager : public AutofillDownloadManager {
+ public:
+  TestAutofillDownloadManager(AutofillDriver* driver,
+                              PrefService* pref_service,
+                              AutofillDownloadManager::Observer* observer)
+      : AutofillDownloadManager(driver, pref_service, observer) {}
+
+  bool StartQueryRequest(const std::vector<FormStructure*>& forms) override {
+    last_queried_forms_ = forms;
+    return true;
+  }
+
+  // Verify that the last queried forms equal |expected_forms|.
+  void VerifyLastQueriedForms(const std::vector<FormData>& expected_forms) {
+    ASSERT_EQ(expected_forms.size(), last_queried_forms_.size());
+    for (size_t i = 0; i < expected_forms.size(); ++i) {
+      EXPECT_EQ(*last_queried_forms_[i], expected_forms[i]);
+    }
+  }
+
+ private:
+  std::vector<FormStructure*> last_queried_forms_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAutofillDownloadManager);
+};
+
 void ExpectFilledField(const char* expected_label,
                        const char* expected_name,
                        const char* expected_value,
@@ -603,7 +631,11 @@
     autofill_driver_->SetURLRequestContext(request_context_.get());
     autofill_manager_.reset(new TestAutofillManager(
         autofill_driver_.get(), &autofill_client_, &personal_data_));
-
+    download_manager_ = new TestAutofillDownloadManager(
+        autofill_driver_.get(), autofill_client_.GetPrefs(),
+        autofill_manager_.get());
+    // AutofillManager takes ownership of |download_manager_|.
+    autofill_manager_->set_download_manager(download_manager_);
     external_delegate_.reset(new TestAutofillExternalDelegate(
         autofill_manager_.get(),
         autofill_driver_.get()));
@@ -780,6 +812,7 @@
   scoped_ptr<TestAutofillManager> autofill_manager_;
   scoped_ptr<TestAutofillExternalDelegate> external_delegate_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+  TestAutofillDownloadManager* download_manager_;
   TestPersonalDataManager personal_data_;
 };
 
@@ -808,6 +841,62 @@
   DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
 };
 
+// Test that calling OnFormsSeen with an empty set of forms (such as when
+// reloading a page or when the renderer processes a set of forms but detects
+// no changes) does not load the forms again.
+TEST_F(AutofillManagerTest, OnFormsSeen_Empty) {
+  // Set up our form data.
+  FormData form;
+  test::CreateTestAddressFormData(&form);
+  std::vector<FormData> forms(1, form);
+
+  base::HistogramTester histogram_tester;
+  FormsSeen(forms);
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.UserHappiness", 0 /* FORMS_LOADED */, 1);
+
+  // No more forms, metric is not logged.
+  forms.clear();
+  FormsSeen(forms);
+  histogram_tester.ExpectUniqueSample(
+      "Autofill.UserHappiness", 0 /* FORMS_LOADED */, 1);
+}
+
+// Test that calling OnFormsSeen consecutively with a different set of forms
+// will query for each separately.
+TEST_F(AutofillManagerTest, OnFormsSeen_DifferentFormStructures) {
+  // Set up our form data.
+  FormData form;
+  test::CreateTestAddressFormData(&form);
+  std::vector<FormData> forms(1, form);
+
+  base::HistogramTester histogram_tester;
+  FormsSeen(forms);
+  histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+                                      0 /* FORMS_LOADED */, 1);
+  download_manager_->VerifyLastQueriedForms(forms);
+
+  // Different form structure.
+  FormData form2;
+  form2.name = ASCIIToUTF16("MyForm");
+  form2.origin = GURL("https://myform.com/form.html");
+  form2.action = GURL("https://myform.com/submit.html");
+  FormFieldData field;
+  test::CreateTestFormField("First Name", "firstname", "", "text", &field);
+  form2.fields.push_back(field);
+  test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
+  form2.fields.push_back(field);
+  test::CreateTestFormField("Email", "email", "", "text", &field);
+  form2.fields.push_back(field);
+
+  forms.clear();
+  forms.push_back(form2);
+  FormsSeen(forms);
+  histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+                                      0 /* FORMS_LOADED */, 2);
+  download_manager_->VerifyLastQueriedForms(forms);
+}
+
 // Test that we return all address profile suggestions when all form fields are
 // empty.
 TEST_F(AutofillManagerTest, GetProfileSuggestionsEmptyValue) {
diff --git a/components/autofill/core/common/password_form.cc b/components/autofill/core/common/password_form.cc
index 4160085..2066ce8 100644
--- a/components/autofill/core/common/password_form.cc
+++ b/components/autofill/core/common/password_form.cc
@@ -21,8 +21,7 @@
                         base::DictionaryValue* target) {
   target->SetInteger("scheme", form.scheme);
   target->SetString("signon_realm", form.signon_realm);
-  target->SetString("signon_realm", form.signon_realm);
-  target->SetString("original_signon_realm", form.original_signon_realm);
+  target->SetBoolean("is_public_suffix_match", form.is_public_suffix_match);
   target->SetString("origin", form.origin.possibly_invalid_spec());
   target->SetString("action", form.action.possibly_invalid_spec());
   target->SetString("submit_element", form.submit_element);
@@ -82,19 +81,15 @@
       skip_zero_click(false),
       layout(Layout::LAYOUT_OTHER),
       was_parsed_using_autofill_predictions(false),
-      is_alive(true) {
-}
+      is_alive(true),
+      is_public_suffix_match(false),
+      is_affiliated(false) {}
 
 PasswordForm::~PasswordForm() {
   CHECK(is_alive);
   is_alive = false;
 }
 
-bool PasswordForm::IsPublicSuffixMatch() const {
-  CHECK(is_alive);
-  return !original_signon_realm.empty();
-}
-
 bool PasswordForm::IsPossibleChangePasswordForm() const {
   return !new_password_element.empty() &&
          layout != PasswordForm::Layout::LAYOUT_LOGIN_AND_SIGNUP;
@@ -105,37 +100,30 @@
 }
 
 bool PasswordForm::operator==(const PasswordForm& form) const {
-  return scheme == form.scheme &&
-      signon_realm == form.signon_realm &&
-      original_signon_realm == form.original_signon_realm &&
-      origin == form.origin &&
-      action == form.action &&
-      submit_element == form.submit_element &&
-      username_element == form.username_element &&
-      username_marked_by_site == form.username_marked_by_site &&
-      username_value == form.username_value &&
-      other_possible_usernames == form.other_possible_usernames &&
-      password_element == form.password_element &&
-      password_value == form.password_value &&
-      new_password_element == form.new_password_element &&
-      new_password_marked_by_site == form.new_password_marked_by_site &&
-      new_password_value == form.new_password_value &&
-      ssl_valid == form.ssl_valid &&
-      preferred == form.preferred &&
-      date_created == form.date_created &&
-      date_synced == form.date_synced &&
-      blacklisted_by_user == form.blacklisted_by_user &&
-      type == form.type &&
-      times_used == form.times_used &&
-      form_data.SameFormAs(form.form_data) &&
-      generation_upload_status == form.generation_upload_status &&
-      display_name == form.display_name &&
-      icon_url == form.icon_url &&
-      federation_url == form.federation_url &&
-      skip_zero_click == form.skip_zero_click &&
-      layout == form.layout &&
-      was_parsed_using_autofill_predictions ==
-          form.was_parsed_using_autofill_predictions;
+  return scheme == form.scheme && signon_realm == form.signon_realm &&
+         origin == form.origin && action == form.action &&
+         submit_element == form.submit_element &&
+         username_element == form.username_element &&
+         username_marked_by_site == form.username_marked_by_site &&
+         username_value == form.username_value &&
+         other_possible_usernames == form.other_possible_usernames &&
+         password_element == form.password_element &&
+         password_value == form.password_value &&
+         new_password_element == form.new_password_element &&
+         new_password_marked_by_site == form.new_password_marked_by_site &&
+         new_password_value == form.new_password_value &&
+         ssl_valid == form.ssl_valid && preferred == form.preferred &&
+         date_created == form.date_created && date_synced == form.date_synced &&
+         blacklisted_by_user == form.blacklisted_by_user && type == form.type &&
+         times_used == form.times_used &&
+         form_data.SameFormAs(form.form_data) &&
+         generation_upload_status == form.generation_upload_status &&
+         display_name == form.display_name && icon_url == form.icon_url &&
+         federation_url == form.federation_url &&
+         skip_zero_click == form.skip_zero_click && layout == form.layout &&
+         was_parsed_using_autofill_predictions ==
+             form.was_parsed_using_autofill_predictions &&
+         is_public_suffix_match == form.is_public_suffix_match;
 }
 
 bool PasswordForm::operator!=(const PasswordForm& form) const {
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h
index f58222d9..57a9d9df 100644
--- a/components/autofill/core/common/password_form.h
+++ b/components/autofill/core/common/password_form.h
@@ -84,24 +84,6 @@
   // data from the database, so it must not be empty.
   std::string signon_realm;
 
-  // The original "Realm" for the sign-on (scheme, host, port for SCHEME_HTML,
-  // and contains the HTTP realm for dialog-based forms). This realm is only set
-  // when two PasswordForms are matched when trying to find a login/pass pair
-  // for a site. It is only set to a non-empty value during a match of the
-  // original stored login/pass and the current observed form if all these
-  // statements are true:
-  // 1) The full signon_realm is not the same.
-  // 2) The registry controlled domain is the same. For example; example.com,
-  // m.example.com, foo.login.example.com and www.example.com would all resolve
-  // to example.com since .com is the public suffix.
-  // 3) The scheme is the same.
-  // 4) The port is the same.
-  // For example, if there exists a stored password for http://www.example.com
-  // (where .com is the public suffix) and the observed form is
-  // http://m.example.com, |original_signon_realm| must be set to
-  // http://www.example.com.
-  std::string original_signon_realm;
-
   // An origin URL consists of the scheme, host, port and path; the rest is
   // stripped. This is the primary data used by the PasswordManager to decide
   // (in longest matching prefix fashion) whether or not a given PasswordForm
@@ -279,8 +261,11 @@
   // TODO(vabr): Remove |is_alive| once http://crbug.com/486931 is fixed.
   bool is_alive;  // Set on construction, reset on destruction.
 
-  // Returns true if this match was found using public suffix matching.
-  bool IsPublicSuffixMatch() const;
+  // if true this match was found using public suffix matching.
+  bool is_public_suffix_match;
+
+  // if true this form is affiliated with Android credentials.
+  bool is_affiliated;
 
   // Return true if we consider this form to be a change password form.
   // We use only client heuristics, so it could include signup forms.
diff --git a/components/autofill/core/common/password_form_fill_data.cc b/components/autofill/core/common/password_form_fill_data.cc
index 702d279..36000f87 100644
--- a/components/autofill/core/common/password_form_fill_data.cc
+++ b/components/autofill/core/common/password_form_fill_data.cc
@@ -58,7 +58,8 @@
   result->is_possible_change_password_form =
       form_on_page.IsPossibleChangePasswordForm();
 
-  result->preferred_realm = preferred_match->original_signon_realm;
+  if (preferred_match->is_public_suffix_match || preferred_match->is_affiliated)
+    result->preferred_realm = preferred_match->signon_realm;
 
   // Copy additional username/value pairs.
   PasswordFormMap::const_iterator iter;
@@ -66,7 +67,8 @@
     if (iter->second != preferred_match) {
       PasswordAndRealm value;
       value.password = iter->second->password_value;
-      value.realm = iter->second->original_signon_realm;
+      if (iter->second->is_public_suffix_match)
+        value.realm = iter->second->signon_realm;
       result->additional_logins[iter->first] = value;
     }
     if (enable_other_possible_usernames &&
@@ -78,7 +80,8 @@
       UsernamesCollectionKey key;
       key.username = iter->first;
       key.password = iter->second->password_value;
-      key.realm = iter->second->original_signon_realm;
+      if (iter->second->is_public_suffix_match)
+        key.realm = iter->second->signon_realm;
       result->other_possible_usernames[key] =
           iter->second->other_possible_usernames;
     }
diff --git a/components/autofill/core/common/password_form_fill_data_unittest.cc b/components/autofill/core/common/password_form_fill_data_unittest.cc
index aafb4732..97355537 100644
--- a/components/autofill/core/common/password_form_fill_data_unittest.cc
+++ b/components/autofill/core/common/password_form_fill_data_unittest.cc
@@ -60,7 +60,7 @@
   EXPECT_TRUE(result.wait_for_username);
   // The preferred realm should be empty since it's the same as the realm of
   // the form.
-  EXPECT_EQ(result.preferred_realm, "");
+  EXPECT_EQ(std::string(), result.preferred_realm);
 
   PasswordFormFillData result2;
   InitPasswordFormFillData(form_on_page,
@@ -103,13 +103,14 @@
   preferred_match.password_element = ASCIIToUTF16("password");
   preferred_match.password_value = ASCIIToUTF16("test");
   preferred_match.submit_element = ASCIIToUTF16("");
-  preferred_match.signon_realm = "https://mobile.foo.com/";
-  preferred_match.original_signon_realm = "https://foo.com/";
+  preferred_match.signon_realm = "https://foo.com/";
+  preferred_match.is_public_suffix_match = true;
   preferred_match.ssl_valid = true;
   preferred_match.preferred = true;
   preferred_match.scheme = PasswordForm::SCHEME_HTML;
 
-  // Create a match that matches exactly, so |original_signon_realm| is not set.
+  // Create a match that matches exactly, so |is_public_suffix_match| has a
+  // default value false.
   scoped_ptr<PasswordForm> scoped_exact_match(new PasswordForm);
   PasswordForm& exact_match = *scoped_exact_match;
   exact_match.origin = GURL("https://foo.com/");
@@ -125,7 +126,7 @@
   exact_match.scheme = PasswordForm::SCHEME_HTML;
 
   // Create a match that was matched using public suffix, so
-  // |original_signon_realm| is set to where the result came from.
+  // |is_public_suffix_match| == true.
   scoped_ptr<PasswordForm> scoped_public_suffix_match(new PasswordForm);
   PasswordForm& public_suffix_match = *scoped_public_suffix_match;
   public_suffix_match.origin = GURL("https://foo.com/");
@@ -135,7 +136,7 @@
   public_suffix_match.password_element = ASCIIToUTF16("password");
   public_suffix_match.password_value = ASCIIToUTF16("test");
   public_suffix_match.submit_element = ASCIIToUTF16("");
-  public_suffix_match.original_signon_realm = "https://subdomain.foo.com/";
+  public_suffix_match.is_public_suffix_match = true;
   public_suffix_match.signon_realm = "https://foo.com/";
   public_suffix_match.ssl_valid = true;
   public_suffix_match.preferred = false;
@@ -155,20 +156,19 @@
                            false,
                            &result);
   EXPECT_TRUE(result.wait_for_username);
-  // The preferred realm should match the original signon realm from the
+  // The preferred realm should match the signon realm from the
   // preferred match so the user can see where the result came from.
-  EXPECT_EQ(result.preferred_realm,
-            preferred_match.original_signon_realm);
+  EXPECT_EQ(preferred_match.signon_realm, result.preferred_realm);
 
   // The realm of the exact match should be empty.
   PasswordFormFillData::LoginCollection::const_iterator iter =
       result.additional_logins.find(exact_match.username_value);
-  EXPECT_EQ(iter->second.realm, "");
+  EXPECT_EQ(std::string(), iter->second.realm);
 
   // The realm of the public suffix match should be set to the original signon
   // realm so the user can see where the result came from.
   iter = result.additional_logins.find(public_suffix_match.username_value);
-  EXPECT_EQ(iter->second.realm, public_suffix_match.original_signon_realm);
+  EXPECT_EQ(iter->second.realm, public_suffix_match.signon_realm);
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index c7c51cc..58e1c2d4 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -80,8 +80,6 @@
                 GetStringFromID(FormSchemeToStringID(form.scheme)));
   log.SetString(GetStringFromID(STRING_SIGNON_REALM),
                 ScrubURL(GURL(form.signon_realm)));
-  log.SetString(GetStringFromID(STRING_ORIGINAL_SIGNON_REALM),
-                ScrubURL(GURL(form.original_signon_realm)));
   log.SetString(GetStringFromID(STRING_ORIGIN), ScrubURL(form.origin));
   log.SetString(GetStringFromID(STRING_ACTION), ScrubURL(form.action));
   log.SetString(GetStringFromID(STRING_USERNAME_ELEMENT),
@@ -94,7 +92,8 @@
   log.SetBoolean(GetStringFromID(STRING_PASSWORD_GENERATED),
                  form.type == PasswordForm::TYPE_GENERATED);
   log.SetInteger(GetStringFromID(STRING_TIMES_USED), form.times_used);
-  log.SetBoolean(GetStringFromID(STRING_PSL_MATCH), form.IsPublicSuffixMatch());
+  log.SetBoolean(GetStringFromID(STRING_PSL_MATCH),
+                 form.is_public_suffix_match);
   LogValue(label, log);
 }
 
@@ -184,8 +183,6 @@
       return "Scheme";
     case SavePasswordProgressLogger::STRING_SIGNON_REALM:
       return "Signon realm";
-    case SavePasswordProgressLogger::STRING_ORIGINAL_SIGNON_REALM:
-      return "Original signon realm";
     case SavePasswordProgressLogger::STRING_ORIGIN:
       return "Origin";
     case SavePasswordProgressLogger::STRING_ACTION:
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h
index d018d434d..ff43e90 100644
--- a/components/autofill/core/common/save_password_progress_logger.h
+++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -44,7 +44,6 @@
     STRING_SCHEME_DIGEST,
     STRING_SCHEME_MESSAGE,
     STRING_SIGNON_REALM,
-    STRING_ORIGINAL_SIGNON_REALM,
     STRING_ORIGIN,
     STRING_ACTION,
     STRING_USERNAME_ELEMENT,
diff --git a/components/browser_watcher/endsession_watcher_window_win.cc b/components/browser_watcher/endsession_watcher_window_win.cc
index ddf99327..cf4bb82 100644
--- a/components/browser_watcher/endsession_watcher_window_win.cc
+++ b/components/browser_watcher/endsession_watcher_window_win.cc
@@ -5,7 +5,6 @@
 #include "components/browser_watcher/endsession_watcher_window_win.h"
 
 #include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/win/wrapped_window_proc.h"
 
 namespace browser_watcher {
diff --git a/components/bubble/bubble_controller.cc b/components/bubble/bubble_controller.cc
index 7dc65b03..511c225 100644
--- a/components/bubble/bubble_controller.cc
+++ b/components/bubble/bubble_controller.cc
@@ -53,12 +53,14 @@
   bubble_ui_->UpdateAnchorPosition();
 }
 
-bool BubbleController::ShouldClose(BubbleCloseReason reason) {
+bool BubbleController::ShouldClose(BubbleCloseReason reason) const {
   DCHECK(bubble_ui_);
-  if (delegate_->ShouldClose(reason) || reason == BUBBLE_CLOSE_FORCED) {
-    bubble_ui_->Close();
-    bubble_ui_.reset();
-    return true;
-  }
-  return false;
+  return delegate_->ShouldClose(reason) || reason == BUBBLE_CLOSE_FORCED;
+}
+
+void BubbleController::DoClose() {
+  DCHECK(bubble_ui_);
+  bubble_ui_->Close();
+  bubble_ui_.reset();
+  delegate_->DidClose();
 }
diff --git a/components/bubble/bubble_controller.h b/components/bubble/bubble_controller.h
index cdb685d..39a20ba 100644
--- a/components/bubble/bubble_controller.h
+++ b/components/bubble/bubble_controller.h
@@ -44,9 +44,11 @@
   // Important when there's a UI change (ex: fullscreen transition).
   void UpdateAnchorPosition();
 
-  // Cleans up the delegate and its UI if it closed.
-  // Returns true if the bubble was closed.
-  bool ShouldClose(BubbleCloseReason reason);
+  // Returns true if the bubble should be closed.
+  bool ShouldClose(BubbleCloseReason reason) const;
+
+  // Cleans up the delegate and its UI.
+  void DoClose();
 
   BubbleManager* manager_;
   scoped_ptr<BubbleDelegate> delegate_;
diff --git a/components/bubble/bubble_delegate.cc b/components/bubble/bubble_delegate.cc
index 9c739060..3e5ff58 100644
--- a/components/bubble/bubble_delegate.cc
+++ b/components/bubble/bubble_delegate.cc
@@ -8,10 +8,12 @@
 
 BubbleDelegate::~BubbleDelegate() {}
 
-bool BubbleDelegate::ShouldClose(BubbleCloseReason reason) {
+bool BubbleDelegate::ShouldClose(BubbleCloseReason reason) const {
   return true;
 }
 
+void BubbleDelegate::DidClose() {}
+
 bool BubbleDelegate::UpdateBubbleUi(BubbleUi* bubble_ui) {
   return false;
 }
diff --git a/components/bubble/bubble_delegate.h b/components/bubble/bubble_delegate.h
index f53b94b1..3127dfd 100644
--- a/components/bubble/bubble_delegate.h
+++ b/components/bubble/bubble_delegate.h
@@ -23,7 +23,10 @@
   // Called by BubbleController to notify a bubble of an event that the bubble
   // might want to close on. Return true if the bubble should close for the
   // specified reason.
-  virtual bool ShouldClose(BubbleCloseReason reason);
+  virtual bool ShouldClose(BubbleCloseReason reason) const;
+
+  // Called by BubbleController to notify a bubble that it has closed.
+  virtual void DidClose();
 
   // Called by BubbleController to build the UI that will represent this bubble.
   // BubbleDelegate should not keep a reference to this newly created UI.
diff --git a/components/bubble/bubble_manager.cc b/components/bubble/bubble_manager.cc
index 41529f9..d8883f8 100644
--- a/components/bubble/bubble_manager.cc
+++ b/components/bubble/bubble_manager.cc
@@ -52,6 +52,7 @@
     if (*iter == bubble.get()) {
       bool closed = (*iter)->ShouldClose(reason);
       if (closed) {
+        (*iter)->DoClose();
         FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
                           OnBubbleClosed((*iter)->AsWeakPtr(), reason));
         iter = controllers_.erase(iter);
@@ -80,6 +81,7 @@
   for (auto iter = controllers_.begin(); iter != controllers_.end();) {
     bool closed = (*iter)->ShouldClose(reason);
     if (closed) {
+      (*iter)->DoClose();
       FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
                         OnBubbleClosed((*iter)->AsWeakPtr(), reason));
     }
diff --git a/components/bubble/bubble_manager_mocks.cc b/components/bubble/bubble_manager_mocks.cc
index 7e8d1d9..067e5f3b 100644
--- a/components/bubble/bubble_manager_mocks.cc
+++ b/components/bubble/bubble_manager_mocks.cc
@@ -8,26 +8,26 @@
 
 MockBubbleUi::~MockBubbleUi() { Destroyed(); }
 
-MockBubbleDelegate::MockBubbleDelegate() {}
+MockBubbleDelegate::MockBubbleDelegate() : bubble_ui_(new MockBubbleUi) {}
 
 MockBubbleDelegate::~MockBubbleDelegate() { Destroyed(); }
 
 // static
 scoped_ptr<MockBubbleDelegate> MockBubbleDelegate::Default() {
   MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
   EXPECT_CALL(*delegate, ShouldClose(testing::_))
       .WillOnce(testing::Return(true));
+  EXPECT_CALL(*delegate, DidClose());
+  EXPECT_CALL(*delegate, Destroyed());
   return make_scoped_ptr(delegate);
 }
 
 // static
 scoped_ptr<MockBubbleDelegate> MockBubbleDelegate::Stubborn() {
   MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
   EXPECT_CALL(*delegate, ShouldClose(testing::_))
       .WillRepeatedly(testing::Return(false));
+  EXPECT_CALL(*delegate, DidClose());
+  EXPECT_CALL(*delegate, Destroyed());
   return make_scoped_ptr(delegate);
 }
diff --git a/components/bubble/bubble_manager_mocks.h b/components/bubble/bubble_manager_mocks.h
index 60becce..460a882a 100644
--- a/components/bubble/bubble_manager_mocks.h
+++ b/components/bubble/bubble_manager_mocks.h
@@ -37,13 +37,11 @@
   // Stubborn bubble shows UI and doesn't want to close.
   static scoped_ptr<MockBubbleDelegate> Stubborn();
 
-  MOCK_METHOD1(ShouldClose, bool(BubbleCloseReason reason));
+  MOCK_CONST_METHOD1(ShouldClose, bool(BubbleCloseReason reason));
+  MOCK_METHOD0(DidClose, void());
 
   // A scoped_ptr can't be returned in MOCK_METHOD.
-  MOCK_METHOD0(BuildBubbleUiMock, BubbleUi*());
-  scoped_ptr<BubbleUi> BuildBubbleUi() override {
-    return make_scoped_ptr(BuildBubbleUiMock());
-  }
+  scoped_ptr<BubbleUi> BuildBubbleUi() override { return bubble_ui_.Pass(); }
 
   MOCK_METHOD1(UpdateBubbleUi, bool(BubbleUi*));
 
@@ -52,7 +50,12 @@
   // To verify destructor call.
   MOCK_METHOD0(Destroyed, void());
 
+  // Will be null after |BubbleManager::ShowBubble| is called.
+  MockBubbleUi* bubble_ui() { return bubble_ui_.get(); }
+
  private:
+  scoped_ptr<MockBubbleUi> bubble_ui_;
+
   DISALLOW_COPY_AND_ASSIGN(MockBubbleDelegate);
 };
 
diff --git a/components/bubble/bubble_manager_unittest.cc b/components/bubble/bubble_manager_unittest.cc
index c481b7a..f888987e 100644
--- a/components/bubble/bubble_manager_unittest.cc
+++ b/components/bubble/bubble_manager_unittest.cc
@@ -10,30 +10,30 @@
 
 namespace {
 
-// Helper class used to test chaining another bubble.
-class DelegateChainHelper {
+class ChainShowBubbleDelegate : public MockBubbleDelegate {
  public:
-  DelegateChainHelper(BubbleManager* manager,
-                      scoped_ptr<BubbleDelegate> next_delegate);
+  ChainShowBubbleDelegate(BubbleManager* manager,
+                          scoped_ptr<BubbleDelegate> delegate)
+      : manager_(manager), delegate_(delegate.Pass()), closed_(false) {
+    EXPECT_CALL(*this, ShouldClose(testing::_)).WillOnce(testing::Return(true));
+  }
 
-  // Will show the bubble in |next_delegate_|.
-  void Chain() { manager_->ShowBubble(next_delegate_.Pass()); }
+  ~ChainShowBubbleDelegate() override { EXPECT_TRUE(closed_); }
 
-  // True if the bubble was taken by the bubble manager.
-  bool BubbleWasTaken() { return !next_delegate_; }
+  void DidClose() override {
+    MockBubbleDelegate::DidClose();
+    manager_->ShowBubble(delegate_.Pass());
+    closed_ = true;
+  }
 
  private:
-  BubbleManager* manager_;  // Weak.
-  scoped_ptr<BubbleDelegate> next_delegate_;
+  BubbleManager* manager_;
+  scoped_ptr<BubbleDelegate> delegate_;
+  bool closed_;
 
-  DISALLOW_COPY_AND_ASSIGN(DelegateChainHelper);
+  DISALLOW_COPY_AND_ASSIGN(ChainShowBubbleDelegate);
 };
 
-DelegateChainHelper::DelegateChainHelper(
-    BubbleManager* manager,
-    scoped_ptr<BubbleDelegate> next_delegate)
-    : manager_(manager), next_delegate_(next_delegate.Pass()) {}
-
 class MockBubbleManagerObserver : public BubbleManager::BubbleManagerObserver {
  public:
   MockBubbleManagerObserver() {}
@@ -74,41 +74,27 @@
 }
 
 TEST_F(BubbleManagerTest, ManagerShowsBubbleUi) {
-  // Manager will delete bubble_ui.
-  MockBubbleUi* bubble_ui = new MockBubbleUi;
+  scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default();
+
+  MockBubbleUi* bubble_ui = delegate->bubble_ui();
   EXPECT_CALL(*bubble_ui, Destroyed());
   EXPECT_CALL(*bubble_ui, Show(testing::_));
   EXPECT_CALL(*bubble_ui, Close());
   EXPECT_CALL(*bubble_ui, UpdateAnchorPosition()).Times(0);
 
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, Destroyed());
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(bubble_ui));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::Return(true));
-
-  manager_->ShowBubble(make_scoped_ptr(delegate));
+  manager_->ShowBubble(delegate.Pass());
 }
 
-TEST_F(BubbleManagerTest, ManagerUpdatesBubbleUi) {
-  // Manager will delete bubble_ui.
-  MockBubbleUi* bubble_ui = new MockBubbleUi;
+TEST_F(BubbleManagerTest, ManagerUpdatesBubbleUiAnchor) {
+  scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default();
+
+  MockBubbleUi* bubble_ui = delegate->bubble_ui();
   EXPECT_CALL(*bubble_ui, Destroyed());
   EXPECT_CALL(*bubble_ui, Show(testing::_));
   EXPECT_CALL(*bubble_ui, Close());
   EXPECT_CALL(*bubble_ui, UpdateAnchorPosition());
 
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, Destroyed());
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(bubble_ui));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::Return(true));
-
-  manager_->ShowBubble(make_scoped_ptr(delegate));
+  manager_->ShowBubble(delegate.Pass());
   manager_->UpdateAllBubbleAnchors();
 }
 
@@ -241,94 +227,27 @@
 }
 
 TEST_F(BubbleManagerTest, AllowBubbleChainingOnClose) {
-  scoped_ptr<BubbleDelegate> chained_delegate = MockBubbleDelegate::Default();
-  DelegateChainHelper chain_helper(manager_.get(), chained_delegate.Pass());
-
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
-                                   &chain_helper, &DelegateChainHelper::Chain),
-                               testing::Return(true)));
-
-  BubbleReference ref = manager_->ShowBubble(make_scoped_ptr(delegate));
+  BubbleReference ref =
+      manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+          manager_.get(), MockBubbleDelegate::Default())));
   ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED));
-
-  ASSERT_TRUE(chain_helper.BubbleWasTaken());
 }
 
 TEST_F(BubbleManagerTest, AllowBubbleChainingOnCloseAll) {
-  scoped_ptr<BubbleDelegate> chained_delegate = MockBubbleDelegate::Default();
-  DelegateChainHelper chain_helper(manager_.get(), chained_delegate.Pass());
-
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
-                                   &chain_helper, &DelegateChainHelper::Chain),
-                               testing::Return(true)));
-
-  manager_->ShowBubble(make_scoped_ptr(delegate));
+  manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+      manager_.get(), MockBubbleDelegate::Default())));
   manager_->CloseAllBubbles(BUBBLE_CLOSE_FORCED);
-
-  ASSERT_TRUE(chain_helper.BubbleWasTaken());
 }
 
 TEST_F(BubbleManagerTest, BubblesDoNotChainOnDestroy) {
-  // Manager will delete delegate.
-  MockBubbleDelegate* chained_delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*chained_delegate, BuildBubbleUiMock()).Times(0);
+  scoped_ptr<MockBubbleDelegate> chained_delegate(new MockBubbleDelegate);
+  EXPECT_CALL(*chained_delegate->bubble_ui(), Show(testing::_)).Times(0);
   EXPECT_CALL(*chained_delegate, ShouldClose(testing::_)).Times(0);
+  EXPECT_CALL(*chained_delegate, DidClose()).Times(0);
 
-  DelegateChainHelper chain_helper(manager_.get(),
-                                   make_scoped_ptr(chained_delegate));
-
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
-                                   &chain_helper, &DelegateChainHelper::Chain),
-                               testing::Return(true)));
-
-  manager_->ShowBubble(make_scoped_ptr(delegate));
+  manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+      manager_.get(), chained_delegate.Pass())));
   manager_.reset();
-
-  // The manager will take the bubble, but not show it.
-  ASSERT_TRUE(chain_helper.BubbleWasTaken());
-}
-
-TEST_F(BubbleManagerTest, BubbleUpdatesTrue) {
-  MockBubbleUi* bubble_ui = new MockBubbleUi;
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(bubble_ui));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::Return(true));
-  EXPECT_CALL(*delegate, UpdateBubbleUi(bubble_ui))
-      .WillOnce(testing::Return(true));
-
-  BubbleReference ref = manager_->ShowBubble(make_scoped_ptr(delegate));
-  ASSERT_TRUE(ref->UpdateBubbleUi());
-}
-
-TEST_F(BubbleManagerTest, BubbleUpdatesFalse) {
-  MockBubbleUi* bubble_ui = new MockBubbleUi;
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(bubble_ui));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::Return(true));
-  EXPECT_CALL(*delegate, UpdateBubbleUi(bubble_ui))
-      .WillOnce(testing::Return(false));
-
-  BubbleReference ref = manager_->ShowBubble(make_scoped_ptr(delegate));
-  ASSERT_FALSE(ref->UpdateBubbleUi());
 }
 
 TEST_F(BubbleManagerTest, BubbleCloseReasonIsCalled) {
@@ -348,32 +267,18 @@
   MockBubbleManagerObserver metrics;
   // |chained_delegate| should never be shown.
   EXPECT_CALL(metrics, OnBubbleNeverShown(testing::_));
-  // |delegate| should be forced to close when the manager is destroyed.
+  // The ChainShowBubbleDelegate should be closed when the manager is destroyed.
   EXPECT_CALL(metrics, OnBubbleClosed(testing::_, BUBBLE_CLOSE_FORCED));
   manager_->AddBubbleManagerObserver(&metrics);
 
-  // Manager will delete delegate.
-  MockBubbleDelegate* chained_delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*chained_delegate, BuildBubbleUiMock()).Times(0);
+  scoped_ptr<MockBubbleDelegate> chained_delegate(new MockBubbleDelegate);
+  EXPECT_CALL(*chained_delegate->bubble_ui(), Show(testing::_)).Times(0);
   EXPECT_CALL(*chained_delegate, ShouldClose(testing::_)).Times(0);
+  EXPECT_CALL(*chained_delegate, DidClose()).Times(0);
 
-  DelegateChainHelper chain_helper(manager_.get(),
-                                   make_scoped_ptr(chained_delegate));
-
-  // Manager will delete delegate.
-  MockBubbleDelegate* delegate = new MockBubbleDelegate;
-  EXPECT_CALL(*delegate, BuildBubbleUiMock())
-      .WillOnce(testing::Return(new MockBubbleUi));
-  EXPECT_CALL(*delegate, ShouldClose(testing::_))
-      .WillOnce(testing::DoAll(testing::InvokeWithoutArgs(
-                                   &chain_helper, &DelegateChainHelper::Chain),
-                               testing::Return(true)));
-
-  manager_->ShowBubble(make_scoped_ptr(delegate));
+  manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+      manager_.get(), chained_delegate.Pass())));
   manager_.reset();
-
-  // The manager will take the bubble, but not show it.
-  ASSERT_TRUE(chain_helper.BubbleWasTaken());
 }
 
 }  // namespace
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index 1dd2fbe..432fe7e8 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -138,6 +138,7 @@
       'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc',
       'data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc',
       'data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc',
+      'data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc',
       'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc',
       'data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc',
       'data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc',
@@ -355,7 +356,7 @@
       'nacl/zygote/nacl_fork_delegate_linux_unittest.cc',
     ],
     'navigation_interception_unittest_sources': [
-      'navigation_interception/intercept_navigation_resource_throttle_unittest.cc',
+      'navigation_interception/intercept_navigation_throttle_unittest.cc',
     ],
     'network_hints_unittest_sources': [
       'network_hints/renderer/dns_prefetch_queue_unittest.cc',
@@ -528,6 +529,7 @@
       'proximity_auth/device_to_device_secure_context_unittest.cc',
       'proximity_auth/logging/logging_unittest.cc',
       'proximity_auth/messenger_impl_unittest.cc',
+      'proximity_auth/proximity_auth_pref_manager_unittest.cc',
       'proximity_auth/proximity_auth_system_unittest.cc',
       'proximity_auth/proximity_monitor_impl_unittest.cc',
       'proximity_auth/remote_device_life_cycle_impl_unittest.cc',
diff --git a/components/content_settings/core/browser/content_settings_pref.cc b/components/content_settings/core/browser/content_settings_pref.cc
index 2443e27..95d1cd6c 100644
--- a/components/content_settings/core/browser/content_settings_pref.cc
+++ b/components/content_settings/core/browser/content_settings_pref.cc
@@ -25,15 +25,6 @@
 const char kPerResourceIdentifierPrefName[] = "per_resource";
 const char kLastUsed[] = "last_used";
 
-ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type,
-                                           ContentSetting setting) {
-  if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
-      setting == CONTENT_SETTING_ASK) {
-    return CONTENT_SETTING_BLOCK;
-  }
-  return setting;
-}
-
 // If the given content type supports resource identifiers in user preferences,
 // returns true and sets |pref_key| to the key in the content settings
 // dictionary under which per-resource content settings are stored.
@@ -307,28 +298,13 @@
         }
       }
     }
-    base::Value* value = NULL;
-    if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) {
-      const base::DictionaryValue* setting = NULL;
-      // TODO(xians): Handle the non-dictionary types.
-      if (settings_dictionary->GetDictionaryWithoutPathExpansion(
-              kSettingPath, &setting)) {
-        DCHECK(!setting->empty());
-        value = setting->DeepCopy();
-      }
-    } else {
-      int setting = CONTENT_SETTING_DEFAULT;
-      if (settings_dictionary->GetIntegerWithoutPathExpansion(
-              kSettingPath, &setting)) {
-        DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
-        setting = FixObsoleteCookiePromptMode(content_type_,
-                                              ContentSetting(setting));
-        value = new base::FundamentalValue(setting);
-      }
-    }
 
-    if (value != NULL) {
-      scoped_ptr<base::Value> value_ptr(value);
+    const base::Value* value = nullptr;
+    settings_dictionary->GetWithoutPathExpansion(kSettingPath, &value);
+
+    if (value) {
+      DCHECK(
+          HostContentSettingsMap::IsValueAllowedForType(value, content_type_));
       value_map_.SetValue(pattern_pair.first,
                           pattern_pair.second,
                           content_type_,
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc
index e45fe4a3..cfc4f65a 100644
--- a/components/content_settings/core/browser/content_settings_registry.cc
+++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -92,6 +92,14 @@
   return nullptr;
 }
 
+ContentSettingsRegistry::const_iterator ContentSettingsRegistry::begin() const {
+  return const_iterator(content_settings_info_.begin());
+}
+
+ContentSettingsRegistry::const_iterator ContentSettingsRegistry::end() const {
+  return const_iterator(content_settings_info_.end());
+}
+
 void ContentSettingsRegistry::Init() {
   // TODO(raymes): This registration code should not have to be in a single
   // location. It should be possible to register a setting from the code
diff --git a/components/content_settings/core/browser/content_settings_registry.h b/components/content_settings/core/browser/content_settings_registry.h
index 71bc415..799054e 100644
--- a/components/content_settings/core/browser/content_settings_registry.h
+++ b/components/content_settings/core/browser/content_settings_registry.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "components/content_settings/core/browser/content_settings_info.h"
+#include "components/content_settings/core/browser/content_settings_utils.h"
 #include "components/content_settings/core/browser/website_settings_info.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
@@ -26,6 +27,11 @@
 // const.
 class ContentSettingsRegistry {
  public:
+  using Map =
+      base::ScopedPtrMap<ContentSettingsType, scoped_ptr<ContentSettingsInfo>>;
+  using const_iterator = MapValueIterator<typename Map::const_iterator,
+                                          const ContentSettingsInfo*>;
+
   static ContentSettingsRegistry* GetInstance();
 
   // Reset the instance for use inside tests.
@@ -33,6 +39,9 @@
 
   const ContentSettingsInfo* Get(ContentSettingsType type) const;
 
+  const_iterator begin() const;
+  const_iterator end() const;
+
  private:
   friend class ContentSettingsRegistryTest;
   friend struct base::DefaultLazyInstanceTraits<ContentSettingsRegistry>;
@@ -51,8 +60,7 @@
                 WebsiteSettingsInfo::SyncStatus sync_status,
                 const std::vector<std::string>& whitelisted_schemes);
 
-  base::ScopedPtrMap<ContentSettingsType, scoped_ptr<ContentSettingsInfo>>
-      content_settings_info_;
+  Map content_settings_info_;
   WebsiteSettingsRegistry* website_settings_registry_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentSettingsRegistry);
diff --git a/components/content_settings/core/browser/content_settings_registry_unittest.cc b/components/content_settings/core/browser/content_settings_registry_unittest.cc
index aea9a81..ad664ef 100644
--- a/components/content_settings/core/browser/content_settings_registry_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -64,4 +64,24 @@
             website_settings_info);
 }
 
+TEST_F(ContentSettingsRegistryTest, Iteration) {
+  // Check that plugins and cookies settings appear once during iteration.
+  bool plugins_found = false;
+  bool cookies_found = false;
+  for (const ContentSettingsInfo* info : *registry()) {
+    ContentSettingsType type = info->website_settings_info()->type();
+    EXPECT_EQ(registry()->Get(type), info);
+    if (type == CONTENT_SETTINGS_TYPE_PLUGINS) {
+      EXPECT_FALSE(plugins_found);
+      plugins_found = true;
+    } else if (type == CONTENT_SETTINGS_TYPE_COOKIES) {
+      EXPECT_FALSE(cookies_found);
+      cookies_found = true;
+    }
+  }
+
+  EXPECT_TRUE(plugins_found);
+  EXPECT_TRUE(cookies_found);
+}
+
 }  // namespace content_settings
diff --git a/components/content_settings/core/browser/content_settings_utils.h b/components/content_settings/core/browser/content_settings_utils.h
index 37d590e..2efa0ed 100644
--- a/components/content_settings/core/browser/content_settings_utils.h
+++ b/components/content_settings/core/browser/content_settings_utils.h
@@ -28,6 +28,27 @@
 
 typedef std::pair<ContentSettingsPattern, ContentSettingsPattern> PatternPair;
 
+// Helper class to iterate over only the values in a map.
+template <typename IteratorType, typename ReferenceType>
+class MapValueIterator {
+ public:
+  explicit MapValueIterator(IteratorType iterator) : iterator_(iterator) {}
+
+  bool operator!=(const MapValueIterator& other) const {
+    return iterator_ != other.iterator_;
+  }
+
+  MapValueIterator& operator++() {
+    ++iterator_;
+    return *this;
+  }
+
+  ReferenceType operator*() { return iterator_->second; }
+
+ private:
+  IteratorType iterator_;
+};
+
 // These constants are copied from extensions/common/extension_constants.h and
 // content/public/common/url_constants.h to avoid complicated dependencies.
 // TODO(vabr): Get these constants through the ContentSettingsClient.
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
index 54ed2d1..26388b7 100644
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -173,7 +173,8 @@
     const GURL& secondary_url,
     ContentSettingsType content_type,
     const std::string& resource_identifier) const {
-  DCHECK(!ContentTypeHasCompoundValue(content_type));
+  DCHECK(content_settings::ContentSettingsRegistry::GetInstance()->Get(
+      content_type));
   scoped_ptr<base::Value> value = GetWebsiteSetting(
       primary_url, secondary_url, content_type, resource_identifier, NULL);
   return content_settings::ValueToContentSetting(value.get());
@@ -233,7 +234,7 @@
     ContentSettingsType content_type,
     const std::string& resource_identifier,
     base::Value* value) {
-  DCHECK(IsValueAllowedForType(prefs_, value, content_type));
+  DCHECK(!value || IsValueAllowedForType(value, content_type));
   DCHECK(SupportsResourceIdentifier(content_type) ||
          resource_identifier.empty());
   UsedContentSettingsProviders();
@@ -286,7 +287,8 @@
     ContentSettingsType content_type,
     const std::string& resource_identifier,
     ContentSetting setting) {
-  DCHECK(!ContentTypeHasCompoundValue(content_type));
+  DCHECK(content_settings::ContentSettingsRegistry::GetInstance()->Get(
+      content_type));
 
   if (setting == CONTENT_SETTING_ALLOW &&
       (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
@@ -394,7 +396,8 @@
   // TODO(markusheintz): Until the UI supports pattern pairs, both urls must
   // match.
   DCHECK(primary_url == secondary_url);
-  DCHECK(!ContentTypeHasCompoundValue(content_type));
+  DCHECK(content_settings::ContentSettingsRegistry::GetInstance()->Get(
+      content_type));
 
   // Make sure there is no entry that would override the pattern we are about
   // to insert for exactly this URL.
@@ -422,12 +425,6 @@
   FlushLossyWebsiteSettings();
 }
 
-bool HostContentSettingsMap::IsValueAllowedForType(
-    PrefService* prefs, const base::Value* value, ContentSettingsType type) {
-  return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType(
-      prefs, content_settings::ValueToContentSetting(value), type);
-}
-
 // static
 bool HostContentSettingsMap::IsDefaultSettingAllowedForType(
     PrefService* prefs,
@@ -452,6 +449,22 @@
 }
 
 // static
+bool HostContentSettingsMap::IsValueAllowedForType(const base::Value* value,
+                                                   ContentSettingsType type) {
+  if (content_settings::ContentSettingsRegistry::GetInstance()->Get(type)) {
+    ContentSetting setting = content_settings::ValueToContentSetting(value);
+    if (setting == CONTENT_SETTING_DEFAULT)
+      return false;
+    return HostContentSettingsMap::IsSettingAllowedForType(nullptr, setting,
+                                                           type);
+  }
+
+  // TODO(raymes): We should permit different types of base::Value for
+  // website settings.
+  return value->GetType() == base::Value::TYPE_DICTIONARY;
+}
+
+// static
 bool HostContentSettingsMap::IsSettingAllowedForType(
     PrefService* prefs,
     ContentSetting setting,
@@ -472,9 +485,11 @@
     return false;
   }
 
-  // Compound types cannot be mapped to the type |ContentSetting|.
-  if (ContentTypeHasCompoundValue(content_type))
+  // Non content settings cannot be mapped to the type |ContentSetting|.
+  if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(
+          content_type)) {
     return false;
+  }
 
   // DEFAULT, ALLOW and BLOCK are always allowed.
   if (setting == CONTENT_SETTING_DEFAULT ||
@@ -508,20 +523,6 @@
   }
 }
 
-// static
-bool HostContentSettingsMap::ContentTypeHasCompoundValue(
-    ContentSettingsType type) {
-  // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
-  // CONTENT_SETTINGS_TYPE_APP_BANNER, CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT and
-  // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS are of type dictionary/map.
-  // Compound types like dictionaries can't be mapped to the type
-  // |ContentSetting|.
-  return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
-          type == CONTENT_SETTINGS_TYPE_APP_BANNER ||
-          type == CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT ||
-          type == CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS);
-}
-
 void HostContentSettingsMap::OnContentSettingChanged(
     const ContentSettingsPattern& primary_pattern,
     const ContentSettingsPattern& secondary_pattern,
@@ -566,10 +567,11 @@
     const content_settings::Rule& rule = rule_iterator->Next();
     ContentSetting setting_value = CONTENT_SETTING_DEFAULT;
     // TODO(bauerb): Return rules as a list of values, not content settings.
-    // Handle the case using compound values for its exceptions and arbitrary
-    // values for its default setting. Here we assume all the exceptions
-    // are granted as |CONTENT_SETTING_ALLOW|.
-    if (ContentTypeHasCompoundValue(content_type) &&
+    // Handle the case using base::Values for its exceptions and default
+    // setting. Here we assume all the exceptions are granted as
+    // |CONTENT_SETTING_ALLOW|.
+    if (!content_settings::ContentSettingsRegistry::GetInstance()->Get(
+            content_type) &&
         rule.value.get() &&
         rule.primary_pattern != ContentSettingsPattern::Wildcard()) {
       setting_value = CONTENT_SETTING_ALLOW;
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h
index 04a204d..5b32e8c 100644
--- a/components/content_settings/core/browser/host_content_settings_map.h
+++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -176,9 +176,9 @@
   // This should only be called on the UI thread.
   void ClearSettingsForOneType(ContentSettingsType content_type);
 
-  static bool IsValueAllowedForType(PrefService* prefs,
-                                    const base::Value* value,
+  static bool IsValueAllowedForType(const base::Value* value,
                                     ContentSettingsType content_type);
+  // TODO(raymes): Remove |prefs| from the below functions, it's unused.
   static bool IsSettingAllowedForType(PrefService* prefs,
                                       ContentSetting setting,
                                       ContentSettingsType content_type);
@@ -186,9 +186,6 @@
                                              ContentSetting setting,
                                              ContentSettingsType content_type);
 
-  // Returns true if the values for content type are of type dictionary/map.
-  static bool ContentTypeHasCompoundValue(ContentSettingsType type);
-
   // RefcountedKeyedService implementation.
   void ShutdownOnUIThread() override;
 
diff --git a/components/content_settings/core/browser/website_settings_registry.h b/components/content_settings/core/browser/website_settings_registry.h
index 2430eb4..7d9ed4c 100644
--- a/components/content_settings/core/browser/website_settings_registry.h
+++ b/components/content_settings/core/browser/website_settings_registry.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
+#include "components/content_settings/core/browser/content_settings_utils.h"
 #include "components/content_settings/core/browser/website_settings_info.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
@@ -23,28 +24,6 @@
 // methods called from from any thread because all of its public methods are
 // const.
 class WebsiteSettingsRegistry {
- private:
-  // Helper class to iterate over only the values in a map.
-  template <typename IteratorType, typename ReferenceType>
-  class MapValueIterator {
-   public:
-    explicit MapValueIterator(IteratorType iterator) : iterator_(iterator) {}
-
-    bool operator!=(const MapValueIterator& other) const {
-      return iterator_ != other.iterator_;
-    }
-
-    MapValueIterator& operator++() {
-      ++iterator_;
-      return *this;
-    }
-
-    ReferenceType operator*() { return iterator_->second; }
-
-   private:
-    IteratorType iterator_;
-  };
-
  public:
   typedef base::ScopedPtrMap<ContentSettingsType,
                              scoped_ptr<WebsiteSettingsInfo>> Map;
diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc
index 39d7618a..d92953e 100644
--- a/components/crash/content/app/breakpad_linux.cc
+++ b/components/crash/content/app/breakpad_linux.cc
@@ -27,12 +27,14 @@
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
+#include "base/lazy_instance.h"
 #include "base/linux_util.h"
 #include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/global_descriptors.h"
 #include "base/process/memory.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_checker.h"
 #include "breakpad/src/client/linux/crash_generation/crash_generation_client.h"
 #include "breakpad/src/client/linux/handler/exception_handler.h"
 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h"
@@ -95,8 +97,43 @@
 #if defined(OS_ANDROID)
 char* g_process_type = nullptr;
 ExceptionHandler* g_microdump = nullptr;
-const char* g_microdump_build_fingerprint = nullptr;
-const char* g_microdump_product_info = nullptr;
+
+class MicrodumpInfo {
+ public:
+  MicrodumpInfo()
+      : microdump_build_fingerprint_(nullptr),
+        microdump_product_info_(nullptr),
+        microdump_gpu_fingerprint_(nullptr) {}
+
+  // The order in which SetGpuFingerprint and Initialize are called
+  // may be dependent on the timing of the availability of GPU
+  // information. For this reason, they can be called in either order,
+  // resulting in the same effect.
+  //
+  // The following restrictions apply, however:
+  // * Both methods must be called from the same thread.
+  // * Both methods must be called at most once.
+  //
+  // Microdumps will only be generated if Initialize is called. If
+  // SetGpuFingerprint has not been called called at the point at
+  // which a microdump is generated, then the GPU fingerprint will be
+  // UNKNOWN.
+  void SetGpuFingerprint(const std::string& gpu_fingerprint);
+  void Initialize(const std::string& process_type,
+                  const char* product_name,
+                  const char* product_version,
+                  const char* android_build_fp);
+
+ private:
+  base::ThreadChecker thread_checker_;
+  const char* microdump_build_fingerprint_;
+  const char* microdump_product_info_;
+  const char* microdump_gpu_fingerprint_;
+};
+
+base::LazyInstance<MicrodumpInfo> g_microdump_info =
+    LAZY_INSTANCE_INITIALIZER;
+
 #endif
 
 CrashKeyStorage* g_crash_keys = nullptr;
@@ -708,34 +745,11 @@
   GetCrashReporterClient()->GetProductNameAndVersion(&product_name,
                                                      &product_version);
 
-  MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole);
-
-  if (product_name && product_version) {
-    g_microdump_product_info = strdup(
-        (product_name + std::string(":") + product_version).c_str());
-    ANNOTATE_LEAKING_OBJECT_PTR(g_microdump_product_info);
-    descriptor.microdump_extra_info()->product_info = g_microdump_product_info;
-  }
-
   const char* android_build_fp =
       base::android::BuildInfo::GetInstance()->android_build_fp();
-  if (android_build_fp) {
-    g_microdump_build_fingerprint = strdup(android_build_fp);
-    ANNOTATE_LEAKING_OBJECT_PTR(g_microdump_build_fingerprint);
-    descriptor.microdump_extra_info()->build_fingerprint =
-        g_microdump_build_fingerprint;
-  }
 
-  DCHECK(!g_microdump);
-  bool is_browser_process = process_type.empty() || process_type == "webview";
-  g_microdump = new ExceptionHandler(
-        descriptor,
-        nullptr,
-        MicrodumpCrashDone,
-        reinterpret_cast<void*>(is_browser_process),
-        true,  // Install handlers.
-        -1);   // Server file descriptor. -1 for in-process.
-    return;
+  g_microdump_info.Get().Initialize(process_type, product_name, product_version,
+                                    android_build_fp);
 }
 
 bool CrashDoneInProcessNoUpload(
@@ -797,6 +811,57 @@
   new google_breakpad::ExceptionHandler(MinidumpDescriptor(minidump_fd),
       nullptr, CrashDoneInProcessNoUpload, nullptr, true, -1);
 }
+
+void MicrodumpInfo::SetGpuFingerprint(const std::string& gpu_fingerprint) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!microdump_gpu_fingerprint_);
+  microdump_gpu_fingerprint_ = strdup(gpu_fingerprint.c_str());
+  ANNOTATE_LEAKING_OBJECT_PTR(microdump_gpu_fingerprint_);
+
+  if (g_microdump) {
+    MinidumpDescriptor minidump_descriptor(g_microdump->minidump_descriptor());
+    minidump_descriptor.microdump_extra_info()->gpu_fingerprint =
+        microdump_gpu_fingerprint_;
+    g_microdump->set_minidump_descriptor(minidump_descriptor);
+  }
+}
+
+void MicrodumpInfo::Initialize(const std::string& process_type,
+                               const char* product_name,
+                               const char* product_version,
+                               const char* android_build_fp) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!g_microdump);
+  bool is_browser_process = process_type.empty() || process_type == "webview";
+
+  MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole);
+
+  if (product_name && product_version) {
+    microdump_product_info_ =
+        strdup((product_name + std::string(":") + product_version).c_str());
+    ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_);
+    descriptor.microdump_extra_info()->product_info = microdump_product_info_;
+  }
+
+  if (android_build_fp) {
+    microdump_build_fingerprint_ = strdup(android_build_fp);
+    ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_);
+    descriptor.microdump_extra_info()->build_fingerprint =
+        microdump_build_fingerprint_;
+  }
+
+  if (microdump_gpu_fingerprint_) {
+    descriptor.microdump_extra_info()->gpu_fingerprint =
+        microdump_gpu_fingerprint_;
+  }
+
+  g_microdump =
+      new ExceptionHandler(descriptor, nullptr, MicrodumpCrashDone,
+                           reinterpret_cast<void*>(is_browser_process),
+                           true,  // Install handlers.
+                           -1);   // Server file descriptor. -1 for in-process.
+}
+
 #else
 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
 class NonBrowserCrashHandler : public google_breakpad::CrashGenerationClient {
@@ -1752,6 +1817,11 @@
     }
   }
 }
+
+void AddGpuFingerprintToMicrodumpCrashHandler(
+    const std::string& gpu_fingerprint) {
+  g_microdump_info.Get().SetGpuFingerprint(gpu_fingerprint);
+}
 #endif  // OS_ANDROID
 
 bool IsCrashReporterEnabled() {
diff --git a/components/crash/content/app/breakpad_linux.h b/components/crash/content/app/breakpad_linux.h
index 4bfe0ce..1d849eb3 100644
--- a/components/crash/content/app/breakpad_linux.h
+++ b/components/crash/content/app/breakpad_linux.h
@@ -20,6 +20,9 @@
 #if defined(OS_ANDROID)
 extern void InitNonBrowserCrashReporterForAndroid(
     const std::string& process_type);
+
+extern void AddGpuFingerprintToMicrodumpCrashHandler(
+    const std::string& gpu_fingerprint);
 #endif
 
 // Checks if crash reporting is enabled. Note that this is not the same as
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc
index 520f62df..d0021a83 100644
--- a/components/cronet/android/cronet_library_loader.cc
+++ b/components/cronet/android/cronet_library_loader.cc
@@ -26,10 +26,11 @@
 #include "net/android/net_jni_registrar.h"
 #include "net/android/network_change_notifier_factory_android.h"
 #include "net/base/network_change_notifier.h"
-#include "url/android/url_jni_registrar.h"
 #include "url/url_util.h"
 
-#if !defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
+#if defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
+#include "url/android/url_jni_registrar.h"
+#else
 #include "base/i18n/icu_util.h"
 #endif
 
@@ -42,13 +43,14 @@
     {"ChromiumUrlRequestContext", ChromiumUrlRequestContextRegisterJni},
     {"CronetHistogramManager", CronetHistogramManagerRegisterJni},
     {"CronetLibraryLoader", RegisterNativesImpl},
-    {"CronetUploadDataStreamAdapter",
-     CronetUploadDataStreamAdapterRegisterJni},
+    {"CronetUploadDataStreamAdapter", CronetUploadDataStreamAdapterRegisterJni},
     {"CronetUrlRequestAdapter", CronetUrlRequestAdapterRegisterJni},
     {"CronetUrlRequestContextAdapter",
      CronetUrlRequestContextAdapterRegisterJni},
     {"NetAndroid", net::android::RegisterJni},
+#if defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
     {"UrlAndroid", url::android::RegisterJni},
+#endif
 };
 
 // MessageLoop on the main thread, which is where objects that receive Java
diff --git a/components/cronet/android/test/javaperftests/run.py b/components/cronet/android/test/javaperftests/run.py
index 19f85cd..cf88beb 100755
--- a/components/cronet/android/test/javaperftests/run.py
+++ b/components/cronet/android/test/javaperftests/run.py
@@ -169,7 +169,7 @@
     super(CronetPerfTestMeasurement, self).__init__(options)
     self._device = device
 
-  def WillRunStoryForPageTest(self, tracing_controller):
+  def WillRunStory(self, platform):
     # Skip parent implementation which doesn't apply to Cronet perf test app as
     # it is not a browser with a timeline interface.
     pass
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn
index 54ae8d2..c005f88 100644
--- a/components/data_reduction_proxy/core/browser/BUILD.gn
+++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -117,6 +117,7 @@
     "data_reduction_proxy_interceptor_unittest.cc",
     "data_reduction_proxy_io_data_unittest.cc",
     "data_reduction_proxy_metrics_unittest.cc",
+    "data_reduction_proxy_mutable_config_values_unittest.cc",
     "data_reduction_proxy_network_delegate_unittest.cc",
     "data_reduction_proxy_prefs_unittest.cc",
     "data_reduction_proxy_request_options_unittest.cc",
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 0d9c9447..dde2176 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -633,12 +633,10 @@
 void DataReductionProxyCompressionStats::GetHistoricalDataUsage(
     const HistoricalDataUsageCallback& get_data_usage_callback) {
   if (current_data_usage_load_status_ != LOADED) {
-    // This method succeeds only if current data usage has already been loaded.
-    // This use case should never occur in practice since data usage reporting
-    // will always be enabled when the Data Saver extension is installed. Also,
-    // current data usage should have sufficient time to load before user tries
-    // to view data usage.
-    NOTREACHED();
+    // If current data usage has not yet loaded, we return an empty array. The
+    // extension can retry after a slight delay.
+    // This use case is unlikely to occur in practice since current data usage
+    // should have sufficient time to load before user tries to view data usage.
     get_data_usage_callback.Run(
         make_scoped_ptr(new std::vector<DataUsageBucket>()));
     return;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 146af5c..df78cf8e 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -12,7 +12,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h"
@@ -41,7 +40,8 @@
 // name in metrics/histograms/histograms.xml.
 enum DataReductionProxyNetworkChangeEvent {
   IP_CHANGED = 0,         // The client IP address changed.
-  DISABLED_ON_VPN = 1,    // The proxy is disabled because a VPN is running.
+  DISABLED_ON_VPN = 1,    // [Deprecated] Proxy is disabled because a VPN is
+                          // running.
   CHANGE_EVENT_COUNT = 2  // This must always be last.
 };
 
@@ -230,7 +230,6 @@
     DataReductionProxyConfigurator* configurator,
     DataReductionProxyEventCreator* event_creator)
     : secure_proxy_allowed_(params::ShouldUseSecureProxyByDefault()),
-      disabled_on_vpn_(false),
       unreachable_(false),
       enabled_by_user_(false),
       config_values_(config_values.Pass()),
@@ -627,7 +626,7 @@
       config_values_->proxies_for_http();
   std::vector<net::ProxyServer> proxies_for_https =
       config_values_->proxies_for_https();
-  if (enabled && !disabled_on_vpn_ && !config_values_->holdback() &&
+  if (enabled && !config_values_->holdback() &&
       (!proxies_for_http.empty() || !proxies_for_https.empty())) {
     configurator_->Enable(!secure_proxy_allowed, proxies_for_http,
                           proxies_for_https);
@@ -695,8 +694,6 @@
   if (enabled_by_user_) {
     DCHECK(config_values_->allowed());
     RecordNetworkChangeEvent(IP_CHANGED);
-    if (MaybeDisableIfVPN())
-      return;
 
     bool should_use_secure_proxy = params::ShouldUseSecureProxyByDefault();
     if (!should_use_secure_proxy && secure_proxy_allowed_) {
@@ -961,30 +958,4 @@
   net::GetNetworkList(interfaces, policy);
 }
 
-bool DataReductionProxyConfig::MaybeDisableIfVPN() {
-  if (params::IsIncludedInUseDataSaverOnVPNFieldTrial()) {
-    return false;
-  }
-  net::NetworkInterfaceList network_interfaces;
-  GetNetworkList(&network_interfaces, 0);
-  // VPNs use a "tun" interface, so the presence of a "tun" interface indicates
-  // a VPN is in use. This logic only works on Android and Linux platforms.
-  // Data Saver will not be disabled on any other platform on VPN.
-  const std::string vpn_interface_name_prefix = "tun";
-  for (size_t i = 0; i < network_interfaces.size(); ++i) {
-    if (base::StartsWith(network_interfaces[i].name, vpn_interface_name_prefix,
-                         base::CompareCase::INSENSITIVE_ASCII)) {
-      disabled_on_vpn_ = true;
-      ReloadConfig();
-      RecordNetworkChangeEvent(DISABLED_ON_VPN);
-      return true;
-    }
-  }
-  if (disabled_on_vpn_) {
-    disabled_on_vpn_ = false;
-    ReloadConfig();
-  }
-  return false;
-}
-
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 9fb003cd..46a301c 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -259,10 +259,6 @@
                            AreProxiesBypassed);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
                            AreProxiesBypassedRetryDelay);
-  FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
-                           TestMaybeDisableIfVPNTrialDisabled);
-  FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
-                           TestMaybeDisableIfVPNTrialEnabled);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest, AutoLoFiParams);
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigTest,
                            AutoLoFiParamsSlowConnectionsFlag);
@@ -301,11 +297,6 @@
   // Adds the default proxy bypass rules for the Data Reduction Proxy.
   void AddDefaultProxyBypassRules();
 
-  // Disables use of the Data Reduction Proxy on VPNs if client is not in the
-  // DataReductionProxyUseDataSaverOnVPN field trial and a TUN network interface
-  // is being used. Returns true if the Data Reduction Proxy has been disabled.
-  bool MaybeDisableIfVPN();
-
   // Checks if all configured data reduction proxies are in the retry map.
   // Returns true if the request is bypassed by all configured data reduction
   // proxies that apply to the request scheme. If all possible data reduction
@@ -348,7 +339,6 @@
   // Indicates if the secure Data Reduction Proxy can be used or not.
   bool secure_proxy_allowed_;
 
-  bool disabled_on_vpn_;
   bool unreachable_;
   bool enabled_by_user_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index b64e10d..603b4d8 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -429,11 +429,30 @@
 
   std::vector<net::ProxyServer> proxies =
       GetProxiesForHTTP(config.proxy_config());
+
+  if (params_ && params::IsDevRolloutEnabled() && !use_local_config_) {
+    // If dev rollout is enabled, proxies returned by client config API are
+    // discarded.
+    proxies.clear();
+    proxies.push_back(net::ProxyServer::FromURI(params_->GetDefaultDevOrigin(),
+                                                net::ProxyServer::SCHEME_HTTP));
+    proxies.push_back(net::ProxyServer::FromURI(
+        params_->GetDefaultDevFallbackOrigin(), net::ProxyServer::SCHEME_HTTP));
+  }
+
   if (proxies.empty())
     return false;
 
   if (!use_local_config_) {
     request_options_->SetSecureSession(config.session_key());
+    // If QUIC is enabled, the scheme of the first proxy (if it is HTTPS) would
+    // be changed to QUIC.
+    if (proxies[0].scheme() == net::ProxyServer::SCHEME_HTTPS && params_ &&
+        params_->quic_enabled()) {
+      proxies[0] = net::ProxyServer(net::ProxyServer::SCHEME_QUIC,
+                                    proxies[0].host_port_pair());
+      DCHECK_EQ(net::ProxyServer::SCHEME_QUIC, proxies[0].scheme());
+    }
     config_values_->UpdateValues(proxies);
     config_->ReloadConfig();
     remote_config_applied_ = true;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
index a73aefa..1a792fd 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -161,7 +161,8 @@
                       int response_code);
 
   // Parses out the proxy configuration portion of |config| and applies it to
-  // |config_| and |request_options_|.
+  // |config_| and |request_options_|. Takes into account the field trials that
+  // this session belongs to.
   bool ParseAndApplyProxyConfig(const ClientConfig& config);
 
   // Contains the static configuration data to use.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index 32274ea..0f4d6131 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -9,10 +9,12 @@
 #include <vector>
 
 #include "base/base64.h"
+#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/mock_entropy_provider.h"
 #include "base/time/tick_clock.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_test_utils.h"
@@ -21,6 +23,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
 #include "components/variations/variations_associated_data.h"
 #include "net/http/http_response_headers.h"
@@ -267,6 +270,8 @@
     return previous_config_;
   }
 
+  void EnableQuic(bool enable) { params()->EnableQuic(enable); }
+
   const std::string& loaded_config() const { return loaded_config_; }
 
  private:
@@ -327,6 +332,85 @@
   EXPECT_TRUE(configurator()->proxies_for_https().empty());
 }
 
+// Tests the interaction of client config with dev rollout and QUIC field trial.
+TEST_F(DataReductionProxyConfigServiceClientTest, DevRolloutAndQuic) {
+  const struct {
+    bool enable_dev;
+    bool enable_quic;
+    std::string expected_primary_proxy;
+    std::string expected_fallback_proxy;
+    net::ProxyServer::Scheme expected_primary_proxy_scheme;
+  } tests[] = {
+      {false, false, kSuccessOrigin, kSuccessFallback,
+       net::ProxyServer::SCHEME_HTTPS},
+      {false, true, kSuccessOrigin, kSuccessFallback,
+       net::ProxyServer::SCHEME_QUIC},
+      {true, false, TestDataReductionProxyParams::DefaultDevOrigin(),
+       TestDataReductionProxyParams::DefaultDevFallbackOrigin(),
+       net::ProxyServer::SCHEME_HTTPS},
+      {true, true, TestDataReductionProxyParams::DefaultDevOrigin(),
+       TestDataReductionProxyParams::DefaultDevFallbackOrigin(),
+       net::ProxyServer::SCHEME_QUIC},
+  };
+
+  for (size_t i = 0; i < arraysize(tests); ++i) {
+    if (tests[i].enable_dev) {
+      base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+      command_line->AppendSwitch(
+          data_reduction_proxy::switches::kEnableDataReductionProxyDev);
+    }
+
+    base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
+    if (tests[i].enable_quic) {
+      base::FieldTrialList::CreateFieldTrial(params::GetQuicFieldTrialName(),
+                                             "Enabled");
+    } else {
+      base::FieldTrialList::CreateFieldTrial(params::GetQuicFieldTrialName(),
+                                             "Control");
+    }
+    EnableQuic(tests[i].enable_quic);
+
+    // Use a remote config.
+    net::MockRead mock_reads[] = {
+        net::MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+        net::MockRead(net::ASYNC, success_response().c_str(),
+                      success_response().length()),
+        net::MockRead(net::SYNCHRONOUS, net::OK),
+    };
+    net::StaticSocketDataProvider socket_data_provider(
+        mock_reads, arraysize(mock_reads), nullptr, 0);
+    mock_socket_factory()->AddSocketDataProvider(&socket_data_provider);
+    config_client()->SetConfigServiceURL(GURL("http://configservice.com"));
+
+    RequestOptionsPopulator populator(
+        base::Time::UnixEpoch() + base::TimeDelta::FromDays(1),
+        base::TimeDelta::FromDays(1));
+    SetDataReductionProxyEnabled(true);
+
+    config_client()->RetrieveConfig();
+    RunUntilIdle();
+    EXPECT_EQ(base::TimeDelta::FromMinutes(10), config_client()->GetDelay())
+        << i;
+
+    std::vector<net::ProxyServer> proxies_for_http =
+        configurator()->proxies_for_http();
+
+    EXPECT_EQ(2U, proxies_for_http.size()) << i;
+    EXPECT_EQ(net::ProxyServer(tests[i].expected_primary_proxy_scheme,
+                               net::ProxyServer::FromURI(
+                                   tests[i].expected_primary_proxy,
+                                   tests[i].expected_primary_proxy_scheme)
+                                   .host_port_pair()),
+              proxies_for_http[0])
+        << i;
+    EXPECT_EQ(net::ProxyServer::FromURI(tests[i].expected_fallback_proxy,
+                                        net::ProxyServer::SCHEME_HTTP),
+              proxies_for_http[1])
+        << i;
+    EXPECT_TRUE(configurator()->proxies_for_https().empty()) << i;
+  }
+}
+
 TEST_F(DataReductionProxyConfigServiceClientTest, SuccessfulLoopShortDuration) {
   // Use a local/static config.
   config_client()->SetConfigServiceURL(GURL());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index d786b45..b1a97bd1 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -156,26 +156,6 @@
   scoped_ptr<TestDataReductionProxyParams> expected_params_;
 };
 
-TEST_F(DataReductionProxyConfigTest, TestMaybeDisableIfVPNTrialDisabled) {
-  // Simulate a VPN connection.
-  config()->interfaces()->clear();
-  config()->interfaces()->push_back(net::NetworkInterface(
-      "tun0", /* network interface name */
-      "tun0", /* network interface friendly name */
-      0,      /* interface index */
-      net::NetworkChangeNotifier::CONNECTION_WIFI, net::IPAddressNumber(),
-      0,                             /* network prefix */
-      net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
-      ));
-  EXPECT_TRUE(config()->MaybeDisableIfVPN());
-}
-
-TEST_F(DataReductionProxyConfigTest, TestMaybeDisableIfVPNTrialEnabled) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      "force-fieldtrials", "DataReductionProxyUseDataSaverOnVPN/Enabled");
-  EXPECT_FALSE(config()->MaybeDisableIfVPN());
-}
-
 TEST_F(DataReductionProxyConfigTest, TestUpdateConfigurator) {
   ResetSettings(true, true, true, false);
 
@@ -226,33 +206,6 @@
   // IP address change triggers a secure proxy check that succeeds. Proxy is
   // unrestricted.
   CheckSecureProxyCheckOnIPChange("OK", SUCCEEDED_PROXY_ENABLED, false, false);
-  // Simulate a VPN connection. The proxy should be disabled.
-  config()->interfaces()->clear();
-  config()->interfaces()->push_back(net::NetworkInterface(
-      "tun0", /* network interface name */
-      "tun0", /* network interface friendly name */
-      0,      /* interface index */
-      net::NetworkChangeNotifier::CONNECTION_WIFI,
-      net::IPAddressNumber(),        /* IP address */
-      0,                             /* network prefix */
-      net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
-      ));
-  config()->OnIPAddressChanged();
-  RunUntilIdle();
-  CheckProxyConfigs(false, false);
-
-  // Check that the proxy is re-enabled if a non-VPN connection is later used.
-  config()->interfaces()->clear();
-  config()->interfaces()->push_back(net::NetworkInterface(
-      "eth0", /* network interface name */
-      "eth0", /* network interface friendly name */
-      0,      /* interface index */
-      net::NetworkChangeNotifier::CONNECTION_WIFI, net::IPAddressNumber(),
-      0,                             /* network prefix */
-      net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
-      ));
-  CheckSecureProxyCheckOnIPChange("OK", SUCCEEDED_PROXY_ALREADY_ENABLED, false,
-                                  false);
 }
 
 TEST_F(DataReductionProxyConfigTest,
@@ -281,33 +234,6 @@
   // IP address change triggers a secure proxy check that succeeds. Proxy is
   // unrestricted.
   CheckSecureProxyCheckOnIPChange("OK", SUCCEEDED_PROXY_ENABLED, false, false);
-  // Simulate a VPN connection. The proxy should be disabled.
-  config()->interfaces()->clear();
-  config()->interfaces()->push_back(net::NetworkInterface(
-      "tun0", /* network interface name */
-      "tun0", /* network interface friendly name */
-      0,      /* interface index */
-      net::NetworkChangeNotifier::CONNECTION_WIFI,
-      net::IPAddressNumber(),        /* IP address */
-      0,                             /* network prefix */
-      net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
-      ));
-  config()->OnIPAddressChanged();
-  RunUntilIdle();
-  CheckProxyConfigs(false, false);
-
-  // Check that the proxy is re-enabled if a non-VPN connection is later used.
-  config()->interfaces()->clear();
-  config()->interfaces()->push_back(net::NetworkInterface(
-      "eth0", /* network interface name */
-      "eth0", /* network interface friendly name */
-      0,      /* interface index */
-      net::NetworkChangeNotifier::CONNECTION_WIFI, net::IPAddressNumber(),
-      0,                             /* network prefix */
-      net::IP_ADDRESS_ATTRIBUTE_NONE /* ip address attribute */
-      ));
-  ExpectSecureProxyCheckResult(PROXY_DISABLED_BEFORE_CHECK);
-  CheckSecureProxyCheckOnIPChange("OK", SUCCEEDED_PROXY_ENABLED, false, false);
 }
 
 std::string GetRetryMapKeyFromOrigin(const std::string& origin) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc
index 5ba7a4f..3699d4e7 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.cc
@@ -4,6 +4,8 @@
 
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
 
+#include <vector>
+
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 
 namespace data_reduction_proxy {
@@ -25,7 +27,12 @@
     : promo_allowed_(false),
       holdback_(false),
       allowed_(false),
-      fallback_allowed_(false) {
+      fallback_allowed_(false),
+      use_override_proxies_for_http_(false) {
+  use_override_proxies_for_http_ =
+      params::GetOverrideProxiesForHttpFromCommandLine(
+          &override_proxies_for_http_);
+
   // Constructed on the UI thread, but should be checked on the IO thread.
   thread_checker_.DetachFromThread();
 }
@@ -58,6 +65,16 @@
 const std::vector<net::ProxyServer>&
 DataReductionProxyMutableConfigValues::proxies_for_http() const {
   DCHECK(thread_checker_.CalledOnValidThread());
+  if (use_override_proxies_for_http_ && !proxies_for_http_.empty()) {
+    // Only override the proxies if a non-empty list of proxies would have been
+    // returned otherwise. This is to prevent use of the proxies when the config
+    // has been invalidated, since attempting to use a Data Reduction Proxy
+    // without valid credentials could cause a proxy bypass.
+    return override_proxies_for_http_;
+  }
+  // TODO(sclittle): Support overriding individual proxies in the proxy list
+  // according to field trials such as the DRP QUIC field trial and their
+  // corresponding command line flags (crbug.com/533637).
   return proxies_for_http_;
 }
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
index 69fea3d..36d2cd3 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h
@@ -60,6 +60,11 @@
   std::vector<net::ProxyServer> proxies_for_https_;
   GURL secure_proxy_check_url_;
 
+  // Permits use of locally specified Data Reduction Proxy servers instead of
+  // ones specified from the Data Saver API.
+  bool use_override_proxies_for_http_;
+  std::vector<net::ProxyServer> override_proxies_for_http_;
+
   // Enforce usage on the IO thread.
   base::ThreadChecker thread_checker_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
new file mode 100644
index 0000000..e11fb72f
--- /dev/null
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
+#include "net/proxy/proxy_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace data_reduction_proxy {
+
+namespace {
+
+class DataReductionProxyMutableConfigValuesTest : public testing::Test {
+ public:
+  DataReductionProxyMutableConfigValuesTest() {}
+  ~DataReductionProxyMutableConfigValuesTest() override {}
+
+  void Init() {
+    params_.reset(new DataReductionProxyParams(
+        DataReductionProxyParams::kAllowAllProxyConfigurations));
+    mutable_config_values_ =
+        DataReductionProxyMutableConfigValues::CreateFromParams(params_.get());
+  }
+
+  DataReductionProxyMutableConfigValues* mutable_config_values() const {
+    return mutable_config_values_.get();
+  }
+
+ private:
+  scoped_ptr<DataReductionProxyParams> params_;
+  scoped_ptr<DataReductionProxyMutableConfigValues> mutable_config_values_;
+};
+
+TEST_F(DataReductionProxyMutableConfigValuesTest, UpdateValuesAndInvalidate) {
+  Init();
+  EXPECT_EQ(std::vector<net::ProxyServer>(),
+            mutable_config_values()->proxies_for_http());
+
+  std::vector<net::ProxyServer> proxies_for_http;
+  proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://first.net", net::ProxyServer::SCHEME_HTTP));
+  proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://second.net", net::ProxyServer::SCHEME_HTTP));
+
+  mutable_config_values()->UpdateValues(proxies_for_http);
+  EXPECT_EQ(proxies_for_http, mutable_config_values()->proxies_for_http());
+
+  mutable_config_values()->Invalidate();
+  EXPECT_EQ(std::vector<net::ProxyServer>(),
+            mutable_config_values()->proxies_for_http());
+}
+
+TEST_F(DataReductionProxyMutableConfigValuesTest, OverrideProxiesForHttp) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kDataReductionProxyHttpProxies,
+      "http://override-first.net;http://override-second.net");
+  Init();
+
+  EXPECT_EQ(std::vector<net::ProxyServer>(),
+            mutable_config_values()->proxies_for_http());
+
+  std::vector<net::ProxyServer> proxies_for_http;
+  proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://first.net", net::ProxyServer::SCHEME_HTTP));
+  proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://second.net", net::ProxyServer::SCHEME_HTTP));
+
+  mutable_config_values()->UpdateValues(proxies_for_http);
+
+  std::vector<net::ProxyServer> expected_override_proxies_for_http;
+  expected_override_proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://override-first.net", net::ProxyServer::SCHEME_HTTP));
+  expected_override_proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://override-second.net", net::ProxyServer::SCHEME_HTTP));
+
+  EXPECT_EQ(expected_override_proxies_for_http,
+            mutable_config_values()->proxies_for_http());
+
+  mutable_config_values()->Invalidate();
+  EXPECT_EQ(std::vector<net::ProxyServer>(),
+            mutable_config_values()->proxies_for_http());
+}
+
+}  // namespace
+
+}  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
index b66c65d4..e8f8f54b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -558,10 +558,8 @@
 
   // |request_context_storage| takes ownership of the network delegate.
   request_context_storage->set_network_delegate(
-      io_data()
-          ->CreateNetworkDelegate(
-              make_scoped_ptr(new net::TestNetworkDelegate()).Pass(), true)
-          .Pass());
+      io_data()->CreateNetworkDelegate(
+          make_scoped_ptr(new net::TestNetworkDelegate()), true));
 
   request_context_storage->set_job_factory(
       make_scoped_ptr(new net::URLRequestInterceptingJobFactory(
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index 38a486a3..9595caa 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -12,6 +12,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_client_config_parser.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
@@ -40,6 +41,7 @@
 const char kAndroidOneIdentifier[] = "sprout";
 
 const char kQuicFieldTrial[] = "DataReductionProxyUseQuic";
+const char kDevRolloutFieldTrial[] = "DataCompressionProxyDevRollout";
 
 const char kLoFiFieldTrial[] = "DataCompressionProxyLoFi";
 const char kLoFiFlagFieldTrial[] = "DataCompressionProxyLoFiFlag";
@@ -128,13 +130,18 @@
   return kQuicFieldTrial;
 }
 
-std::string GetClientConfigFieldTrialName() {
-  return kConfigServiceFieldTrial;
+bool IsDevRolloutEnabled() {
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
+    return false;
+
+  return command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
+         (FieldTrialList::FindFullName(kDevRolloutFieldTrial) == kEnabled);
 }
 
-bool IsIncludedInUseDataSaverOnVPNFieldTrial() {
-  return FieldTrialList::FindFullName("DataReductionProxyUseDataSaverOnVPN") ==
-         kEnabled;
+std::string GetClientConfigFieldTrialName() {
+  return kConfigServiceFieldTrial;
 }
 
 bool IsConfigClientEnabled() {
@@ -206,12 +213,36 @@
   return value;
 }
 
+bool GetOverrideProxiesForHttpFromCommandLine(
+    std::vector<net::ProxyServer>* override_proxies_for_http) {
+  DCHECK(override_proxies_for_http);
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDataReductionProxyHttpProxies)) {
+    return false;
+  }
+
+  override_proxies_for_http->clear();
+
+  std::string proxy_overrides =
+      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kDataReductionProxyHttpProxies);
+  std::vector<std::string> proxy_override_values = base::SplitString(
+      proxy_overrides, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+  for (const std::string& proxy_override : proxy_override_values) {
+    override_proxies_for_http->push_back(net::ProxyServer::FromURI(
+        proxy_override, net::ProxyServer::SCHEME_HTTP));
+  }
+
+  return true;
+}
+
 }  // namespace params
 
 void DataReductionProxyParams::EnableQuic(bool enable) {
   quic_enabled_ = enable;
   DCHECK(!quic_enabled_ || params::IsIncludedInQuicFieldTrial());
-  if (override_quic_origin_.empty() && quic_enabled_) {
+  if (!params::IsDevRolloutEnabled() && override_quic_origin_.empty() &&
+      quic_enabled_) {
     origin_ = net::ProxyServer::FromURI(kDefaultQuicOrigin,
                                         net::ProxyServer::SCHEME_HTTP);
     proxies_for_http_.clear();
@@ -230,15 +261,7 @@
 }
 
 DataReductionProxyParams::DataReductionProxyParams(int flags)
-    : allowed_((flags & kAllowed) == kAllowed),
-      fallback_allowed_((flags & kFallbackAllowed) == kFallbackAllowed),
-      promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
-      holdback_((flags & kHoldback) == kHoldback),
-      quic_enabled_(false),
-      configured_on_command_line_(false) {
-  bool result = Init(allowed_, fallback_allowed_);
-  DCHECK(result);
-}
+    : DataReductionProxyParams(flags, true) {}
 
 DataReductionProxyParams::~DataReductionProxyParams() {
 }
@@ -250,7 +273,8 @@
       promo_allowed_((flags & kPromoAllowed) == kPromoAllowed),
       holdback_((flags & kHoldback) == kHoldback),
       quic_enabled_(false),
-      configured_on_command_line_(false) {
+      configured_on_command_line_(false),
+      use_override_proxies_for_http_(false) {
   if (should_call_init) {
     bool result = Init(allowed_, fallback_allowed_);
     DCHECK(result);
@@ -291,10 +315,13 @@
     return false;
   }
   return true;
-
 }
 
 void DataReductionProxyParams::InitWithoutChecks() {
+  use_override_proxies_for_http_ =
+      params::GetOverrideProxiesForHttpFromCommandLine(
+          &override_proxies_for_http_);
+
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   std::string origin;
@@ -364,6 +391,8 @@
 
 const std::vector<net::ProxyServer>&
 DataReductionProxyParams::proxies_for_http() const {
+  if (use_override_proxies_for_http_)
+    return override_proxies_for_http_;
   return proxies_for_http_;
 }
 
@@ -422,29 +451,11 @@
 }
 
 std::string DataReductionProxyParams::GetDefaultDevOrigin() const {
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
-    return std::string();
-  if (command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
-      (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
-         kEnabled)) {
-    return kDevOrigin;
-  }
-  return std::string();
+  return params::IsDevRolloutEnabled() ? kDevOrigin : std::string();
 }
 
 std::string DataReductionProxyParams::GetDefaultDevFallbackOrigin() const {
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kDisableDataReductionProxyDev))
-    return std::string();
-  if (command_line.HasSwitch(switches::kEnableDataReductionProxyDev) ||
-      (FieldTrialList::FindFullName("DataCompressionProxyDevRollout") ==
-           kEnabled)) {
-    return kDevFallbackOrigin;
-  }
-  return std::string();
+  return params::IsDevRolloutEnabled() ? kDevFallbackOrigin : std::string();
 }
 
 // TODO(kundaji): Remove tests for macro definitions.
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index 8790a34..b3eefde9 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -67,6 +67,10 @@
 // proxy server as quic://proxy.googlezip.net.
 bool IsIncludedInQuicFieldTrial();
 
+// Returns true if dev rollout is enabled on this client either through command
+// line switch or as a part of field trial.
+bool IsDevRolloutEnabled();
+
 // Returns the name of the Lo-Fi field trial.
 std::string GetLoFiFieldTrialName();
 
@@ -79,10 +83,6 @@
 // Returns the name of the client config field trial.
 std::string GetClientConfigFieldTrialName();
 
-// Returns true if this client is part of a field trial that allows Data Saver
-// to be used on VPN.
-bool IsIncludedInUseDataSaverOnVPNFieldTrial();
-
 // Returns true if the Data Reduction Proxy config client should be used.
 bool IsConfigClientEnabled();
 
@@ -106,6 +106,12 @@
                                     int default_value,
                                     int min_value);
 
+// Returns true if the list of Data Reduction Proxies to use for HTTP requests
+// has been overridden on the command line, and if so, returns the override
+// proxy list in |override_proxies_for_http|.
+bool GetOverrideProxiesForHttpFromCommandLine(
+    std::vector<net::ProxyServer>* override_proxies_for_http);
+
 }  // namespace params
 
 class ClientConfig;
@@ -180,6 +186,13 @@
 
   bool holdback() const override;
 
+  bool quic_enabled() const { return quic_enabled_; }
+
+  // Returns the corresponding string from preprocessor constants if defined,
+  // and an empty string otherwise.
+  virtual std::string GetDefaultDevOrigin() const;
+  virtual std::string GetDefaultDevFallbackOrigin() const;
+
  protected:
   // Test constructor that optionally won't call Init();
   DataReductionProxyParams(int flags,
@@ -196,8 +209,6 @@
 
   // Returns the corresponding string from preprocessor constants if defined,
   // and an empty string otherwise.
-  virtual std::string GetDefaultDevOrigin() const;
-  virtual std::string GetDefaultDevFallbackOrigin() const;
   virtual std::string GetDefaultOrigin() const;
   virtual std::string GetDefaultFallbackOrigin() const;
   virtual std::string GetDefaultSSLOrigin() const;
@@ -224,6 +235,9 @@
 
   bool configured_on_command_line_;
 
+  bool use_override_proxies_for_http_;
+  std::vector<net::ProxyServer> override_proxies_for_http_;
+
   DISALLOW_COPY_AND_ASSIGN(DataReductionProxyParams);
 };
 
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
index e423425..d4870ae7e 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
@@ -423,4 +423,20 @@
   }
 }
 
+TEST(DataReductionProxyParamsStandaloneTest, OverrideProxiesForHttp) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kDataReductionProxyHttpProxies,
+      "http://override-first.net;http://override-second.net");
+  DataReductionProxyParams params(
+      DataReductionProxyParams::kAllowAllProxyConfigurations);
+
+  std::vector<net::ProxyServer> expected_override_proxies_for_http;
+  expected_override_proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://override-first.net", net::ProxyServer::SCHEME_HTTP));
+  expected_override_proxies_for_http.push_back(net::ProxyServer::FromURI(
+      "http://override-second.net", net::ProxyServer::SCHEME_HTTP));
+
+  EXPECT_EQ(expected_override_proxies_for_http, params.proxies_for_http());
+}
+
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc
index 59bcff8..2e83064 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.cc
@@ -81,5 +81,15 @@
 // The URL from which to retrieve the Data Reduction Proxy configuration.
 const char kDataReductionProxyConfigURL[] = "data-reduction-proxy-config-url";
 
+// The semicolon-separated list of proxy server URIs to override the list of
+// HTTP proxies returned by the Data Saver API. If set, the value of this flag
+// overrides any proxies specified by other flags like --spdy-proxy-auth-origin
+// or --spdy-proxy-auth-fallback. If the URI omits a scheme, then the proxy
+// server scheme defaults to HTTP, and if the port is omitted then the default
+// port for that scheme is used. E.g. "http://foo.net:80", "http://foo.net",
+// "foo.net:80", and "foo.net" are all equivalent.
+const char kDataReductionProxyHttpProxies[] =
+    "data-reduction-proxy-http-proxies";
+
 }  // namespace switches
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h
index 548a7a4..180702e4 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h
@@ -33,6 +33,7 @@
 extern const char kClearDataReductionProxyDataSavings[];
 extern const char kEnableDataReductionProxyConfigClient[];
 extern const char kDataReductionProxyConfigURL[];
+extern const char kDataReductionProxyHttpProxies[];
 
 }  // namespace switches
 }  // namespace data_reduction_proxy
diff --git a/components/domain_reliability/context.cc b/components/domain_reliability/context.cc
index 5a35090..3673b9f5 100644
--- a/components/domain_reliability/context.cc
+++ b/components/domain_reliability/context.cc
@@ -154,6 +154,11 @@
     reported = true;
     UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError",
                                 -beacon.chrome_error);
+    if (!beacon.server_ip.empty()) {
+      UMA_HISTOGRAM_SPARSE_SLOWLY(
+          "DomainReliability.ReportedBeaconError_HasServerIP",
+          -beacon.chrome_error);
+    }
     // TODO(ttuttle): Histogram HTTP response code?
   }
 
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc
index 014f34d..115a6c6 100644
--- a/components/domain_reliability/monitor.cc
+++ b/components/domain_reliability/monitor.cc
@@ -11,7 +11,6 @@
 #include "base/task_runner.h"
 #include "base/time/time.h"
 #include "components/domain_reliability/baked_in_configs.h"
-#include "net/base/ip_endpoint.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
@@ -58,17 +57,6 @@
   return true;
 }
 
-// TODO(ttuttle): This function is absurd. See if |socket_address| in
-// HttpResponseInfo can become an IPEndPoint.
-bool ConvertHostPortPairToIPEndPoint(const net::HostPortPair& host_port_pair,
-                                     net::IPEndPoint* ip_endpoint_out) {
-  net::IPAddressNumber ip_address_number;
-  if (!net::ParseIPLiteralToNumber(host_port_pair.host(), &ip_address_number))
-    return false;
-  *ip_endpoint_out = net::IPEndPoint(ip_address_number, host_port_pair.port());
-  return true;
-}
-
 }  // namespace
 
 DomainReliabilityMonitor::DomainReliabilityMonitor(
@@ -275,6 +263,8 @@
       is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) {
   request.GetLoadTimingInfo(&load_timing_info);
   request.GetConnectionAttempts(&connection_attempts);
+  if (!request.GetRemoteEndpoint(&remote_endpoint))
+    remote_endpoint = net::IPEndPoint();
 }
 
 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {}
@@ -312,19 +302,8 @@
   else
     response_code = -1;
 
-  net::IPEndPoint url_request_endpoint;
-  // If response was cached, socket address will be from the serialized
-  // response info in the cache, so don't report it.
-  // TODO(ttuttle): Plumb out the "current" socket address so we can always
-  // report it.
-  if (!request.response_info.was_cached &&
-      !request.response_info.was_fetched_via_proxy) {
-    ConvertHostPortPairToIPEndPoint(request.response_info.socket_address,
-                                    &url_request_endpoint);
-  }
-
   net::ConnectionAttempt url_request_attempt(
-      url_request_endpoint, URLRequestStatusToNetError(request.status));
+      request.remote_endpoint, URLRequestStatusToNetError(request.status));
 
   DomainReliabilityBeacon beacon;
   beacon.protocol = GetDomainReliabilityProtocol(
diff --git a/components/domain_reliability/monitor.h b/components/domain_reliability/monitor.h
index 5260f9f..c91decdb 100644
--- a/components/domain_reliability/monitor.h
+++ b/components/domain_reliability/monitor.h
@@ -22,6 +22,7 @@
 #include "components/domain_reliability/scheduler.h"
 #include "components/domain_reliability/uploader.h"
 #include "components/domain_reliability/util.h"
+#include "net/base/ip_endpoint.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/network_change_notifier.h"
 #include "net/http/http_response_info.h"
@@ -146,6 +147,7 @@
     int load_flags;
     net::LoadTimingInfo load_timing_info;
     net::ConnectionAttempts connection_attempts;
+    net::IPEndPoint remote_endpoint;
     bool is_upload;
   };
 
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc
index c4aa894a..5d71df02 100644
--- a/components/favicon/content/content_favicon_driver.cc
+++ b/components/favicon/content/content_favicon_driver.cc
@@ -161,11 +161,14 @@
 
   // Ignore the update if there is no last committed navigation entry. This can
   // occur when loading an initially blank page.
-  if (!web_contents()->GetController().GetLastCommittedEntry())
+  content::NavigationEntry* entry =
+      web_contents()->GetController().GetLastCommittedEntry();
+  if (!entry)
     return;
 
   favicon_urls_ = candidates;
-  OnUpdateFaviconURL(FaviconURLsFromContentFaviconURLs(candidates));
+  OnUpdateFaviconURL(entry->GetURL(),
+                     FaviconURLsFromContentFaviconURLs(candidates));
 }
 
 void ContentFaviconDriver::DidStartNavigationToPendingEntry(
diff --git a/components/favicon/core/favicon_driver.h b/components/favicon/core/favicon_driver.h
index 986ad391..cf9a4a59 100644
--- a/components/favicon/core/favicon_driver.h
+++ b/components/favicon/core/favicon_driver.h
@@ -62,15 +62,14 @@
   virtual GURL GetActiveURL() = 0;
 
   // Returns whether the page's favicon is valid (returns false if the default
-  // favicon is being used). Requires GetActiveURL() to be valid.
+  // favicon is being used).
   virtual bool GetActiveFaviconValidity() = 0;
 
   // Sets whether the page's favicon is valid (if false, the default favicon is
   // being used).
   virtual void SetActiveFaviconValidity(bool valid) = 0;
 
-  // Returns the URL of the current page's favicon. Requires GetActiveURL() to
-  // be valid.
+  // Returns the URL of the current page's favicon.
   virtual GURL GetActiveFaviconURL() = 0;
 
   // Sets the URL of the favicon's bitmap.
@@ -83,8 +82,9 @@
   // necessarily 16x16. |icon_url| is the url the image is from. If
   // |is_active_favicon| is true the image corresponds to the favicon
   // (possibly empty) of the page.
-  virtual void OnFaviconAvailable(const gfx::Image& image,
+  virtual void OnFaviconAvailable(const GURL& page_url,
                                   const GURL& icon_url,
+                                  const gfx::Image& image,
                                   bool is_active_favicon) = 0;
 
   // Returns whether the driver is waiting for a download to complete or for
diff --git a/components/favicon/core/favicon_driver_impl.cc b/components/favicon/core/favicon_driver_impl.cc
index 81359228..8896bd859 100644
--- a/components/favicon/core/favicon_driver_impl.cc
+++ b/components/favicon/core/favicon_driver_impl.cc
@@ -98,9 +98,17 @@
   return bookmark_model_ && bookmark_model_->IsBookmarked(url);
 }
 
-void FaviconDriverImpl::OnFaviconAvailable(const gfx::Image& image,
+void FaviconDriverImpl::OnFaviconAvailable(const GURL& page_url,
                                            const GURL& icon_url,
+                                           const gfx::Image& image,
                                            bool is_active_favicon) {
+  // Check whether the active URL has changed since FetchFavicon() was called.
+  // On iOS only, the active URL can change between calls to FetchFavicon().
+  // For instance, FetchFavicon() is not synchronously called when the active
+  // URL changes as a result of CRWSessionController::goToEntry().
+  if (page_url != GetActiveURL())
+    return;
+
   if (is_active_favicon) {
     bool icon_url_changed = GetActiveFaviconURL() != icon_url;
     // No matter what happens, we need to mark the favicon as being set.
@@ -141,13 +149,14 @@
 }
 
 void FaviconDriverImpl::OnUpdateFaviconURL(
+    const GURL& page_url,
     const std::vector<FaviconURL>& candidates) {
   DCHECK(!candidates.empty());
-  favicon_handler_->OnUpdateFaviconURL(candidates);
+  favicon_handler_->OnUpdateFaviconURL(page_url, candidates);
   if (touch_icon_handler_.get())
-    touch_icon_handler_->OnUpdateFaviconURL(candidates);
+    touch_icon_handler_->OnUpdateFaviconURL(page_url, candidates);
   if (large_icon_handler_.get())
-    large_icon_handler_->OnUpdateFaviconURL(candidates);
+    large_icon_handler_->OnUpdateFaviconURL(page_url, candidates);
 }
 
 }  // namespace favicon
diff --git a/components/favicon/core/favicon_driver_impl.h b/components/favicon/core/favicon_driver_impl.h
index 7c4c442..68f240c 100644
--- a/components/favicon/core/favicon_driver_impl.h
+++ b/components/favicon/core/favicon_driver_impl.h
@@ -53,8 +53,9 @@
   // FaviconDriver implementation.
   void FetchFavicon(const GURL& url) override;
   bool IsBookmarked(const GURL& url) override;
-  void OnFaviconAvailable(const gfx::Image& image,
+  void OnFaviconAvailable(const GURL& page_url,
                           const GURL& icon_url,
+                          const gfx::Image& image,
                           bool is_active_favicon) override;
   bool HasPendingTasksForTest() override;
 
@@ -73,7 +74,8 @@
   void SetFaviconOutOfDateForPage(const GURL& url, bool force_reload);
 
   // Broadcasts new favicon URL candidates to FaviconHandlers.
-  void OnUpdateFaviconURL(const std::vector<FaviconURL>& candidates);
+  void OnUpdateFaviconURL(const GURL& page_url,
+                          const std::vector<FaviconURL>& candidates);
 
  protected:
   history::HistoryService* history_service() { return history_service_; }
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc
index 3befa34..58c0c8cb 100644
--- a/components/favicon/core/favicon_handler.cc
+++ b/components/favicon/core/favicon_handler.cc
@@ -54,16 +54,6 @@
   return true;
 }
 
-std::string UrlWithoutFragment(const GURL& gurl) {
-  GURL::Replacements replacements;
-  replacements.ClearRef();
-  return gurl.ReplaceComponents(replacements).spec();
-}
-
-bool UrlMatches(const GURL& gurl_a, const GURL& gurl_b) {
-  return UrlWithoutFragment(gurl_a) == UrlWithoutFragment(gurl_b);
-}
-
 // Return true if |bitmap_result| is expired.
 bool IsExpired(const favicon_base::FaviconRawBitmapResult& bitmap_result) {
   return bitmap_result.expired;
@@ -173,10 +163,9 @@
 }
 
 FaviconHandler::DownloadRequest::DownloadRequest(
-    const GURL& url,
     const GURL& image_url,
     favicon_base::IconType icon_type)
-    : url(url), image_url(image_url), icon_type(icon_type) {
+    : image_url(image_url), icon_type(icon_type) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -189,13 +178,11 @@
 }
 
 FaviconHandler::FaviconCandidate::FaviconCandidate(
-    const GURL& url,
     const GURL& image_url,
     const gfx::Image& image,
     float score,
     favicon_base::IconType icon_type)
-    : url(url),
-      image_url(image_url),
+    : image_url(image_url),
       image(image),
       score(score),
       icon_type(icon_type) {}
@@ -255,8 +242,7 @@
       &cancelable_task_tracker_);
 }
 
-bool FaviconHandler::UpdateFaviconCandidate(const GURL& url,
-                                            const GURL& image_url,
+bool FaviconHandler::UpdateFaviconCandidate(const GURL& image_url,
                                             const gfx::Image& image,
                                             float score,
                                             favicon_base::IconType icon_type) {
@@ -293,18 +279,17 @@
         score > best_favicon_candidate_.score;
   }
   if (replace_best_favicon_candidate) {
-    best_favicon_candidate_ = FaviconCandidate(
-        url, image_url, image, score, icon_type);
+    best_favicon_candidate_ =
+        FaviconCandidate(image_url, image, score, icon_type);
   }
   return exact_match;
 }
 
-void FaviconHandler::SetFavicon(const GURL& url,
-                                const GURL& icon_url,
+void FaviconHandler::SetFavicon(const GURL& icon_url,
                                 const gfx::Image& image,
                                 favicon_base::IconType icon_type) {
-  if (ShouldSaveFavicon(url))
-    SetHistoryFavicons(url, icon_url, icon_type, image);
+  if (ShouldSaveFavicon())
+    SetHistoryFavicons(url_, icon_url, icon_type, image);
 
   NotifyFaviconAvailable(icon_url, image);
 }
@@ -332,11 +317,15 @@
       (handler_type_ == FAVICON && !download_largest_icon_);
 
   driver_->OnFaviconAvailable(
-      image_with_adjusted_colorspace, icon_url, is_active_favicon);
+      url_, icon_url, image_with_adjusted_colorspace, is_active_favicon);
 }
 
 void FaviconHandler::OnUpdateFaviconURL(
+    const GURL& page_url,
     const std::vector<FaviconURL>& candidates) {
+  if (page_url != url_)
+    return;
+
   download_requests_.clear();
   image_urls_.clear();
   best_favicon_candidate_ = FaviconCandidate();
@@ -360,7 +349,7 @@
 
   // current_candidate() may return NULL if download_largest_icon_ is true and
   // all the sizes are larger than the max.
-  if (PageChangedSinceFaviconWasRequested() || !current_candidate())
+  if (!current_candidate())
     return;
 
   if (current_candidate()->icon_type == favicon_base::FAVICON &&
@@ -378,8 +367,7 @@
   }
 
   if (got_favicon_from_history_)
-    DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(),
-                                       current_candidate()->icon_url,
+    DownloadFaviconOrAskFaviconService(current_candidate()->icon_url,
                                        current_candidate()->icon_type);
 }
 
@@ -398,8 +386,7 @@
   DownloadRequest download_request = i->second;
   download_requests_.erase(i);
 
-  if (PageChangedSinceFaviconWasRequested() ||
-      !current_candidate() ||
+  if (!current_candidate() ||
       !DoUrlAndIconMatch(*current_candidate(),
                          image_url,
                          download_request.icon_type)) {
@@ -434,9 +421,8 @@
       gfx::Image image(image_skia);
       // The downloaded icon is still valid when there is no FaviconURL update
       // during the downloading.
-      request_next_icon = !UpdateFaviconCandidate(
-          download_request.url, image_url, image, score,
-          download_request.icon_type);
+      request_next_icon = !UpdateFaviconCandidate(image_url, image, score,
+                                                  download_request.icon_type);
     }
   }
 
@@ -448,7 +434,7 @@
     // We have either found the ideal candidate or run out of candidates.
     if (best_favicon_candidate_.icon_type != favicon_base::INVALID_ICON) {
       // No more icons to request, set the favicon from the candidate.
-      SetFavicon(best_favicon_candidate_.url, best_favicon_candidate_.image_url,
+      SetFavicon(best_favicon_candidate_.image_url,
                  best_favicon_candidate_.image,
                  best_favicon_candidate_.icon_type);
     }
@@ -464,15 +450,6 @@
          cancelable_task_tracker_.HasTrackedTasks();
 }
 
-bool FaviconHandler::PageChangedSinceFaviconWasRequested() {
-  if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) {
-    return false;
-  }
-  // If the URL has changed out from under us (as will happen with redirects)
-  // return true.
-  return true;
-}
-
 int FaviconHandler::DownloadFavicon(const GURL& image_url,
                                     int max_bitmap_size) {
   if (!image_url.is_valid()) {
@@ -531,12 +508,12 @@
   }
 }
 
-bool FaviconHandler::ShouldSaveFavicon(const GURL& url) {
+bool FaviconHandler::ShouldSaveFavicon() {
   if (!driver_->IsOffTheRecord())
     return true;
 
   // Always save favicon if the page is bookmarked.
-  return driver_->IsBookmarked(url);
+  return driver_->IsBookmarked(url_);
 }
 
 int FaviconHandler::GetMaximalIconSize(favicon_base::IconType icon_type) {
@@ -560,8 +537,6 @@
 void FaviconHandler::OnFaviconDataForInitialURLFromFaviconService(
     const std::vector<favicon_base::FaviconRawBitmapResult>&
         favicon_bitmap_results) {
-  if (PageChangedSinceFaviconWasRequested())
-    return;
   got_favicon_from_history_ = true;
   history_results_ = favicon_bitmap_results;
   bool has_results = !favicon_bitmap_results.empty();
@@ -592,16 +567,14 @@
       // Mapping in the database is wrong. DownloadFavIconOrAskHistory will
       // update the mapping for this url and download the favicon if we don't
       // already have it.
-      DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(),
-                                         current_candidate()->icon_url,
+      DownloadFaviconOrAskFaviconService(current_candidate()->icon_url,
                                          current_candidate()->icon_type);
     }
   } else if (current_candidate()) {
     // We know the official url for the favicon, but either don't have the
     // favicon or it's expired. Continue on to DownloadFaviconOrAskHistory to
     // either download or check history again.
-    DownloadFaviconOrAskFaviconService(driver_->GetActiveURL(),
-                                       current_candidate()->icon_url,
+    DownloadFaviconOrAskFaviconService(current_candidate()->icon_url,
                                        current_candidate()->icon_type);
   }
   // else we haven't got the icon url. When we get it we'll ask the
@@ -612,12 +585,11 @@
 }
 
 void FaviconHandler::DownloadFaviconOrAskFaviconService(
-    const GURL& page_url,
     const GURL& icon_url,
     favicon_base::IconType icon_type) {
   if (favicon_expired_or_incomplete_) {
     // We have the mapping, but the favicon is out of date. Download it now.
-    ScheduleDownload(page_url, icon_url, icon_type);
+    ScheduleDownload(icon_url, icon_type);
   } else {
     // We don't know the favicon, but we may have previously downloaded the
     // favicon for another page that shares the same favicon. Ask for the
@@ -634,7 +606,7 @@
       //    include the mapping between the page url and the favicon url.
       // This is asynchronous. The history service will call back when done.
       UpdateFaviconMappingAndFetch(
-          page_url, icon_url, icon_type,
+          url_, icon_url, icon_type,
           base::Bind(&FaviconHandler::OnFaviconData, base::Unretained(this)),
           &cancelable_task_tracker_);
     }
@@ -643,9 +615,6 @@
 
 void FaviconHandler::OnFaviconData(const std::vector<
     favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) {
-  if (PageChangedSinceFaviconWasRequested())
-    return;
-
   bool has_results = !favicon_bitmap_results.empty();
   bool has_expired_or_incomplete_result = HasExpiredOrIncompleteResult(
       preferred_icon_size(), favicon_bitmap_results);
@@ -668,15 +637,13 @@
   }
 
   if (!has_results || has_expired_or_incomplete_result) {
-    ScheduleDownload(driver_->GetActiveURL(),
-                     current_candidate()->icon_url,
+    ScheduleDownload(current_candidate()->icon_url,
                      current_candidate()->icon_type);
   }
 }
 
-void FaviconHandler::ScheduleDownload(const GURL& url,
-                                     const GURL& image_url,
-                                     favicon_base::IconType icon_type) {
+void FaviconHandler::ScheduleDownload(const GURL& image_url,
+                                      favicon_base::IconType icon_type) {
   // A max bitmap size is specified to avoid receiving huge bitmaps in
   // OnDidDownloadFavicon(). See FaviconDriver::StartDownload()
   // for more details about the max bitmap size.
@@ -685,7 +652,7 @@
 
   // Download ids should be unique.
   DCHECK(download_requests_.find(download_id) == download_requests_.end());
-  download_requests_[download_id] = DownloadRequest(url, image_url, icon_type);
+  download_requests_[download_id] = DownloadRequest(image_url, icon_type);
 
   if (download_id == 0) {
     // If DownloadFavicon() did not start a download, it returns a download id
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h
index 3fee8be..4850f3c 100644
--- a/components/favicon/core/favicon_handler.h
+++ b/components/favicon/core/favicon_handler.h
@@ -94,7 +94,8 @@
 
   // Message Handler.  Must be public, because also called from
   // PrerenderContents. Collects the |image_urls| list.
-  void OnUpdateFaviconURL(const std::vector<favicon::FaviconURL>& candidates);
+  void OnUpdateFaviconURL(const GURL& page_url,
+                          const std::vector<favicon::FaviconURL>& candidates);
 
   // Processes the current image_urls_ entry, requesting the image from the
   // history / download service.
@@ -153,7 +154,7 @@
                                   const gfx::Image& image);
 
   // Returns true if the favicon should be saved.
-  virtual bool ShouldSaveFavicon(const GURL& url);
+  virtual bool ShouldSaveFavicon();
 
  private:
   // For testing:
@@ -164,11 +165,8 @@
     DownloadRequest();
     ~DownloadRequest();
 
-    DownloadRequest(const GURL& url,
-                    const GURL& image_url,
-                    favicon_base::IconType icon_type);
+    DownloadRequest(const GURL& image_url, favicon_base::IconType icon_type);
 
-    GURL url;
     GURL image_url;
     favicon_base::IconType icon_type;
   };
@@ -178,13 +176,11 @@
     FaviconCandidate();
     ~FaviconCandidate();
 
-    FaviconCandidate(const GURL& url,
-                     const GURL& image_url,
+    FaviconCandidate(const GURL& image_url,
                      const gfx::Image& image,
                      float score,
                      favicon_base::IconType icon_type);
 
-    GURL url;
     GURL image_url;
     gfx::Image image;
     float score;
@@ -202,8 +198,7 @@
   // If the favicon has expired, asks the renderer to download the favicon.
   // Otherwise asks history to update the mapping between page url and icon
   // url with a callback to OnFaviconData when done.
-  void DownloadFaviconOrAskFaviconService(const GURL& page_url,
-                                          const GURL& icon_url,
+  void DownloadFaviconOrAskFaviconService(const GURL& icon_url,
                                           favicon_base::IconType icon_type);
 
   // See description above class for details.
@@ -212,20 +207,17 @@
 
   // Schedules a download for the specified entry. This adds the request to
   // download_requests_.
-  void ScheduleDownload(const GURL& url,
-                        const GURL& image_url,
+  void ScheduleDownload(const GURL& image_url,
                         favicon_base::IconType icon_type);
 
   // Updates |favicon_candidate_| and returns true if it is an exact match.
-  bool UpdateFaviconCandidate(const GURL& url,
-                              const GURL& image_url,
+  bool UpdateFaviconCandidate(const GURL& image_url,
                               const gfx::Image& image,
                               float score,
                               favicon_base::IconType icon_type);
 
   // Sets the image data for the favicon.
-  void SetFavicon(const GURL& url,
-                  const GURL& icon_url,
+  void SetFavicon(const GURL& icon_url,
                   const gfx::Image& image,
                   favicon_base::IconType icon_type);
 
@@ -242,9 +234,6 @@
     return (!image_urls_.empty()) ? &image_urls_.front() : NULL;
   }
 
-  // Returns whether the page's url changed since the favicon was requested.
-  bool PageChangedSinceFaviconWasRequested();
-
   // Returns the preferred size of the image. 0 means no preference (any size
   // will do).
   int preferred_icon_size() const {
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc
index fb51385..69869039 100644
--- a/components/favicon/core/favicon_handler_unittest.cc
+++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -247,8 +247,9 @@
     image_ = image;
   }
 
-  void OnFaviconAvailable(const gfx::Image& image,
+  void OnFaviconAvailable(const GURL& page_url,
                           const GURL& icon_url,
+                          const gfx::Image& image,
                           bool update_active_favicon) override {
     ++num_favicon_available_;
     available_image_ = image;
@@ -398,7 +399,7 @@
         page_url, icon_url, icon_type, bitmap_data, image.Size()));
   }
 
-  bool ShouldSaveFavicon(const GURL& url) override { return true; }
+  bool ShouldSaveFavicon() override { return true; }
 
   GURL page_url_;
 
@@ -502,7 +503,7 @@
     favicon_handler->FetchFavicon(page_url);
     favicon_handler->history_handler()->InvokeCallback();
 
-    favicon_handler->OnUpdateFaviconURL(candidate_icons);
+    favicon_handler->OnUpdateFaviconURL(page_url, candidate_icons);
   }
 
   void SetUp() override {
@@ -551,7 +552,7 @@
   std::vector<FaviconURL> urls;
   urls.push_back(
       FaviconURL(icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status
   EXPECT_EQ(1U, helper.urls().size());
@@ -593,7 +594,7 @@
   std::vector<FaviconURL> urls;
   urls.push_back(
       FaviconURL(icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status
   EXPECT_EQ(1U, helper.urls().size());
@@ -662,7 +663,7 @@
   std::vector<FaviconURL> urls;
   urls.push_back(FaviconURL(
       new_icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status.
   EXPECT_EQ(1U, helper.urls().size());
@@ -749,7 +750,7 @@
   std::vector<FaviconURL> urls;
   urls.push_back(
       FaviconURL(icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // A download for the favicon should be requested, and we should not do
   // another history request.
@@ -810,7 +811,7 @@
   std::vector<FaviconURL> urls;
   urls.push_back(FaviconURL(
       new_icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status.
   EXPECT_EQ(1U, helper.urls().size());
@@ -879,7 +880,7 @@
       new_icon_url, favicon_base::TOUCH_ICON, std::vector<gfx::Size>()));
   urls.push_back(FaviconURL(
       new_icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status.
   EXPECT_EQ(2U, helper.urls().size());
@@ -990,7 +991,7 @@
       new_icon_url, favicon_base::TOUCH_ICON, std::vector<gfx::Size>()));
   urls.push_back(FaviconURL(
       new_icon_url, favicon_base::FAVICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(urls);
+  helper.OnUpdateFaviconURL(page_url, urls);
 
   // Verify FaviconHandler status.
   EXPECT_EQ(2U, helper.urls().size());
@@ -1024,7 +1025,7 @@
   std::vector<FaviconURL> latest_urls;
   latest_urls.push_back(FaviconURL(
       latest_icon_url, favicon_base::TOUCH_ICON, std::vector<gfx::Size>()));
-  helper.OnUpdateFaviconURL(latest_urls);
+  helper.OnUpdateFaviconURL(page_url, latest_urls);
 
   EXPECT_EQ(1U, helper.urls().size());
   EXPECT_EQ(latest_icon_url, helper.current_candidate()->icon_url);
diff --git a/components/favicon/ios/web_favicon_driver.cc b/components/favicon/ios/web_favicon_driver.cc
index b691ecfb..cadd60f 100644
--- a/components/favicon/ios/web_favicon_driver.cc
+++ b/components/favicon/ios/web_favicon_driver.cc
@@ -32,6 +32,11 @@
                                               history_service, bookmark_model));
 }
 
+void WebFaviconDriver::FetchFavicon(const GURL& url) {
+  fetch_favicon_url_ = url;
+  FaviconDriverImpl::FetchFavicon(url);
+}
+
 gfx::Image WebFaviconDriver::GetFavicon() const {
   web::NavigationItem* item =
       web_state()->GetNavigationManager()->GetLastCommittedItem();
@@ -68,7 +73,7 @@
 }
 
 bool WebFaviconDriver::GetActiveFaviconValidity() {
-  return GetFaviconStatus().valid;
+  return !ActiveURLChangedSinceFetchFavicon() && GetFaviconStatus().valid;
 }
 
 void WebFaviconDriver::SetActiveFaviconValidity(bool validity) {
@@ -76,7 +81,7 @@
 }
 
 GURL WebFaviconDriver::GetActiveFaviconURL() {
-  return GetFaviconStatus().url;
+  return ActiveURLChangedSinceFetchFavicon() ? GURL() : GetFaviconStatus().url;
 }
 
 void WebFaviconDriver::SetActiveFaviconURL(const GURL& url) {
@@ -87,8 +92,17 @@
   GetFaviconStatus().image = image;
 }
 
+bool WebFaviconDriver::ActiveURLChangedSinceFetchFavicon() {
+  // On iOS the active URL can change in between calls to FetchFavicon(). For
+  // instance, FetchFavicon() is not synchronously called when the active URL
+  // changes as a result of CRWSessionController::goToEntry().
+  // TODO(stuartmorgan): Remove this once iOS always triggers favicon fetches
+  // synchronously after active URL changes.
+  return GetActiveURL() != fetch_favicon_url_;
+}
+
 web::FaviconStatus& WebFaviconDriver::GetFaviconStatus() {
-  DCHECK(web_state()->GetNavigationManager()->GetVisibleItem());
+  DCHECK(!ActiveURLChangedSinceFetchFavicon());
   return web_state()->GetNavigationManager()->GetVisibleItem()->GetFavicon();
 }
 
@@ -106,7 +120,7 @@
 void WebFaviconDriver::FaviconUrlUpdated(
     const std::vector<web::FaviconURL>& candidates) {
   DCHECK(!candidates.empty());
-  OnUpdateFaviconURL(FaviconURLsFromWebFaviconURLs(candidates));
+  OnUpdateFaviconURL(GetActiveURL(), FaviconURLsFromWebFaviconURLs(candidates));
 }
 
 }  // namespace favicon
diff --git a/components/favicon/ios/web_favicon_driver.h b/components/favicon/ios/web_favicon_driver.h
index 9ea3e7d2..0be7bce 100644
--- a/components/favicon/ios/web_favicon_driver.h
+++ b/components/favicon/ios/web_favicon_driver.h
@@ -29,6 +29,7 @@
                                 bookmarks::BookmarkModel* bookmark_model);
 
   // FaviconDriver implementation.
+  void FetchFavicon(const GURL& url) override;
   gfx::Image GetFavicon() const override;
   bool FaviconIsValid() const override;
   int StartDownload(const GURL& url, int max_bitmap_size) override;
@@ -49,6 +50,9 @@
                    bookmarks::BookmarkModel* bookmark_model);
   ~WebFaviconDriver() override;
 
+  // Returns whether the active URL has changed since FetchFavicon() was called.
+  bool ActiveURLChangedSinceFetchFavicon();
+
   // web::WebStateObserver implementation.
   void FaviconUrlUpdated(
       const std::vector<web::FaviconURL>& candidates) override;
@@ -56,6 +60,9 @@
   // Returns the active navigation entry's favicon.
   web::FaviconStatus& GetFaviconStatus();
 
+  // The URL passed to FetchFavicon().
+  GURL fetch_favicon_url_;
+
   DISALLOW_COPY_AND_ASSIGN(WebFaviconDriver);
 };
 
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc b/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc
index bfe85dfc..49cf6a7 100644
--- a/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc
+++ b/components/gcm_driver/crypto/gcm_message_cryptographer_nss.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "base/numerics/safe_math.h"
 #include "base/strings/string_util.h"
-#include "crypto/aes_128_gcm_helpers_nss.h"
 #include "crypto/scoped_nss_types.h"
 
 namespace gcm {
@@ -32,15 +31,10 @@
   const CK_ATTRIBUTE_TYPE cka_mode = mode == ENCRYPT ? CKA_ENCRYPT
                                                      : CKA_DECRYPT;
 
-  // TODO(peter): For AES-GCM we should be using CKM_AES_GCM as the mechanism,
-  // but because of an NSS bug we need to use CKM_AES_ECB as a work-around until
-  // we require NSS 3.15+. https://bugzilla.mozilla.org/show_bug.cgi?id=853285
-  // This does not affect the call to PK11{Decrypt,Encrypt}Helper below.
-  const CK_MECHANISM_TYPE key_mechanism = CKM_AES_ECB;
-
   crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
-  crypto::ScopedPK11SymKey aead_key(PK11_ImportSymKey(slot.get(), key_mechanism,
-      PK11_OriginUnwrap, cka_mode, &key_item, nullptr));
+  crypto::ScopedPK11SymKey aead_key(
+      PK11_ImportSymKey(slot.get(), CKM_AES_GCM, PK11_OriginUnwrap, cka_mode,
+                        &key_item, nullptr));
 
   CK_GCM_PARAMS gcm_params;
   gcm_params.pIv = const_cast<unsigned char*>(
@@ -71,17 +65,15 @@
       base::WriteInto(output, maximum_output_length.ValueOrDie()));
 
   if (mode == ENCRYPT) {
-    if (crypto::PK11EncryptHelper(aead_key.get(), CKM_AES_GCM, &param,
-                                  raw_output, &output_length, output->size(),
-                                  raw_input, input.size())
-            != SECSuccess) {
+    if (PK11_Encrypt(aead_key.get(), CKM_AES_GCM, &param, raw_output,
+                     &output_length, output->size(), raw_input,
+                     input.size()) != SECSuccess) {
       return false;
     }
   } else {
-    if (crypto::PK11DecryptHelper(aead_key.get(), CKM_AES_GCM, &param,
-                                  raw_output, &output_length, output->size(),
-                                  raw_input, input.size())
-            != SECSuccess) {
+    if (PK11_Decrypt(aead_key.get(), CKM_AES_GCM, &param, raw_output,
+                     &output_length, output->size(), raw_input,
+                     input.size()) != SECSuccess) {
       return false;
     }
   }
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index e4243bf..8257beb 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -1045,10 +1045,12 @@
 
 // Statistics ------------------------------------------------------------------
 
-HistoryCountResult HistoryBackend::GetHistoryCount() {
+HistoryCountResult HistoryBackend::GetHistoryCount(const Time& begin_time,
+                                                   const Time& end_time) {
   HistoryCountResult result;
   result.count = 0;
-  result.success = db_ && db_->GetHistoryCount(&result.count);
+  result.success =
+      db_ && db_->GetHistoryCount(begin_time, end_time, &result.count);
   return result;
 }
 
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index c8f87f25..71f3eb3 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -276,11 +276,12 @@
 
   // Statistics ----------------------------------------------------------------
 
-  // Gets the number of URLs as seen in chrome://history with infinite date
-  // range. If a URL is visited in multiple days, the URL is counted once for
-  // each day. For determination of the date, timestamps are converted to dates
-  // using local time.
-  HistoryCountResult GetHistoryCount();
+  // Gets the number of URLs as seen in chrome://history within the time range
+  // [|begin_time|, |end_time|). Each URL is counted only once per day. For
+  // determination of the date, timestamps are converted to dates using local
+  // time.
+  HistoryCountResult GetHistoryCount(const base::Time& begin_time,
+                                     const base::Time& end_time);
 
   // Favicon -------------------------------------------------------------------
 
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc
index fafadfb..c0e9536 100644
--- a/components/history/core/browser/history_service.cc
+++ b/components/history/core/browser/history_service.cc
@@ -670,6 +670,8 @@
 // Statistics ------------------------------------------------------------------
 
 base::CancelableTaskTracker::TaskId HistoryService::GetHistoryCount(
+    const Time& begin_time,
+    const Time& end_time,
     const GetHistoryCountCallback& callback,
     base::CancelableTaskTracker* tracker) {
   DCHECK(thread_) << "History service being called after cleanup";
@@ -677,7 +679,10 @@
 
   return tracker->PostTaskAndReplyWithResult(
       thread_->task_runner().get(), FROM_HERE,
-      base::Bind(&HistoryBackend::GetHistoryCount, history_backend_.get()),
+      base::Bind(&HistoryBackend::GetHistoryCount,
+                 history_backend_.get(),
+                 begin_time,
+                 end_time),
       callback);
 }
 
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h
index 56fa114..62267e1 100644
--- a/components/history/core/browser/history_service.h
+++ b/components/history/core/browser/history_service.h
@@ -344,13 +344,15 @@
 
   // Statistics ----------------------------------------------------------------
 
-  // Gets the number of URLs as seen in chrome://history with infinite date
-  // range. If a URL is visited in multiple days, the URL is counted once for
-  // each day. For determination of the date, timestamps are converted to dates
-  // using local time.
+  // Gets the number of URLs as seen in chrome://history within the time range
+  // [|begin_time|, |end_time|). Each URL is counted only once per day. For
+  // determination of the date, timestamps are converted to dates using local
+  // time.
   typedef base::Callback<void(HistoryCountResult)> GetHistoryCountCallback;
 
   base::CancelableTaskTracker::TaskId GetHistoryCount(
+      const base::Time& begin_time,
+      const base::Time& end_time,
       const GetHistoryCountCallback& callback,
       base::CancelableTaskTracker* tracker);
 
diff --git a/components/history/core/browser/visit_database.cc b/components/history/core/browser/visit_database.cc
index 3d4e715..5d47a5a5 100644
--- a/components/history/core/browser/visit_database.cc
+++ b/components/history/core/browser/visit_database.cc
@@ -537,7 +537,9 @@
   return true;
 }
 
-bool VisitDatabase::GetHistoryCount(int* count) {
+bool VisitDatabase::GetHistoryCount(const base::Time& begin_time,
+                                    const base::Time& end_time,
+                                    int* count) {
   sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
       "SELECT COUNT(*) FROM ("
       "SELECT DISTINCT url, "
@@ -545,11 +547,12 @@
       // Windows Epoch to the number of seconds from Unix Epoch. Leap seconds
       // are not handled in both timestamp units, so a linear conversion is
       // valid here.
-      "DATE((visit_time - ?) / ?, 'unixepoch', 'localtime') "
+      "DATE((visit_time - ?) / ?, 'unixepoch', 'localtime')"
       "FROM visits "
       "WHERE (transition & ?) != 0 "  // CHAIN_END
-      "AND (transition & ?) NOT IN (?, ?, ?)"  // NO SUBFRAME or
-                                               // KEYWORD_GENERATED
+      "AND (transition & ?) NOT IN (?, ?, ?) "  // NO SUBFRAME or
+                                                // KEYWORD_GENERATED
+      "AND visit_time >= ? AND visit_time < ?"
       ")"));
 
   statement.BindInt64(0, base::Time::kTimeTToMicrosecondsOffset);
@@ -559,6 +562,8 @@
   statement.BindInt(4, ui::PAGE_TRANSITION_AUTO_SUBFRAME);
   statement.BindInt(5, ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
   statement.BindInt(6, ui::PAGE_TRANSITION_KEYWORD_GENERATED);
+  statement.BindInt64(7, begin_time.ToInternalValue());
+  statement.BindInt64(8, end_time.ToInternalValue());
 
   if (!statement.Step())
     return false;
diff --git a/components/history/core/browser/visit_database.h b/components/history/core/browser/visit_database.h
index 765dc81..eb3a8f8 100644
--- a/components/history/core/browser/visit_database.h
+++ b/components/history/core/browser/visit_database.h
@@ -178,13 +178,15 @@
                                   int* count,
                                   base::Time* first_visit);
 
-  // Gets the number of URLs as seen in chrome://history with infinite date
-  // range. "User-visible" is defined as in GetVisibleVisitsInRange() above,
-  // i.e. excluding redirects and subframes. Also, if a URL is visited in
-  // multiple days, the URL is counted once for each day. For determination
-  // of the date, timestamps are converted to dates using local time.
-  // Returns false if there's a failure executing the statement. True otherwise.
-  bool GetHistoryCount(int* count);
+  // Gets the number of URLs as seen in chrome://history within the time
+  // range [|begin_time|, |end_time|). "User-visible" is defined as in
+  // GetVisibleVisitsInRange() above, i.e. excluding redirects and subframes.
+  // Each URL is counted only once per day. For determination of the date,
+  // timestamps are converted to dates using local time. Returns false if
+  // there is a failure executing the statement. True otherwise.
+  bool GetHistoryCount(const base::Time& begin_time,
+                       const base::Time& end_time,
+                       int* count);
 
   // Get the time of the first item in our database.
   bool GetStartDate(base::Time* first_visit);
diff --git a/components/history/core/browser/visit_database_unittest.cc b/components/history/core/browser/visit_database_unittest.cc
index be2594a1..8074dd9 100644
--- a/components/history/core/browser/visit_database_unittest.cc
+++ b/components/history/core/browser/visit_database_unittest.cc
@@ -416,4 +416,176 @@
   EXPECT_TRUE(IsVisitInfoEqual(results[2], test_visit_rows[0]));
 }
 
+TEST_F(VisitDatabaseTest, GetHistoryCount) {
+  Time today = Time::Now().LocalMidnight();
+  // Find the beginning of yesterday and the day before yesterday. We cannot use
+  // TimeDelta::FromDays(1), as this simply removes 24 hours and thus does not
+  // work correctly with DST shifts. Instead, we'll jump 36 hours (i.e.
+  // somewhere in the middle of the previous day), and use |LocalMidnight()| to
+  // round down to the beginning of the day in the local time, taking timezones
+  // and DST into account. This is necessary to achieve the same equivalence
+  // class on days as the DATE(..., 'localtime') function in SQL.
+  Time yesterday = (today - TimeDelta::FromHours(36)).LocalMidnight();
+  Time two_days_ago = (yesterday - TimeDelta::FromHours(36)).LocalMidnight();
+  Time now = two_days_ago;
+
+  ui::PageTransition standard_transition = ui::PageTransitionFromInt(
+      ui::PAGE_TRANSITION_TYPED |
+      ui::PAGE_TRANSITION_CHAIN_START |
+      ui::PAGE_TRANSITION_CHAIN_END);
+
+  // Add 5 visits (3 distinct URLs) for the day before yesterday.
+  // Whether the URL was browsed on this machine or synced has no effect.
+  VisitRow first_day_1(1, now, 0, standard_transition, 0);
+  first_day_1.visit_id = 1;
+  AddVisit(&first_day_1, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow first_day_2(2, now, 0, standard_transition, 0);
+  first_day_2.visit_id = 2;
+  AddVisit(&first_day_2, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow first_day_3(1, now, 0, standard_transition, 0);
+  first_day_3.visit_id = 3;
+  AddVisit(&first_day_3, SOURCE_SYNCED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow first_day_4(3, now, 0, standard_transition, 0);
+  first_day_4.visit_id = 4;
+  AddVisit(&first_day_4, SOURCE_SYNCED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow first_day_5(2, now, 0, standard_transition, 0);
+  first_day_5.visit_id = 5;
+  AddVisit(&first_day_5, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  // Add 4 more visits for yesterday. One of them is invalid, as it's not
+  // a user-visible navigation. Of the remaining 3, only 2 are unique.
+  now = yesterday;
+
+  VisitRow second_day_1(1, now, 0, standard_transition, 0);
+  second_day_1.visit_id = 6;
+  AddVisit(&second_day_1, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow second_day_2(1, now, 0, standard_transition, 0);
+  second_day_2.visit_id = 7;
+  AddVisit(&second_day_2, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow second_day_3(2, now, 0, ui::PAGE_TRANSITION_AUTO_SUBFRAME, 0);
+  second_day_3.visit_id = 8;
+  AddVisit(&second_day_3, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  VisitRow second_day_4(3, now, 0, standard_transition, 0);
+  second_day_4.visit_id = 9;
+  AddVisit(&second_day_4, SOURCE_BROWSED);
+  now += TimeDelta::FromHours(1);
+
+  int result;
+
+  // There were 3 distinct URLs two days ago.
+  EXPECT_TRUE(GetHistoryCount(two_days_ago, yesterday, &result));
+  EXPECT_EQ(3, result);
+
+  // For both previous days, there should be 5 per-day unique URLs.
+  EXPECT_TRUE(GetHistoryCount(two_days_ago, today, &result));
+  EXPECT_EQ(5, result);
+
+  // Since we only have entries for the two previous days, the infinite time
+  // range should yield the same result.
+  EXPECT_TRUE(GetHistoryCount(Time(), Time::Max(), &result));
+  EXPECT_EQ(5, result);
+
+  // Narrowing the range to exclude |first_day_1| will still return 5,
+  // because |first_day_1| is not unique.
+  EXPECT_TRUE(GetHistoryCount(
+      two_days_ago + TimeDelta::FromHours(2), today, &result));
+  EXPECT_EQ(5, result);
+
+  // Narrowing the range to exclude |second_day_4| will return 4,
+  // because |second_day_4| is unique.
+  EXPECT_TRUE(GetHistoryCount(
+      two_days_ago, yesterday + TimeDelta::FromHours(3), &result));
+  EXPECT_EQ(4, result);
+
+  // Narrowing the range to exclude both |first_day_1| and |second_day_4| will
+  // still return 4.
+  EXPECT_TRUE(GetHistoryCount(two_days_ago + TimeDelta::FromHours(2),
+                              yesterday + TimeDelta::FromHours(3),
+                              &result));
+  EXPECT_EQ(4, result);
+
+  // A range that contains no visits will return 0.
+  EXPECT_TRUE(GetHistoryCount(two_days_ago + TimeDelta::FromMicroseconds(1),
+                              two_days_ago + TimeDelta::FromHours(1),
+                              &result));
+  EXPECT_EQ(0, result);
+
+  // If this timezone uses DST, test the behavior on days when the time
+  // is shifted forward and backward.
+  Time shift_forward;
+  Time shift_backward;
+  Time current_day = (two_days_ago - TimeDelta::FromSeconds(1)).LocalMidnight();
+  for (int i = 0; i < 366; i++) {
+    current_day = (current_day - TimeDelta::FromSeconds(1)).LocalMidnight();
+    Time after_24_hours = current_day + TimeDelta::FromHours(24);
+
+    if (current_day == after_24_hours.LocalMidnight()) {
+      // More than 24 hours. Shift backward.
+      shift_backward = current_day;
+    } else if (after_24_hours > after_24_hours.LocalMidnight()) {
+      // Less than 24 hours. Shift forward.
+      shift_forward = current_day;
+    }
+
+    if (!shift_backward.is_null() && !shift_forward.is_null())
+      break;
+  }
+
+  // Test the backward shift. Add two visits for the same page on midnight and
+  // 24 hours later. The count should be 1, not 2, because the day is longer
+  // than 24 hours, and the two visits will be regarded as duplicate.
+  if (!shift_backward.is_null()) {
+    VisitRow backward_1(1, shift_backward, 0, standard_transition, 0);
+    backward_1.visit_id = 10;
+    AddVisit(&backward_1, SOURCE_BROWSED);
+
+    VisitRow backward_2(1, shift_backward + TimeDelta::FromHours(24),
+                        0, standard_transition, 0);
+    backward_2.visit_id = 11;
+    AddVisit(&backward_2, SOURCE_BROWSED);
+
+    EXPECT_TRUE(GetHistoryCount(shift_backward,
+                                shift_backward + TimeDelta::FromHours(25),
+                                &result));
+    EXPECT_EQ(1, result);
+  }
+
+  // Test the forward shift. Add two visits for the same page at midnight and
+  // almost 24 hours later. The count should be 2, not 1. The visits would be
+  // regarded as duplicate in a normal 24 hour day, but in this case the second
+  // visit is already in the next day.
+  if (!shift_forward.is_null()) {
+    VisitRow forward_1(1, shift_forward, 0, standard_transition, 0);
+    forward_1.visit_id = 12;
+    AddVisit(&forward_1, SOURCE_BROWSED);
+
+    Time almost_24_hours_later = shift_forward +
+                                 TimeDelta::FromHours(24) -
+                                 TimeDelta::FromMicroseconds(1);
+    VisitRow forward_2(1, almost_24_hours_later, 0, standard_transition, 0);
+    forward_2.visit_id = 13;
+    AddVisit(&forward_2, SOURCE_BROWSED);
+
+    EXPECT_TRUE(GetHistoryCount(shift_forward,
+                                shift_forward + TimeDelta::FromHours(24),
+                                &result));
+    EXPECT_EQ(2, result);
+  }
+}
+
 }  // namespace history
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index 1489c79..9943a00b 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -117,8 +117,6 @@
     "web_cookie_jar_impl.h",
     "web_graphics_context_3d_command_buffer_impl.cc",
     "web_graphics_context_3d_command_buffer_impl.h",
-    "web_layer_impl.cc",
-    "web_layer_impl.h",
     "web_layer_tree_view_impl.cc",
     "web_layer_tree_view_impl.h",
     "web_mime_registry_impl.cc",
@@ -166,7 +164,6 @@
     "//media/mojo",
     "//mojo/application/public/cpp",
     "//mojo/application/public/interfaces",
-    "//mojo/cc",
     "//mojo/common",
     "//mojo/converters/surfaces",
     "//mojo/gles2:headers",
@@ -216,7 +213,7 @@
 
   data_deps = [
     "//components/clipboard",
-    "//components/mus",
+    "//components/mus/vm:lib",
     "//mojo/services/network:network",
     "//mojo/services/tracing",
   ]
@@ -362,7 +359,7 @@
 
   data_deps = [
     ":html_viewer",
-    "//components/mus",
+    "//components/mus/vm:lib",
   ]
 
   if (is_linux && !is_android) {
diff --git a/components/html_viewer/html_document.cc b/components/html_viewer/html_document.cc
index 88f1ae01..1d976f7 100644
--- a/components/html_viewer/html_document.cc
+++ b/components/html_viewer/html_document.cc
@@ -18,9 +18,9 @@
 #include "components/html_viewer/html_frame_tree_manager.h"
 #include "components/html_viewer/test_html_viewer_impl.h"
 #include "components/html_viewer/web_url_loader_impl.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/cpp/view.h"
 #include "components/mus/public/cpp/view_tree_connection.h"
+#include "components/mus/vm/ids.h"
 #include "mojo/application/public/cpp/application_impl.h"
 #include "mojo/application/public/cpp/connect.h"
 #include "mojo/application/public/interfaces/shell.mojom.h"
@@ -185,7 +185,7 @@
   web_request.setURL(url);
   web_request.setExtraData(extra_data.release());
 
-  frame_->web_frame()->toWebLocalFrame()->loadRequest(web_request);
+  frame_->LoadRequest(web_request);
 }
 
 HTMLDocument::BeforeLoadCache* HTMLDocument::GetBeforeLoadCache() {
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc
index edaed4f2..19be8ee 100644
--- a/components/html_viewer/html_frame.cc
+++ b/components/html_viewer/html_frame.cc
@@ -12,6 +12,8 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/thread_task_runner_handle.h"
+#include "cc/blink/web_layer_impl.h"
+#include "cc/surfaces/surface_id.h"
 #include "components/html_viewer/ax_provider_impl.h"
 #include "components/html_viewer/blink_basic_type_converters.h"
 #include "components/html_viewer/blink_input_events_type_converters.h"
@@ -28,14 +30,13 @@
 #include "components/html_viewer/media_factory.h"
 #include "components/html_viewer/stats_collection_controller.h"
 #include "components/html_viewer/touch_handler.h"
-#include "components/html_viewer/web_layer_impl.h"
 #include "components/html_viewer/web_layer_tree_view_impl.h"
 #include "components/html_viewer/web_storage_namespace_impl.h"
 #include "components/html_viewer/web_url_loader_impl.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/cpp/scoped_view_ptr.h"
 #include "components/mus/public/cpp/view.h"
 #include "components/mus/public/cpp/view_tree_connection.h"
+#include "components/mus/vm/ids.h"
 #include "mojo/application/public/cpp/application_impl.h"
 #include "mojo/application/public/cpp/connect.h"
 #include "mojo/application/public/interfaces/shell.mojom.h"
@@ -102,6 +103,17 @@
   return (iter == frame->parent()->children().begin()) ? nullptr : *(--iter);
 }
 
+// See surface_layer.h for a description of this callback.
+void SatisfyCallback(cc::SurfaceSequence sequence) {
+  // TODO(fsamuel): Implement this.
+}
+
+// See surface_layer.h for a description of this callback.
+void RequireCallback(cc::SurfaceId surface_id,
+                     cc::SurfaceSequence sequence) {
+  // TODO(fsamuel): Implement this.
+}
+
 }  // namespace
 
 HTMLFrame::HTMLFrame(CreateParams* params)
@@ -111,6 +123,7 @@
       id_(params->id),
       web_frame_(nullptr),
       delegate_(params->delegate),
+      pending_navigation_(false),
       weak_factory_(this) {
   if (parent_)
     parent_->children_.push_back(this);
@@ -257,6 +270,16 @@
   return false;
 }
 
+void HTMLFrame::LoadRequest(const blink::WebURLRequest& request) {
+  DCHECK(IsLocal());
+
+  DVLOG(2) << "HTMLFrame::LoadRequest this=" << this << " id=" << id_
+           << " URL=" << GURL(request.url());
+
+  pending_navigation_ = false;
+  web_frame_->toWebLocalFrame()->loadRequest(request);
+}
+
 HTMLFrame::~HTMLFrame() {
   DVLOG(2) << "~HTMLFrame this=" << this << " id=" << id_;
 
@@ -362,14 +385,28 @@
     return blink::WebNavigationPolicyCurrentTab;
   }
 
-  // Ask the Frame to handle the navigation. By returning
-  // WebNavigationPolicyIgnore the load is suppressed.
+  // Ask the Frame to handle the navigation. Returning
+  // WebNavigationPolicyHandledByClient to inform blink that the navigation is
+  // being handled.
+  DVLOG(2) << "HTMLFrame::decidePolicyForNavigation calls "
+           << "Frame::RequestNavigate this=" << this << " id=" << id_
+           << " URL=" << GURL(info.urlRequest.url());
+
   mojo::URLRequestPtr url_request = mojo::URLRequest::From(info.urlRequest);
   server_->RequestNavigate(
       WebNavigationPolicyToNavigationTarget(info.defaultPolicy), id_,
       url_request.Pass());
 
-  return blink::WebNavigationPolicyIgnore;
+  // TODO(yzshen): crbug.com/532556 If the server side drops the request,
+  // this frame will be in permenant-loading state. We should send a
+  // notification to mark this frame as not loading in that case. We also need
+  // to better keep track of multiple pending navigations.
+  pending_navigation_ = true;
+  return blink::WebNavigationPolicyHandledByClient;
+}
+
+bool HTMLFrame::hasPendingNavigation(blink::WebLocalFrame* frame) {
+  return pending_navigation_;
 }
 
 void HTMLFrame::didHandleOnloadEvents(blink::WebLocalFrame* frame) {
@@ -510,10 +547,9 @@
       return frame->server_.get();
   }
 
-  // No local root. This means we're a remote frame with no local frame
-  // ancestors. Use the server Frame from the local root of the
-  // HTMLFrameTreeManager.
-  return frame_tree_manager_->local_root_->server_.get();
+  // We're a remote frame with no local frame ancestors. Use the server Frame
+  // from the local frame of the HTMLFrameTreeManager.
+  return frame_tree_manager_->local_frame_->server_.get();
 }
 
 void HTMLFrame::SetView(mus::View* view) {
@@ -567,19 +603,28 @@
   // swap() ends up calling us back and we then close the frame, which deletes
   // it.
   web_frame_->swap(remote_frame);
-  // TODO(sky): this isn't quite right, but WebLayerImpl is temporary.
   if (owned_view_) {
-    web_layer_.reset(
-        new WebLayerImpl(owned_view_->view(),
-                         global_state()->device_pixel_ratio()));
+    surface_layer_ =
+          cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
+                                   base::Bind(&SatisfyCallback),
+                                   base::Bind(&RequireCallback));
+    surface_layer_->SetSurfaceId(
+        cc::SurfaceId(owned_view_->view()->id()),
+        global_state()->device_pixel_ratio(),
+        owned_view_->view()->bounds().To<gfx::Rect>().size());
+
+    web_layer_.reset(new cc_blink::WebLayerImpl(surface_layer_));
   }
   remote_frame->setRemoteWebLayer(web_layer_.get());
   remote_frame->setReplicatedName(state_.name);
   remote_frame->setReplicatedOrigin(state_.origin);
   remote_frame->setReplicatedSandboxFlags(state_.sandbox_flags);
+
   // Tell the frame that it is actually loading. This prevents its parent
   // from prematurely dispatching load event.
   remote_frame->didStartLoading();
+  pending_navigation_ = false;
+
   web_frame_ = remote_frame;
   SetView(nullptr);
   server_.reset();
@@ -748,20 +793,6 @@
   serialized_script_value = blink::WebSerializedScriptValue::fromString(
       serialized_event->data.To<blink::WebString>());
 
-  blink::WebMessagePortChannelArray channels;
-
-  // Create an event with the message.  The next-to-last parameter to
-  // initMessageEvent is the last event ID, which is not used with postMessage.
-  blink::WebDOMEvent event =
-      target_web_frame->document().createEvent("MessageEvent");
-  blink::WebDOMMessageEvent msg_event = event.to<blink::WebDOMMessageEvent>();
-  msg_event.initMessageEvent(
-      "message",
-      // |canBubble| and |cancellable| are always false
-      false, false, serialized_script_value,
-      serialized_event->source_origin.To<blink::WebString>(),
-      source->web_frame_, target_web_frame->document(), "", channels);
-
   // We must pass in the target_origin to do the security check on this side,
   // since it may have changed since the original postMessage call was made.
   blink::WebSecurityOrigin target_origin;
@@ -769,17 +800,37 @@
     target_origin = blink::WebSecurityOrigin::createFromString(
         serialized_event->target_origin.To<blink::WebString>());
   }
+
+  // TODO(esprehn): Shouldn't this also fill in channels like RenderFrameImpl?
+  blink::WebMessagePortChannelArray channels;
+  blink::WebDOMMessageEvent msg_event(serialized_script_value,
+      serialized_event->source_origin.To<blink::WebString>(),
+      source->web_frame_, target_web_frame->document(), channels);
+
   target_web_frame->dispatchMessageEventWithOriginCheck(target_origin,
                                                         msg_event);
 }
 
 void HTMLFrame::OnWillNavigate(const mojo::String& origin,
                                const OnWillNavigateCallback& callback) {
+  bool should_swap = true;
+
+  if (this == frame_tree_manager_->local_frame_) {
+    HTMLFrame* new_local_frame = frame_tree_manager_->FindNewLocalFrame();
+    if (!new_local_frame) {
+      // All local frames are descendants of |this|. In this case, the whole
+      // frame tree in the current process is going to be deleted very soon. We
+      // don't have to swap.
+      should_swap = false;
+    } else {
+      frame_tree_manager_->local_frame_ = new_local_frame;
+    }
+  }
+
   DVLOG(2) << "HTMLFrame::OnWillNavigate this=" << this << " id=" << id_
-           << " local=" << IsLocal() << " will_swap="
-           << (IsLocal() && this != frame_tree_manager_->local_root_);
+           << " local=" << IsLocal() << " should_swap=" << should_swap;
   callback.Run();
-  if (IsLocal() && this != frame_tree_manager_->local_root_) {
+  if (should_swap) {
     SwapToRemote();
     const blink::WebSecurityOrigin security_origin(
         blink::WebSecurityOrigin::createFromString(
@@ -864,8 +915,25 @@
   NOTIMPLEMENTED();
 }
 
-void HTMLFrame::forwardInputEvent(const blink::WebInputEvent* event) {
-  NOTIMPLEMENTED();
+void HTMLFrame::frameRectsChanged(const blink::WebRect& frame_rect) {
+  // Only the owner of view can update its size.
+  if (!owned_view_)
+    return;
+
+  const gfx::Rect rect_in_dip(frame_rect.x, frame_rect.y, frame_rect.width,
+                              frame_rect.height);
+  const gfx::Rect rect_in_pixels(gfx::ConvertRectToPixel(
+      global_state()->device_pixel_ratio(), rect_in_dip));
+  const mojo::RectPtr mojo_rect_in_pixels(mojo::Rect::From(rect_in_pixels));
+  owned_view_->view()->SetBounds(*mojo_rect_in_pixels);
+
+  if (!surface_layer_)
+    return;
+
+  surface_layer_->SetSurfaceId(
+      cc::SurfaceId(owned_view_->view()->id()),
+      global_state()->device_pixel_ratio(),
+      owned_view_->view()->bounds().To<gfx::Rect>().size());
 }
 
 }  // namespace mojo
diff --git a/components/html_viewer/html_frame.h b/components/html_viewer/html_frame.h
index 4f7de6c..fef256a 100644
--- a/components/html_viewer/html_frame.h
+++ b/components/html_viewer/html_frame.h
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
+#include "cc/layers/surface_layer.h"
 #include "components/html_viewer/html_frame_tree_manager.h"
 #include "components/html_viewer/replicated_frame_state.h"
 #include "components/mus/public/cpp/view_observer.h"
@@ -146,6 +147,8 @@
   // Returns true if this or one of the frames descendants is local.
   bool HasLocalDescendant() const;
 
+  void LoadRequest(const blink::WebURLRequest& request);
+
  protected:
   virtual ~HTMLFrame();
 
@@ -166,6 +169,7 @@
   virtual blink::WebCookieJar* cookieJar(blink::WebLocalFrame* frame);
   virtual blink::WebNavigationPolicy decidePolicyForNavigation(
       const NavigationPolicyInfo& info);
+  virtual bool hasPendingNavigation(blink::WebLocalFrame* frame);
   virtual void didHandleOnloadEvents(blink::WebLocalFrame* frame);
   virtual void didAddMessageToConsole(const blink::WebConsoleMessage& message,
                                       const blink::WebString& source_name,
@@ -288,7 +292,7 @@
   virtual void navigate(const blink::WebURLRequest& request,
                         bool should_replace_current_entry);
   virtual void reload(bool ignore_cache, bool is_client_redirect);
-  virtual void forwardInputEvent(const blink::WebInputEvent* event);
+  virtual void frameRectsChanged(const blink::WebRect& frame_rect);
 
   HTMLFrameTreeManager* frame_tree_manager_;
   HTMLFrame* parent_;
@@ -305,6 +309,7 @@
   scoped_ptr<TouchHandler> touch_handler_;
 
   scoped_ptr<cc_blink::WebLayerImpl> web_layer_;
+  scoped_refptr<cc::SurfaceLayer> surface_layer_;
 
   HTMLFrameDelegate* delegate_;
   scoped_ptr<mojo::Binding<web_view::mojom::FrameClient>> frame_client_binding_;
@@ -330,6 +335,10 @@
 
   scoped_ptr<DevToolsAgentImpl> devtools_agent_;
 
+  // A navigation request has been sent to the frame server side, and we haven't
+  // received response to it.
+  bool pending_navigation_;
+
   base::WeakPtrFactory<HTMLFrame> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(HTMLFrame);
diff --git a/components/html_viewer/html_frame_tree_manager.cc b/components/html_viewer/html_frame_tree_manager.cc
index 6d8d12e..2cefb66 100644
--- a/components/html_viewer/html_frame_tree_manager.cc
+++ b/components/html_viewer/html_frame_tree_manager.cc
@@ -108,8 +108,7 @@
   if (!frame_tree) {
     frame_tree = new HTMLFrameTreeManager(global_state);
     frame_tree->Init(delegate, view, frame_data, change_id);
-    if (frame_data[0]->frame_id == view->id())
-      (*instances_)[frame_data[0]->frame_id] = frame_tree;
+    (*instances_)[frame_data[0]->frame_id] = frame_tree;
   } else if (view_connect_type ==
              web_view::mojom::VIEW_CONNECT_TYPE_USE_EXISTING) {
     HTMLFrame* existing_frame = frame_tree->root_->FindFrame(view_id);
@@ -179,29 +178,39 @@
 }
 
 void HTMLFrameTreeManager::OnFrameDestroyed(HTMLFrame* frame) {
-  if (frame == root_)
-    root_ = nullptr;
-
-  if (frame == local_root_)
-    local_root_ = nullptr;
-
   if (!in_process_on_frame_removed_)
     pending_remove_ids_.insert(frame->id());
 
-  if (!local_root_ || !local_root_->HasLocalDescendant())
+  if (frame == root_) {
+    // If |root_| is removed before |local_frame_|, we don't have a way to
+    // select a new local frame when |local_frame_| is removed. On the other
+    // hand, it is impossible to remove |root_| after all local frames are gone,
+    // because by that time this object has already been deleted.
+    CHECK_EQ(root_, local_frame_);
+    root_ = nullptr;
+  }
+
+  if (frame != local_frame_)
+    return;
+
+  // |local_frame_| is being removed. We need to find out whether we have local
+  // frames that are not descendants of |local_frame_|, and if yes select a new
+  // |local_frame_|.
+  local_frame_ = FindNewLocalFrame();
+  if (!local_frame_)
     delete this;
 }
 
 HTMLFrameTreeManager::HTMLFrameTreeManager(GlobalState* global_state)
     : global_state_(global_state),
       root_(nullptr),
-      local_root_(nullptr),
+      local_frame_(nullptr),
       change_id_(0u),
       in_process_on_frame_removed_(false),
       weak_factory_(this) {}
 
 HTMLFrameTreeManager::~HTMLFrameTreeManager() {
-  DCHECK(!root_ || !local_root_);
+  DCHECK(!local_frame_);
   RemoveFromInstances();
 
   FOR_EACH_OBSERVER(HTMLFrameTreeManagerObserver, observers_,
@@ -215,9 +224,9 @@
     uint32_t change_id) {
   change_id_ = change_id;
   root_ = BuildFrameTree(delegate, frame_data, local_view->id(), local_view);
-  local_root_ = root_->FindFrame(local_view->id());
-  CHECK(local_root_);
-  local_root_->UpdateFocus();
+  local_frame_ = root_->FindFrame(local_view->id());
+  CHECK(local_frame_);
+  local_frame_->UpdateFocus();
 }
 
 HTMLFrame* HTMLFrameTreeManager::BuildFrameTree(
@@ -269,7 +278,7 @@
     return false;
 
   // We only process changes for the topmost local root.
-  if (source != local_root_)
+  if (source != local_frame_)
     return false;
 
   // Update the id as the change is going to be applied (or we can assume it
@@ -360,7 +369,7 @@
     uint32_t frame_id,
     const mojo::String& name,
     mojo::Array<uint8_t> new_data) {
-  if (source != local_root_)
+  if (source != local_frame_)
     return;
 
   HTMLFrame* frame = root_->FindFrame(frame_id);
@@ -368,4 +377,31 @@
     frame->SetValueFromClientProperty(name, new_data.Pass());
 }
 
+HTMLFrame* HTMLFrameTreeManager::FindNewLocalFrame() {
+  HTMLFrame* new_local_frame = nullptr;
+
+  if (root_) {
+    std::queue<HTMLFrame*> nodes;
+    nodes.push(root_);
+
+    while (!nodes.empty()) {
+      HTMLFrame* node = nodes.front();
+      nodes.pop();
+
+      if (node == local_frame_)
+        continue;
+
+      if (node->IsLocal()) {
+        new_local_frame = node;
+        break;
+      }
+
+      for (const auto& child : node->children())
+        nodes.push(child);
+    }
+  }
+
+  return new_local_frame;
+}
+
 }  // namespace mojo
diff --git a/components/html_viewer/html_frame_tree_manager.h b/components/html_viewer/html_frame_tree_manager.h
index 55ee53a..8ece76d 100644
--- a/components/html_viewer/html_frame_tree_manager.h
+++ b/components/html_viewer/html_frame_tree_manager.h
@@ -95,7 +95,7 @@
 
   // Each HTMLFrame delegates FrameClient methods to the HTMLFrameTreeManager
   // the frame is in. HTMLFrameTreeManager only responds to changes from the
-  // |local_root_| (this is because each FrameClient sees the same change, and
+  // |local_frame_| (this is because each FrameClient sees the same change, and
   // a change only need be processed once).
   void ProcessOnFrameAdded(HTMLFrame* source,
                            uint32_t change_id,
@@ -108,15 +108,22 @@
                                            const mojo::String& name,
                                            mojo::Array<uint8_t> new_data);
 
+  // Finds a new local frame which satisfies:
+  // - it is not a descendant of |local_frame_|;
+  // - it is the highest local frame or one of the highest local frames if
+  //   there are multiple.
+  HTMLFrame* FindNewLocalFrame();
+
   static TreeMap* instances_;
 
   GlobalState* global_state_;
 
   HTMLFrame* root_;
 
-  // The |local_root_| is the HTMLFrame that is the highest frame that is
-  // local.
-  HTMLFrame* local_root_;
+  // The |local_frame_| is the HTMLFrame that is the highest frame that is
+  // local. Please note that it is not necessarily the ancestor of all local
+  // frames.
+  HTMLFrame* local_frame_;
 
   uint32_t change_id_;
 
diff --git a/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc b/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc
index 7b01690..f9e4c5bc 100644
--- a/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc
+++ b/components/html_viewer/web_graphics_context_3d_command_buffer_impl.cc
@@ -6,10 +6,10 @@
 
 #include "components/html_viewer/blink_basic_type_converters.h"
 #include "components/html_viewer/global_state.h"
+#include "components/mus/public/cpp/context_provider.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "mojo/application/public/cpp/application_impl.h"
-#include "mojo/cc/context_provider_mojo.h"
 #include "mojo/gles2/gles2_context.h"
 #include "mojo/gpu/mojo_gles2_impl_autogen.h"
 #include "third_party/mojo/src/mojo/public/cpp/environment/environment.h"
diff --git a/components/html_viewer/web_layer_impl.cc b/components/html_viewer/web_layer_impl.cc
deleted file mode 100644
index 6b56f93..0000000
--- a/components/html_viewer/web_layer_impl.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/html_viewer/web_layer_impl.h"
-
-#include "base/bind.h"
-#include "cc/layers/layer.h"
-#include "components/mus/public/cpp/view.h"
-#include "ui/gfx/geometry/dip_util.h"
-#include "ui/mojo/geometry/geometry.mojom.h"
-
-using blink::WebFloatPoint;
-using blink::WebSize;
-
-namespace html_viewer {
-
-namespace {
-
-// See surface_layer.h for a description of this callback.
-void SatisfyCallback(cc::SurfaceSequence sequence) {
-  // TODO(fsamuel): Implement this.
-}
-
-// See surface_layer.h for a description of this callback.
-void RequireCallback(cc::SurfaceId surface_id,
-                     cc::SurfaceSequence sequence) {
-  // TODO(fsamuel): Implement this.
-}
-
-}
-
-WebLayerImpl::WebLayerImpl(mus::View* view, float device_pixel_ratio)
-    : cc_blink::WebLayerImpl(
-          cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
-                                   base::Bind(&SatisfyCallback),
-                                   base::Bind(&RequireCallback))),
-      view_(view),
-      device_pixel_ratio_(device_pixel_ratio) {}
-
-WebLayerImpl::~WebLayerImpl() {
-}
-
-void WebLayerImpl::setBounds(const WebSize& size) {
-  gfx::Size size_in_pixels =
-      gfx::ScaleToCeiledSize(gfx::Size(size), device_pixel_ratio_);
-  static_cast<cc::SurfaceLayer*>(layer())->
-      SetSurfaceId(cc::SurfaceId(view_->id()),
-                   device_pixel_ratio_, size_in_pixels);
-  cc_blink::WebLayerImpl::setBounds(size);
-}
-
-}  // namespace html_viewer
diff --git a/components/html_viewer/web_layer_impl.h b/components/html_viewer/web_layer_impl.h
deleted file mode 100644
index e245d1f7..0000000
--- a/components/html_viewer/web_layer_impl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_HTML_VIEWER_WEB_LAYER_IMPL_H_
-#define COMPONENTS_HTML_VIEWER_WEB_LAYER_IMPL_H_
-
-#include <utility>
-
-#include "cc/blink/web_layer_impl.h"
-#include "cc/layers/surface_layer.h"
-
-namespace mus {
-class View;
-}
-
-namespace html_viewer {
-
-class WebLayerImpl : public cc_blink::WebLayerImpl {
- public:
-  WebLayerImpl(mus::View* view, float device_pixel_ratio);
-  ~WebLayerImpl() override;
-
-  // WebLayer implementation.
-  void setBounds(const blink::WebSize& bounds) override;
-
- private:
-  mus::View* view_;
-  const float device_pixel_ratio_;
-  scoped_refptr<cc::SurfaceLayer> layer_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebLayerImpl);
-};
-
-}  // namespace html_viewer
-
-#endif  // COMPONENTS_HTML_VIEWER_WEB_LAYER_IMPL_H_
diff --git a/components/html_viewer/web_layer_tree_view_impl.cc b/components/html_viewer/web_layer_tree_view_impl.cc
index b4f1cc4..2ee1c75 100644
--- a/components/html_viewer/web_layer_tree_view_impl.cc
+++ b/components/html_viewer/web_layer_tree_view_impl.cc
@@ -10,9 +10,9 @@
 #include "cc/output/begin_frame_args.h"
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/trees/layer_tree_host.h"
+#include "components/mus/public/cpp/context_provider.h"
+#include "components/mus/public/cpp/output_surface.h"
 #include "components/mus/public/cpp/view.h"
-#include "mojo/cc/context_provider_mojo.h"
-#include "mojo/cc/output_surface_mojo.h"
 #include "mojo/converters/surfaces/surfaces_type_converters.h"
 #include "third_party/WebKit/public/web/WebWidget.h"
 #include "ui/gfx/buffer_types.h"
@@ -66,9 +66,9 @@
     mojo::CommandBufferPtr cb;
     gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb));
     scoped_refptr<cc::ContextProvider> context_provider(
-        new mojo::ContextProviderMojo(cb.PassInterface().PassHandle()));
+        new mus::ContextProvider(cb.PassInterface().PassHandle()));
     output_surface_.reset(
-        new mojo::OutputSurfaceMojo(context_provider, view_->RequestSurface()));
+        new mus::OutputSurface(context_provider, view_->RequestSurface()));
   }
   layer_tree_host_->SetLayerTreeHostClientReady();
 }
diff --git a/components/html_viewer/web_layer_tree_view_impl.h b/components/html_viewer/web_layer_tree_view_impl.h
index 3a48bc3..ed16fab 100644
--- a/components/html_viewer/web_layer_tree_view_impl.h
+++ b/components/html_viewer/web_layer_tree_view_impl.h
@@ -11,8 +11,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "cc/trees/layer_tree_host_client.h"
+#include "components/mus/public/cpp/output_surface.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
-#include "mojo/cc/output_surface_mojo.h"
 #include "third_party/WebKit/public/platform/WebLayerTreeView.h"
 
 namespace base {
diff --git a/components/infobars/core/infobar_delegate.cc b/components/infobars/core/infobar_delegate.cc
index 866e1954..b22a685 100644
--- a/components/infobars/core/infobar_delegate.cc
+++ b/components/infobars/core/infobar_delegate.cc
@@ -47,8 +47,9 @@
     gfx::VectorIconId vector_id = GetVectorIconId();
     if (vector_id != gfx::VectorIconId::VECTOR_ICON_NONE) {
       return gfx::Image(gfx::CreateVectorIcon(
-          vector_id, 16,
-          GetInfoBarType() == WARNING_TYPE ? gfx::kAmber : gfx::kGoogleBlue));
+          vector_id, 18,
+          GetInfoBarType() == WARNING_TYPE ? SkColorSetRGB(0xFF, 0x67, 0)
+                                           : gfx::kGoogleBlue));
     }
   }
 #endif
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index 9d6ba770..774c215 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -86,7 +86,7 @@
   virtual int GetIconId() const;
 
   // Returns the vector icon identifier to be shown for this InfoBar. This will
-  // take precedent over GetIconId() (although typically only one of the two
+  // take precedence over GetIconId() (although typically only one of the two
   // should be defined for any given infobar).
   virtual gfx::VectorIconId GetVectorIconId() const;
 
diff --git a/components/infobars/core/simple_alert_infobar_delegate.cc b/components/infobars/core/simple_alert_infobar_delegate.cc
index 7385fd6..ce84d8f 100644
--- a/components/infobars/core/simple_alert_infobar_delegate.cc
+++ b/components/infobars/core/simple_alert_infobar_delegate.cc
@@ -12,22 +12,24 @@
 void SimpleAlertInfoBarDelegate::Create(
     infobars::InfoBarManager* infobar_manager,
     int icon_id,
+    gfx::VectorIconId vector_icon_id,
     const base::string16& message,
     bool auto_expire) {
-  infobar_manager->AddInfoBar(
-      infobar_manager->CreateConfirmInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
-          new SimpleAlertInfoBarDelegate(icon_id, message, auto_expire))));
+  infobar_manager->AddInfoBar(infobar_manager->CreateConfirmInfoBar(
+      scoped_ptr<ConfirmInfoBarDelegate>(new SimpleAlertInfoBarDelegate(
+          icon_id, vector_icon_id, message, auto_expire))));
 }
 
 SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate(
     int icon_id,
+    gfx::VectorIconId vector_icon_id,
     const base::string16& message,
     bool auto_expire)
     : ConfirmInfoBarDelegate(),
       icon_id_(icon_id),
+      vector_icon_id_(vector_icon_id),
       message_(message),
-      auto_expire_(auto_expire) {
-}
+      auto_expire_(auto_expire) {}
 
 SimpleAlertInfoBarDelegate::~SimpleAlertInfoBarDelegate() {
 }
@@ -36,6 +38,10 @@
   return icon_id_;
 }
 
+gfx::VectorIconId SimpleAlertInfoBarDelegate::GetVectorIconId() const {
+  return vector_icon_id_;
+}
+
 bool SimpleAlertInfoBarDelegate::ShouldExpire(
     const NavigationDetails& details) const {
   return auto_expire_ && ConfirmInfoBarDelegate::ShouldExpire(details);
diff --git a/components/infobars/core/simple_alert_infobar_delegate.h b/components/infobars/core/simple_alert_infobar_delegate.h
index b52f5df..f2cd454 100644
--- a/components/infobars/core/simple_alert_infobar_delegate.h
+++ b/components/infobars/core/simple_alert_infobar_delegate.h
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
+#include "ui/gfx/vector_icons_public.h"
 
 namespace infobars {
 class InfoBarManager;
@@ -17,25 +18,30 @@
 class SimpleAlertInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   // Creates a simple alert infobar and delegate and adds the infobar to
-  // |infobar_manager|. |icon_id| may be kNoIconID if no icon is shown.
+  // |infobar_manager|. If |vector_icon_id| is not VECTOR_ICON_NONE, it will be
+  // shown; otherwise, |icon_id| (if present) will be used as the icon.
   static void Create(infobars::InfoBarManager* infobar_manager,
                      int icon_id,
+                     gfx::VectorIconId vector_icon_id,
                      const base::string16& message,
                      bool auto_expire);
 
  private:
   SimpleAlertInfoBarDelegate(int icon_id,
+                             gfx::VectorIconId vector_icon_id,
                              const base::string16& message,
                              bool auto_expire);
   ~SimpleAlertInfoBarDelegate() override;
 
   // ConfirmInfoBarDelegate:
   int GetIconId() const override;
+  gfx::VectorIconId GetVectorIconId() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
   base::string16 GetMessageText() const override;
   int GetButtons() const override;
 
   const int icon_id_;
+  gfx::VectorIconId vector_icon_id_;
   base::string16 message_;
   bool auto_expire_;  // Should it expire automatically on navigation?
 
diff --git a/components/metrics/metrics_pref_names.cc b/components/metrics/metrics_pref_names.cc
index 3cdebab..a5ad6a52 100644
--- a/components/metrics/metrics_pref_names.cc
+++ b/components/metrics/metrics_pref_names.cc
@@ -43,6 +43,11 @@
 // client id and low entropy source should be reset.
 const char kMetricsResetIds[] = "user_experience_metrics.reset_metrics_ids";
 
+// Boolean that specifies whether or not crash reporting and metrics reporting
+// are sent over the network for analysis.
+const char kMetricsReportingEnabled[] =
+    "user_experience_metrics.reporting_enabled";
+
 // Date/time when the user opted in to UMA and generated the client id for the
 // very first time (local machine time, stored as a 64-bit time_t value).
 const char kMetricsReportingEnabledTimestamp[] =
diff --git a/components/metrics/metrics_pref_names.h b/components/metrics/metrics_pref_names.h
index f4456a56..8118a597 100644
--- a/components/metrics/metrics_pref_names.h
+++ b/components/metrics/metrics_pref_names.h
@@ -17,6 +17,11 @@
 extern const char kMetricsMachineId[];
 extern const char kMetricsOngoingLogs[];
 extern const char kMetricsResetIds[];
+
+// For finding out whether metrics and crash reporting is enabled use
+// ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled() instead of
+// reading this pref directly.
+extern const char kMetricsReportingEnabled[];
 extern const char kMetricsReportingEnabledTimestamp[];
 extern const char kMetricsSessionID[];
 extern const char kStabilityBreakpadRegistrationSuccess[];
diff --git a/components/metrics/metrics_service_accessor.cc b/components/metrics/metrics_service_accessor.cc
index 515ce08..ec34c7f 100644
--- a/components/metrics/metrics_service_accessor.cc
+++ b/components/metrics/metrics_service_accessor.cc
@@ -5,12 +5,31 @@
 #include "components/metrics/metrics_service_accessor.h"
 
 #include "components/metrics/metrics_service.h"
+#include "components/variations/metrics_util.h"
 
 namespace metrics {
 
 // static
 bool MetricsServiceAccessor::RegisterSyntheticFieldTrial(
     MetricsService* metrics_service,
+    const std::string& trial_name,
+    const std::string& group_name) {
+  return RegisterSyntheticFieldTrialWithNameAndGroupHash(
+      metrics_service, HashName(trial_name), HashName(group_name));
+}
+
+// static
+bool MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameHash(
+    MetricsService* metrics_service,
+    uint32_t trial_name_hash,
+    const std::string& group_name) {
+  return RegisterSyntheticFieldTrialWithNameAndGroupHash(
+      metrics_service, trial_name_hash, HashName(group_name));
+}
+
+// static
+bool MetricsServiceAccessor::RegisterSyntheticFieldTrialWithNameAndGroupHash(
+    MetricsService* metrics_service,
     uint32_t trial_name_hash,
     uint32_t group_name_hash) {
   if (!metrics_service)
diff --git a/components/metrics/metrics_service_accessor.h b/components/metrics/metrics_service_accessor.h
index 33315a9..92f253f 100644
--- a/components/metrics/metrics_service_accessor.h
+++ b/components/metrics/metrics_service_accessor.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_METRICS_METRICS_SERVICE_ACCESSOR_H_
 
 #include <stdint.h>
+#include <string>
 
 #include "base/macros.h"
 
@@ -22,11 +23,29 @@
   // disallow instantiation.
   MetricsServiceAccessor() {}
 
-  // Registers the specified synthetic field trial (identified by a hash of the
-  // trial name and group name) with |metrics_service|, if the service is not
-  // NULL, returning true on success.
+  // Registers a field trial name and group with |metrics_service| (if not
+  // null), to be used to annotate a UMA report with a particular configuration
+  // state. A UMA report will be annotated with this trial group if and only if
+  // all events in the report were created after the trial is registered. Only
+  // one group name may be registered at a time for a given trial name. Only the
+  // last group name that is registered for a given trial name will be recorded.
+  // The values passed in must not correspond to any real field trial in the
+  // code. Returns true on success.
   // See the comment on MetricsService::RegisterSyntheticFieldTrial for details.
-  static bool RegisterSyntheticFieldTrial(
+  static bool RegisterSyntheticFieldTrial(MetricsService* metrics_service,
+                                          const std::string& trial_name,
+                                          const std::string& group_name);
+
+  // Same as RegisterSyntheticFieldTrial above, but takes in the trial name as a
+  // hash rather than computing the hash from the string.
+  static bool RegisterSyntheticFieldTrialWithNameHash(
+      MetricsService* metrics_service,
+      uint32_t trial_name_hash,
+      const std::string& group_name);
+
+  // Same as RegisterSyntheticFieldTrial above, but takes in the trial and group
+  // names as hashes rather than computing those hashes from the strings.
+  static bool RegisterSyntheticFieldTrialWithNameAndGroupHash(
       MetricsService* metrics_service,
       uint32_t trial_name_hash,
       uint32_t group_name_hash);
diff --git a/components/mus/BUILD.gn b/components/mus/BUILD.gn
index 956f8ff0..098bd30 100644
--- a/components/mus/BUILD.gn
+++ b/components/mus/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
+# Copyright 2015 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -40,174 +40,26 @@
 
 source_set("lib") {
   sources = [
-    "access_policy.h",
-    "access_policy_delegate.h",
-    "client_connection.cc",
-    "client_connection.h",
-    "connection_manager.cc",
-    "connection_manager.h",
-    "connection_manager_delegate.h",
-    "default_access_policy.cc",
-    "default_access_policy.h",
-    "display_manager.cc",
-    "display_manager.h",
-    "display_manager_delegate.h",
-    "display_manager_factory.h",
-    "event_dispatcher.cc",
-    "event_dispatcher.h",
-    "focus_controller.cc",
-    "focus_controller.h",
-    "focus_controller_delegate.h",
-    "gesture_manager.cc",
-    "gesture_manager.h",
-    "gesture_manager_delegate.h",
     "mus_app.cc",
     "mus_app.h",
-    "server_view.cc",
-    "server_view.h",
-    "server_view_delegate.h",
-    "server_view_drawn_tracker.cc",
-    "server_view_drawn_tracker.h",
-    "server_view_drawn_tracker_observer.h",
-    "server_view_observer.h",
-    "view_coordinate_conversions.cc",
-    "view_coordinate_conversions.h",
-    "view_locator.cc",
-    "view_locator.h",
-    "view_tree_host_connection.cc",
-    "view_tree_host_connection.h",
-    "view_tree_host_delegate.h",
-    "view_tree_host_impl.cc",
-    "view_tree_host_impl.h",
-    "view_tree_impl.cc",
-    "view_tree_impl.h",
-    "window_manager_access_policy.cc",
-    "window_manager_access_policy.h",
-  ]
-
-  public_deps = [
-    "//components/mus/public/cpp",
   ]
 
   deps = [
     "//base",
     "//cc",
     "//cc/surfaces",
-    "//cc/surfaces:surface_id",
-    "//components/mus/gles2:gles2",
+    "//components/mus/gles2",
     "//components/mus/public/cpp:common",
     "//components/mus/public/interfaces",
     "//components/mus/surfaces",
+    "//components/mus/vm:lib",
     "//mojo/application/public/cpp",
     "//mojo/common:common_base",
     "//mojo/common:tracing_impl",
-    "//mojo/converters/geometry",
-    "//mojo/converters/ime",
-    "//mojo/converters/input_events",
-    "//mojo/converters/surfaces",
-    "//third_party/mojo/src/mojo/public/cpp/bindings:callback",
     "//ui/events",
-    "//ui/events/platform",
-    "//ui/gfx",
-    "//ui/gfx/geometry",
     "//ui/gl:gl",
     "//ui/gl:test_support",
-    "//ui/mojo/events:interfaces",
-    "//ui/mojo/geometry:interfaces",
     "//ui/platform_window:platform_impls",
     "//ui/platform_window:platform_window",
   ]
 }
-
-source_set("test_support") {
-  testonly = true
-
-  sources = [
-    "test_change_tracker.cc",
-    "test_change_tracker.h",
-  ]
-
-  deps = [
-    "//base",
-    "//components/mus/public/cpp",
-    "//components/mus/public/cpp:common",
-    "//components/mus/public/interfaces",
-    "//mojo/common",
-    "//third_party/mojo/src/mojo/public/cpp/bindings:bindings",
-    "//ui/mojo/geometry:interfaces",
-  ]
-}
-
-group("tests") {
-  testonly = true
-  deps = [
-    ":apptests",
-    ":view_manager_unittests",
-    "//components/mus/public/cpp/tests:mojo_view_manager_lib_unittests",
-  ]
-}
-
-test("view_manager_unittests") {
-  sources = [
-    "focus_controller_unittest.cc",
-    "gesture_manager_unittest.cc",
-    "server_view_drawn_tracker_unittest.cc",
-    "test_server_view_delegate.cc",
-    "test_server_view_delegate.h",
-    "view_coordinate_conversions_unittest.cc",
-    "view_tree_unittest.cc",
-  ]
-
-  deps = [
-    ":test_support",
-    ":lib",
-    "//base",
-    "//base/test:test_config",
-    "//components/mus/public/cpp:common",
-    "//components/mus/public/interfaces",
-    "//components/mus/surfaces",
-    "//mojo/application/public/interfaces",
-    "//mojo/converters/geometry",
-    "//mojo/converters/input_events",
-    "//mojo/converters/transform",
-    "//mojo/environment:chromium",
-    "//mojo/platform_handle",
-    "//third_party/mojo/src/mojo/edk/test:run_all_unittests",
-    "//third_party/mojo/src/mojo/public/cpp/bindings:bindings",
-    "//ui/mojo/geometry:interfaces",
-    "//ui/mojo/events:interfaces",
-    "//testing/gtest",
-    "//ui/gfx",
-    "//ui/gfx:test_support",
-    "//ui/gfx/geometry",
-  ]
-
-  if (!is_android) {  # TODO(GYP) Enable on Android when osmesa links.
-    deps += [ "//third_party/mesa:osmesa" ]
-  }
-}
-
-mojo_native_application("apptests") {
-  output_name = "mus_apptests"
-  testonly = true
-
-  sources = [
-    "view_manager_client_apptest.cc",
-    "view_tree_apptest.cc",
-  ]
-
-  deps = [
-    ":test_support",
-    "//base",
-    "//base/test:test_config",
-    "//components/mus/public/cpp",
-    "//components/mus/public/cpp/tests:test_support",
-    "//components/mus/public/interfaces",
-    "//mojo/application/public/cpp:sources",
-    "//mojo/application/public/cpp:test_support",
-    "//ui/mojo/geometry:interfaces",
-    "//ui/mojo/geometry:util",
-  ]
-
-  data_deps = [ ":mus" ]
-}
diff --git a/components/mus/event_dispatcher.cc b/components/mus/event_dispatcher.cc
deleted file mode 100644
index 548fc41..0000000
--- a/components/mus/event_dispatcher.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/mus/event_dispatcher.h"
-
-#include "components/mus/server_view.h"
-#include "components/mus/view_coordinate_conversions.h"
-#include "components/mus/view_locator.h"
-#include "components/mus/view_tree_host_impl.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/point_f.h"
-
-namespace mus {
-
-EventDispatcher::EventDispatcher(ViewTreeHostImpl* view_tree_host)
-    : view_tree_host_(view_tree_host) {}
-
-EventDispatcher::~EventDispatcher() {}
-
-void EventDispatcher::AddAccelerator(uint32_t id,
-                                     mojo::KeyboardCode keyboard_code,
-                                     mojo::EventFlags flags) {
-#if !defined(NDEBUG)
-  for (const auto& pair : accelerators_) {
-    DCHECK(pair.first != id);
-    DCHECK(pair.second.keyboard_code != keyboard_code ||
-           pair.second.flags != flags);
-  }
-#endif
-  accelerators_.insert(Entry(id, Accelerator(keyboard_code, flags)));
-}
-
-void EventDispatcher::RemoveAccelerator(uint32_t id) {
-  auto it = accelerators_.find(id);
-  DCHECK(it != accelerators_.end());
-  accelerators_.erase(it);
-}
-
-void EventDispatcher::OnEvent(mojo::EventPtr event) {
-  if (event->action == mojo::EVENT_TYPE_KEY_PRESSED &&
-      !event->key_data->is_char) {
-    uint32_t accelerator = 0u;
-    if (FindAccelerator(*event, &accelerator)) {
-      view_tree_host_->OnAccelerator(accelerator, event.Pass());
-      return;
-    }
-  }
-
-  ServerView* target = FindEventTarget(event.get());
-  if (target) {
-    // Update focus on pointer-down.
-    if (event->action == mojo::EVENT_TYPE_POINTER_DOWN)
-      view_tree_host_->SetFocusedView(target);
-    view_tree_host_->DispatchInputEventToView(target, event.Pass());
-  }
-}
-
-bool EventDispatcher::FindAccelerator(const mojo::Event& event,
-                                      uint32_t* accelerator_id) {
-  DCHECK(event.key_data);
-  for (const auto& pair : accelerators_) {
-    if (pair.second.keyboard_code == event.key_data->windows_key_code &&
-        pair.second.flags == event.flags) {
-      *accelerator_id = pair.first;
-      return true;
-    }
-  }
-  return false;
-}
-
-ServerView* EventDispatcher::FindEventTarget(mojo::Event* event) {
-  ServerView* focused_view = view_tree_host_->GetFocusedView();
-  if (event->pointer_data && event->pointer_data->location) {
-    ServerView* root = view_tree_host_->root_view();
-    const gfx::Point root_point(
-        static_cast<int>(event->pointer_data->location->x),
-        static_cast<int>(event->pointer_data->location->y));
-    ServerView* target = focused_view;
-    if (event->action == mojo::EVENT_TYPE_POINTER_DOWN || !target ||
-        !root->Contains(target)) {
-      target = FindDeepestVisibleView(root, root_point);
-      CHECK(target);
-    }
-    const gfx::PointF local_point(ConvertPointFBetweenViews(
-        root, target, gfx::PointF(event->pointer_data->location->x,
-                                  event->pointer_data->location->y)));
-    event->pointer_data->location->x = local_point.x();
-    event->pointer_data->location->y = local_point.y();
-    return target;
-  }
-
-  return focused_view;
-}
-
-}  // namespace mus
diff --git a/components/mus/gesture_manager.cc b/components/mus/gesture_manager.cc
deleted file mode 100644
index 5cedf3a..0000000
--- a/components/mus/gesture_manager.cc
+++ /dev/null
@@ -1,698 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/mus/gesture_manager.h"
-
-#include <algorithm>
-
-#include "components/mus/gesture_manager_delegate.h"
-#include "components/mus/public/cpp/keys.h"
-#include "components/mus/server_view.h"
-#include "components/mus/view_coordinate_conversions.h"
-#include "components/mus/view_locator.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/mojo/events/input_events.mojom.h"
-
-namespace mus {
-
-using Views = std::vector<const ServerView*>;
-
-namespace {
-
-GestureManager::GestureAndConnectionId MakeGestureAndConnectionId(
-    const ServerView* view,
-    uint32_t gesture_id) {
-  return (static_cast<GestureManager::GestureAndConnectionId>(
-              view->id().connection_id)
-          << 32) |
-         gesture_id;
-}
-
-// Returns the views (deepest first) that should receive touch events. This only
-// returns one view per connection. If multiple views from the same connection
-// are interested in touch events the shallowest view is returned.
-Views GetTouchTargets(const ServerView* deepest) {
-  Views result;
-  const ServerView* view = deepest;
-  while (view) {
-    if (view->properties().count(kViewManagerKeyWantsTouchEvents)) {
-      if (!result.empty() &&
-          result.back()->id().connection_id == view->id().connection_id) {
-        result.pop_back();
-      }
-      result.push_back(view);
-    }
-    view = view->parent();
-  }
-  // TODO(sky): I'm doing this until things are converted. Seems as though we
-  // shouldn't do this long term.
-  if (result.empty())
-    result.push_back(deepest);
-  return result;
-}
-
-mojo::EventPtr CloneEventForView(const mojo::Event& event,
-                                 const ServerView* view) {
-  mojo::EventPtr result(event.Clone());
-  if (event.pointer_data && event.pointer_data->location) {
-    const gfx::PointF location(event.pointer_data->location->x,
-                               event.pointer_data->location->y);
-    const gfx::PointF target_location(
-        ConvertPointFBetweenViews(view->GetRoot(), view, location));
-    result->pointer_data->location->x = target_location.x();
-    result->pointer_data->location->y = target_location.y();
-  }
-  return result.Pass();
-}
-
-}  // namespace
-
-// GestureStateChange ----------------------------------------------------------
-
-GestureStateChange::GestureStateChange()
-    : chosen_gesture(GestureManager::kInvalidGestureId) {}
-
-GestureStateChange::~GestureStateChange() {}
-
-// ViewIterator ----------------------------------------------------------------
-
-// Used to iterate over a set of views.
-class ViewIterator {
- public:
-  explicit ViewIterator(const Views& views)
-      : views_(views), current_(views_.begin()) {}
-
-  // Advances to the next view. Returns true if there are no more views (at
-  // the end).
-  bool advance() { return ++current_ != views_.end(); }
-
-  bool at_end() const { return current_ == views_.end(); }
-
-  bool empty() const { return views_.empty(); }
-
-  const ServerView* current() const { return *current_; }
-
-  void reset_to_beginning() { current_ = views_.begin(); }
-
-  void remove(const ServerView* view) {
-    Views::iterator iter = std::find(views_.begin(), views_.end(), view);
-    DCHECK(iter != views_.end());
-    if (iter == current_) {
-      current_ = views_.erase(current_);
-    } else if (!at_end()) {
-      size_t index = current_ - views_.begin();
-      if (current_ > iter)
-        index--;
-      views_.erase(iter);
-      current_ = views_.begin() + index;
-    } else {
-      views_.erase(iter);
-      current_ = views_.end();
-    }
-  }
-
-  bool contains(const ServerView* view) const {
-    return std::find(views_.begin(), views_.end(), view) != views_.end();
-  }
-
- private:
-  Views views_;
-  Views::iterator current_;
-
-  DISALLOW_COPY_AND_ASSIGN(ViewIterator);
-};
-
-// PointerAndView --------------------------------------------------------------
-
-struct GestureManager::PointerAndView {
-  PointerAndView();
-  PointerAndView(Pointer* pointer, const ServerView* view);
-
-  // Compares two PointerAndView instances based on pointer id, then view id.
-  // This is really only interesting for unit tests so that they get a known
-  // order of events.
-  bool operator<(const PointerAndView& other) const;
-
-  Pointer* pointer;
-  const ServerView* view;
-};
-
-// Gesture ---------------------------------------------------------------------
-
-// Gesture maintains the set of pointers and views it is attached to.
-class GestureManager::Gesture {
- public:
-  enum State { STATE_INITIAL, STATE_CANCELED, STATE_CHOSEN };
-
-  explicit Gesture(uint32_t id);
-  ~Gesture();
-
-  uint32_t id() const { return id_; }
-
-  void Attach(Pointer* pointer, const ServerView* view);
-  void Detach(Pointer* pointer, const ServerView* view);
-
-  void set_state(State state) { state_ = state; }
-  State state() const { return state_; }
-
-  const std::set<PointerAndView>& pointers_and_views() const {
-    return pointers_and_views_;
-  }
-
- private:
-  const uint32_t id_;
-  State state_;
-  std::set<PointerAndView> pointers_and_views_;
-
-  DISALLOW_COPY_AND_ASSIGN(Gesture);
-};
-
-GestureManager::Gesture::Gesture(uint32_t id)
-    : id_(id), state_(STATE_INITIAL) {}
-
-GestureManager::Gesture::~Gesture() {}
-
-void GestureManager::Gesture::Attach(Pointer* pointer, const ServerView* view) {
-  pointers_and_views_.insert(PointerAndView(pointer, view));
-}
-
-void GestureManager::Gesture::Detach(Pointer* pointer, const ServerView* view) {
-  pointers_and_views_.erase(PointerAndView(pointer, view));
-}
-
-// Pointer ---------------------------------------------------------------------
-
-// Pointer manages the state associated with a particular pointer from the time
-// of the POINTER_DOWN to the time of the POINTER_UP (or POINTER_CANCEL). This
-// state includes a mapping from view to the set of gestures the view is
-// interested in. It also manages choosing gestures at the appropriate point as
-// well as which view to dispatch to and the events to dispatch.
-// See description in GestureManager for more.
-class GestureManager::Pointer {
- public:
-  Pointer(GestureManager* gesture_manager,
-          int32_t pointer_id,
-          const mojo::Event& event,
-          const Views& views);
-  ~Pointer();
-
-  int32_t pointer_id() const { return pointer_id_; }
-  bool was_chosen_or_canceled() const { return was_chosen_or_canceled_; }
-
-  // Sets the set of gestures for this pointer.
-  void SetGestures(const ServerView* view,
-                   uint32_t chosen_gesture_id,
-                   const std::set<uint32_t>& possible_gesture_ids,
-                   const std::set<uint32_t>& canceled_ids);
-
-  // Called when a Gesture we contain has been canceled.
-  void GestureCanceled(Gesture* gesture);
-
-  // Called when a Gesture we contain has been chosen.
-  void GestureChosen(Gesture* gesture, const ServerView* view);
-
-  // Process a move or up event. This may delay processing if we're waiting for
-  // previous results.
-  void ProcessEvent(const mojo::Event& event);
-
- private:
-  // Corresponds to the type of event we're dispatching.
-  enum Phase {
-    // We're dispatching the initial down.
-    PHASE_DOWN,
-
-    // We're dispatching a move.
-    PHASE_MOVE,
-  };
-
-  // Sends the event for the current phase to the delegate.
-  void ForwardCurrentEvent();
-
-  // Moves |pending_event_| to |current_event_| and notifies the delegate.
-  void MovePendingToCurrentAndProcess();
-
-  // If |was_chosen_or_canceled_| is false and there is only one possible
-  // gesture and it is in the initial state, choose it. Otherwise do nothing.
-  void ChooseGestureIfPossible();
-
-  bool ScheduleDeleteIfNecessary();
-
-  GestureManager* gesture_manager_;
-  const int32_t pointer_id_;
-  Phase phase_;
-
-  // Used to iterate over the set of views that potentially have gestures.
-  ViewIterator view_iter_;
-
-  // Maps from the view to the set of possible gestures for the view.
-  std::map<const ServerView*, std::set<Gesture*>> view_to_gestures_;
-
-  Gesture* chosen_gesture_;
-
-  bool was_chosen_or_canceled_;
-
-  // The event we're processing. When initially created this is the supplied
-  // down event. When in PHASE_MOVE this is a move event.
-  mojo::EventPtr current_event_;
-
-  // Incoming events (move or up) are added here while while waiting for
-  // responses.
-  mojo::EventPtr pending_event_;
-
-  DISALLOW_COPY_AND_ASSIGN(Pointer);
-};
-
-GestureManager::Pointer::Pointer(GestureManager* gesture_manager,
-                                 int32_t pointer_id,
-                                 const mojo::Event& event,
-                                 const Views& views)
-    : gesture_manager_(gesture_manager),
-      pointer_id_(pointer_id),
-      phase_(PHASE_DOWN),
-      view_iter_(views),
-      chosen_gesture_(nullptr),
-      was_chosen_or_canceled_(false),
-      current_event_(event.Clone()) {
-  ForwardCurrentEvent();
-}
-
-GestureManager::Pointer::~Pointer() {
-  for (auto& pair : view_to_gestures_) {
-    for (Gesture* gesture : pair.second)
-      gesture_manager_->DetachGesture(gesture, this, pair.first);
-  }
-}
-
-void GestureManager::Pointer::SetGestures(
-    const ServerView* view,
-    uint32_t chosen_gesture_id,
-    const std::set<uint32_t>& possible_gesture_ids,
-    const std::set<uint32_t>& canceled_gesture_ids) {
-  if (!view_iter_.contains(view)) {
-    // We don't know about this view.
-    return;
-  }
-
-  // True if this is the view we're waiting for a response from.
-  const bool was_waiting_on =
-      (!was_chosen_or_canceled_ &&
-       (!view_iter_.at_end() && view_iter_.current() == view));
-
-  if (possible_gesture_ids.empty()) {
-    // The view no longer wants to be notified.
-    for (Gesture* gesture : view_to_gestures_[view])
-      gesture_manager_->DetachGesture(gesture, this, view);
-    view_to_gestures_.erase(view);
-    view_iter_.remove(view);
-    if (view_iter_.empty()) {
-      gesture_manager_->PointerHasNoGestures(this);
-      // WARNING: we've been deleted.
-      return;
-    }
-  } else {
-    if (was_waiting_on)
-      view_iter_.advance();
-
-    Gesture* to_choose = nullptr;
-    std::set<Gesture*> gestures;
-    for (auto gesture_id : possible_gesture_ids) {
-      Gesture* gesture = gesture_manager_->GetGesture(view, gesture_id);
-      gesture_manager_->AttachGesture(gesture, this, view);
-      gestures.insert(gesture);
-      if (gesture->state() == Gesture::STATE_CHOSEN &&
-          !was_chosen_or_canceled_) {
-        to_choose = gesture;
-      }
-    }
-
-    // Give preference to the supplied |chosen_gesture_id|.
-    if (!was_chosen_or_canceled_ && chosen_gesture_id != kInvalidGestureId) {
-      Gesture* gesture = gesture_manager_->GetGesture(view, chosen_gesture_id);
-      if (gesture->state() != Gesture::STATE_CANCELED)
-        to_choose = gesture;
-
-      DCHECK(possible_gesture_ids.count(gesture->id()));
-      gesture_manager_->AttachGesture(gesture, this, view);
-    }
-
-    // Tell GestureManager of any Gestures we're no longer associated with.
-    std::set<Gesture*> removed_gestures;
-    std::set_difference(
-        view_to_gestures_[view].begin(), view_to_gestures_[view].end(),
-        gestures.begin(), gestures.end(),
-        std::inserter(removed_gestures, removed_gestures.begin()));
-    view_to_gestures_[view].swap(gestures);
-    for (Gesture* gesture : removed_gestures)
-      gesture_manager_->DetachGesture(gesture, this, view);
-
-    if (chosen_gesture_ && removed_gestures.count(chosen_gesture_))
-      chosen_gesture_ = nullptr;
-
-    if (to_choose) {
-      gesture_manager_->ChooseGesture(to_choose, this, view);
-    } else {
-      // Choosing a gesture implicitly cancels all other gestures. If we didn't
-      // choose a gesture we need to update the state of any newly added
-      // gestures.
-      for (Gesture* gesture : gestures) {
-        if (gesture != chosen_gesture_ &&
-            (was_chosen_or_canceled_ ||
-             canceled_gesture_ids.count(gesture->id()))) {
-          gesture_manager_->CancelGesture(gesture, this, view);
-        }
-      }
-    }
-  }
-
-  if (was_waiting_on && !was_chosen_or_canceled_) {
-    if (view_iter_.at_end()) {
-      if (ScheduleDeleteIfNecessary())
-        return;
-      // If we're got all the responses, check if there is only one valid
-      // gesture.
-      ChooseGestureIfPossible();
-      if (!was_chosen_or_canceled_) {
-        // There is more than one valid gesture and none chosen. Continue
-        // synchronous dispatch of move events.
-        phase_ = PHASE_MOVE;
-        MovePendingToCurrentAndProcess();
-      }
-    } else {
-      ForwardCurrentEvent();
-    }
-  } else if (!was_chosen_or_canceled_ && phase_ != PHASE_DOWN) {
-    // We weren't waiting on this view but we're in the move phase. The set of
-    // gestures may have changed such that we only have one valid gesture. Check
-    // for that.
-    ChooseGestureIfPossible();
-  }
-}
-
-void GestureManager::Pointer::GestureCanceled(Gesture* gesture) {
-  if (was_chosen_or_canceled_ && gesture == chosen_gesture_) {
-    chosen_gesture_ = nullptr;
-    // No need to cancel other gestures as they are already canceled by virtue
-    // of us having been chosen.
-  } else if (!was_chosen_or_canceled_ && phase_ == PHASE_MOVE) {
-    ChooseGestureIfPossible();
-  }
-}
-
-void GestureManager::Pointer::GestureChosen(Gesture* gesture,
-                                            const ServerView* view) {
-  DCHECK(!was_chosen_or_canceled_);
-  was_chosen_or_canceled_ = true;
-  chosen_gesture_ = gesture;
-  for (auto& pair : view_to_gestures_) {
-    for (Gesture* g : pair.second) {
-      if (g != gesture)
-        gesture_manager_->CancelGesture(g, this, pair.first);
-    }
-  }
-
-  while (!view_iter_.at_end()) {
-    ForwardCurrentEvent();
-    view_iter_.advance();
-  }
-  if (ScheduleDeleteIfNecessary())
-    return;
-  phase_ = PHASE_MOVE;
-  MovePendingToCurrentAndProcess();
-}
-
-void GestureManager::Pointer::ProcessEvent(const mojo::Event& event) {
-  // |event| is either a move or up. In either case it has the new coordinates
-  // and is safe to replace the existing one with.
-  pending_event_ = event.Clone();
-  if (was_chosen_or_canceled_) {
-    MovePendingToCurrentAndProcess();
-  } else if (view_iter_.at_end()) {
-    view_iter_.reset_to_beginning();
-    MovePendingToCurrentAndProcess();
-  }
-  // The else case is we are waiting on a response from a view before we
-  // continue dispatching. When we get the response for the last view in the
-  // stack we'll move pending to current and start dispatching it.
-}
-
-void GestureManager::Pointer::ForwardCurrentEvent() {
-  DCHECK(!view_iter_.at_end());
-  const ServerView* view = view_iter_.current();
-  gesture_manager_->delegate_->ProcessEvent(
-      view, CloneEventForView(*current_event_, view), was_chosen_or_canceled_);
-}
-
-void GestureManager::Pointer::MovePendingToCurrentAndProcess() {
-  if (!pending_event_.get()) {
-    current_event_ = nullptr;
-    return;
-  }
-  current_event_ = pending_event_.Pass();
-  view_iter_.reset_to_beginning();
-  ForwardCurrentEvent();
-  if (was_chosen_or_canceled_) {
-    while (view_iter_.advance())
-      ForwardCurrentEvent();
-    if (ScheduleDeleteIfNecessary())
-      return;
-    current_event_ = nullptr;
-  }
-}
-
-void GestureManager::Pointer::ChooseGestureIfPossible() {
-  if (was_chosen_or_canceled_)
-    return;
-
-  Gesture* gesture_to_choose = nullptr;
-  const ServerView* view = nullptr;
-  for (auto& pair : view_to_gestures_) {
-    for (Gesture* gesture : pair.second) {
-      if (gesture->state() == Gesture::STATE_INITIAL) {
-        if (gesture_to_choose)
-          return;
-        view = pair.first;
-        gesture_to_choose = gesture;
-      }
-    }
-  }
-  if (view)
-    gesture_manager_->ChooseGesture(gesture_to_choose, this, view);
-}
-
-bool GestureManager::Pointer::ScheduleDeleteIfNecessary() {
-  if (current_event_ &&
-      (current_event_->action == mojo::EVENT_TYPE_POINTER_UP ||
-       current_event_->action == mojo::EVENT_TYPE_POINTER_CANCEL)) {
-    gesture_manager_->ScheduleDelete(this);
-    return true;
-  }
-  return false;
-}
-
-// ScheduledDeleteProcessor ---------------------------------------------------
-
-class GestureManager::ScheduledDeleteProcessor {
- public:
-  explicit ScheduledDeleteProcessor(GestureManager* manager)
-      : manager_(manager) {}
-
-  ~ScheduledDeleteProcessor() { manager_->pointers_to_delete_.clear(); }
-
- private:
-  GestureManager* manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScheduledDeleteProcessor);
-};
-
-// PointerAndView --------------------------------------------------------------
-
-GestureManager::PointerAndView::PointerAndView()
-    : pointer(nullptr), view(nullptr) {}
-
-GestureManager::PointerAndView::PointerAndView(Pointer* pointer,
-                                               const ServerView* view)
-    : pointer(pointer), view(view) {}
-
-bool GestureManager::PointerAndView::operator<(
-    const PointerAndView& other) const {
-  if (other.pointer->pointer_id() == pointer->pointer_id())
-    return view->id().connection_id < other.view->id().connection_id;
-  return pointer->pointer_id() < other.pointer->pointer_id();
-}
-
-// GestureManager --------------------------------------------------------------
-
-// static
-const uint32_t GestureManager::kInvalidGestureId = 0u;
-
-GestureManager::GestureManager(GestureManagerDelegate* delegate,
-                               const ServerView* root)
-    : delegate_(delegate), root_view_(root) {}
-
-GestureManager::~GestureManager() {
-  // Explicitly delete the pointers first as this may result in calling back to
-  // us to cleanup and delete gestures.
-  active_pointers_.clear();
-}
-
-bool GestureManager::ProcessEvent(const mojo::Event& event) {
-  if (!event.pointer_data || !event.pointer_data->location)
-    return false;
-
-  ScheduledDeleteProcessor delete_processor(this);
-  const gfx::Point location(static_cast<int>(event.pointer_data->location->x),
-                            static_cast<int>(event.pointer_data->location->y));
-  switch (event.action) {
-    case mojo::EVENT_TYPE_POINTER_DOWN: {
-      if (GetPointerById(event.pointer_data->pointer_id)) {
-        DVLOG(1) << "received more than one down for a pointer without a "
-                 << "corresponding up, id=" << event.pointer_data->pointer_id;
-        NOTREACHED();
-        return true;
-      }
-
-      const ServerView* deepest = FindDeepestVisibleView(root_view_, location);
-      Views targets(GetTouchTargets(deepest));
-      if (targets.empty())
-        return true;
-
-      scoped_ptr<Pointer> pointer(
-          new Pointer(this, event.pointer_data->pointer_id, event, targets));
-      active_pointers_.push_back(pointer.Pass());
-      return true;
-    }
-
-    case mojo::EVENT_TYPE_POINTER_CANCEL:
-    case mojo::EVENT_TYPE_POINTER_MOVE:
-    case mojo::EVENT_TYPE_POINTER_UP: {
-      Pointer* pointer = GetPointerById(event.pointer_data->pointer_id);
-      // We delete a pointer when it has no gestures, so it's possible to get
-      // here with no gestures. Additionally there is no need to explicitly
-      // delete |pointer| as it'll tell us when it's ready to be deleted.
-      if (pointer)
-        pointer->ProcessEvent(event);
-      return true;
-    }
-
-    default:
-      break;
-  }
-  return false;
-}
-
-scoped_ptr<ChangeMap> GestureManager::SetGestures(
-    const ServerView* view,
-    int32_t pointer_id,
-    uint32_t chosen_gesture_id,
-    const std::set<uint32_t>& possible_gesture_ids,
-    const std::set<uint32_t>& canceled_gesture_ids) {
-  // TODO(sky): caller should validate ids and make sure possible contains
-  // canceled and chosen.
-  DCHECK(!canceled_gesture_ids.count(kInvalidGestureId));
-  DCHECK(!possible_gesture_ids.count(kInvalidGestureId));
-  DCHECK(chosen_gesture_id == kInvalidGestureId ||
-         possible_gesture_ids.count(chosen_gesture_id));
-  DCHECK(chosen_gesture_id == kInvalidGestureId ||
-         !canceled_gesture_ids.count(chosen_gesture_id));
-  ScheduledDeleteProcessor delete_processor(this);
-  Pointer* pointer = GetPointerById(pointer_id);
-  current_change_.reset(new ChangeMap);
-  if (pointer) {
-    pointer->SetGestures(view, chosen_gesture_id, possible_gesture_ids,
-                         canceled_gesture_ids);
-  }
-  return current_change_.Pass();
-}
-
-GestureManager::Pointer* GestureManager::GetPointerById(int32_t pointer_id) {
-  for (Pointer* pointer : active_pointers_) {
-    if (pointer->pointer_id() == pointer_id)
-      return pointer;
-  }
-  return nullptr;
-}
-
-void GestureManager::PointerHasNoGestures(Pointer* pointer) {
-  auto iter =
-      std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
-  CHECK(iter != active_pointers_.end());
-  active_pointers_.erase(iter);
-}
-
-GestureManager::Gesture* GestureManager::GetGesture(const ServerView* view,
-                                                    uint32_t gesture_id) {
-  GestureAndConnectionId gesture_and_connection_id =
-      MakeGestureAndConnectionId(view, gesture_id);
-  Gesture* gesture = gesture_map_[gesture_and_connection_id];
-  if (!gesture) {
-    gesture = new Gesture(gesture_id);
-    gesture_map_[gesture_and_connection_id] = gesture;
-  }
-  return gesture;
-}
-
-void GestureManager::AttachGesture(Gesture* gesture,
-                                   Pointer* pointer,
-                                   const ServerView* view) {
-  gesture->Attach(pointer, view);
-}
-
-void GestureManager::DetachGesture(Gesture* gesture,
-                                   Pointer* pointer,
-                                   const ServerView* view) {
-  gesture->Detach(pointer, view);
-  if (gesture->pointers_and_views().empty()) {
-    gesture_map_.erase(MakeGestureAndConnectionId(view, gesture->id()));
-    delete gesture;
-  }
-}
-
-void GestureManager::CancelGesture(Gesture* gesture,
-                                   Pointer* pointer,
-                                   const ServerView* view) {
-  if (gesture->state() == Gesture::STATE_CANCELED)
-    return;
-
-  gesture->set_state(Gesture::STATE_CANCELED);
-  for (auto& pointer_and_view : gesture->pointers_and_views()) {
-    (*current_change_)[pointer_and_view.view].canceled_gestures.insert(
-        gesture->id());
-    if (pointer_and_view.pointer != pointer)
-      pointer_and_view.pointer->GestureCanceled(gesture);
-  }
-}
-
-void GestureManager::ChooseGesture(Gesture* gesture,
-                                   Pointer* pointer,
-                                   const ServerView* view) {
-  if (gesture->state() == Gesture::STATE_CHOSEN) {
-    // This happens when |pointer| is supplied a gesture that is already
-    // chosen.
-    DCHECK((*current_change_)[view].chosen_gesture == kInvalidGestureId ||
-           (*current_change_)[view].chosen_gesture == gesture->id());
-    (*current_change_)[view].chosen_gesture = gesture->id();
-    pointer->GestureChosen(gesture, view);
-  } else {
-    gesture->set_state(Gesture::STATE_CHOSEN);
-    for (auto& pointer_and_view : gesture->pointers_and_views()) {
-      DCHECK((*current_change_)[pointer_and_view.view].chosen_gesture ==
-                 kInvalidGestureId ||
-             (*current_change_)[pointer_and_view.view].chosen_gesture ==
-                 gesture->id());
-      (*current_change_)[pointer_and_view.view].chosen_gesture = gesture->id();
-      pointer_and_view.pointer->GestureChosen(gesture, view);
-    }
-  }
-}
-
-void GestureManager::ScheduleDelete(Pointer* pointer) {
-  auto iter =
-      std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
-  if (iter != active_pointers_.end()) {
-    active_pointers_.weak_erase(iter);
-    pointers_to_delete_.push_back(pointer);
-  }
-}
-
-}  // namespace mus
diff --git a/components/mus/gesture_manager.h b/components/mus/gesture_manager.h
deleted file mode 100644
index 2eac355e..0000000
--- a/components/mus/gesture_manager.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MUS_GESTURE_MANAGER_H_
-#define COMPONENTS_MUS_GESTURE_MANAGER_H_
-
-#include <map>
-#include <set>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-
-namespace mojo {
-class Event;
-}
-
-namespace mus {
-
-class GestureManagerDelegate;
-class GestureManagerTest;
-class ServerView;
-
-struct GestureStateChange {
-  GestureStateChange();
-  ~GestureStateChange();
-
-  uint32_t chosen_gesture;
-  std::set<uint32_t> canceled_gestures;
-};
-
-using ChangeMap = std::map<const ServerView*, GestureStateChange>;
-
-// GestureManager handles incoming pointer events. It determines the set of
-// views (at most one per connection) that are interested in the event and
-// informs the delegate at the appropriate time.
-//
-// Each pointer may have any number of views associated with it, and each view
-// may have any number of gestures associated with it. Gesture are identified
-// the by the pair of the connection id of the view and the client supplied
-// gesture.  The same gesture may be used in multiple pointers (see example
-// below).
-//
-// Gestures have the following states:
-// . initial: Initial state for new gestures. From this state the gesture may
-//   become chosen or canceled. Once a gesture moves out of this state it can
-//   never go back.
-// . chosen: the gesture has been chosen. From this state the gesture may be
-//   canceled.
-// . canceled: the gesture has been canceled.
-// Gestures are active as long as they are included in the set of
-// |possible_gesture_ids|. Gestures can be removed at any time by removing the
-// gesture from |possible_gesture_ids|.
-//
-// A particular pointer has two distinct states:
-// . initial: none of the gestures associated with the pointer have been
-//   chosen.
-// . chosen: when a gesture associated with the pointer has been chosen.
-// Pointers are removed when a POINTER_UP or POINTER_CANCEL event is received.
-//
-// When a pointer is chosen all other gestures associated with the pointer are
-// implicitly canceled. If the chosen gesture is canceled the pointer remains
-// in the chosen state and no gestures can be chosen.
-//
-// Event propagation (ProcessEvent()) is handled in two distinct ways:
-// . Until a gesture has been chosen for the pointer, views are notified in
-//   order (deepest first). The next view (ancestor) is notified once
-//   SetGestures() has been invoked for the previous (descendant) view.
-// . Once a gesture has been chosen, then incoming events are immediately
-//   dispatched.
-//
-// The following example highlights various states and transitions:
-// . A POINTER_DOWN event is received for the pointer p1. The views that
-//   contain the location of the event (starting with the deepest) are v1, v2,
-//   v3 and v4. Both v1 and v2 have the property kViewManagerKeyWantsTouchEvents
-//   set, so only v1 and v2 are considered. v1 is the deepest view, so the
-//   touch event is set to it and only it first.
-// . v1 responds with possible gestures g1 and g2. v1 does not specify either
-//   of the gestures as chosen.
-// . As the response from v1 has been received and there is no chosen gesture
-//   the POINTER_DOWN event is sent to v2.
-// . v2 responds with gestures g3 and g4, neither of which are chosen.
-// . A POINTER_MOVE for p1 is received. As no gestures have been chosen event
-//   of the POINTER_MOVE continues with v1 first.
-// . v1 returns g1 and g2 as possible gestures and does not choose one.
-// . The POINTER_MOVE is sent to v2.
-// . v2 returns g3 and g4 as possible gestures and does not choose one.
-// At this point p1 has the possible gestures g1, g2, g3, g4. Gestures g1 and
-// g2 are associated with v1. Gestures g3 and g4 are associated with v2.
-// . A POINTER_DOWN event is received for the pointer p2. v1 and v2 again
-//   contain the location of the pointer. v1 is handed the event first.
-// . A POINTER_MOVE event is received for the pointer p2. As the response from
-//   v1 has not been received yet, the event is not sent yet (it is queued up).
-// . v1 responds to the POINTER_DOWN for p2 with g1 and g2 and chooses g1.
-// At this point g2, g3 and g4 are all canceled with g1 chosen. p2 is in the
-// chosen state, as is p1 (p1 enters the chosen state as it contains the chosen
-// gesture as well).
-// . The POINTER_DOWN event for p2 is sent to v2. As p2 is in the chosen state
-//   the POINTER_MOVE event that was queued up is sent to both v1 and v2 at the
-//   same time (no waiting for response).
-//
-// TODO(sky): add some sort of timeout to deal with hung processes.
-class GestureManager {
- public:
-  using GestureAndConnectionId = uint64_t;
-
-  static const uint32_t kInvalidGestureId;
-
-  GestureManager(GestureManagerDelegate* delegate, const ServerView* root);
-  ~GestureManager();
-
-  // Processes the current event. See GestureManager description for details.
-  bool ProcessEvent(const mojo::Event& event);
-
-  // Sets the gestures for the specified view and pointer.
-  scoped_ptr<ChangeMap> SetGestures(
-      const ServerView* view,
-      int32_t pointer_id,
-      uint32_t chosen_gesture_id,
-      const std::set<uint32_t>& possible_gesture_ids,
-      const std::set<uint32_t>& canceled_gesture_ids);
-
- private:
-  friend class GestureManagerTest;
-
-  class Gesture;
-  class Pointer;
-  struct PointerAndView;
-  class ScheduledDeleteProcessor;
-
-  // Returns the Pointer for |pointer_id|, or null if one doesn't exist.
-  Pointer* GetPointerById(int32_t pointer_id);
-
-  // Notification that |pointer| has no gestures. This deletes |pointer|.
-  void PointerHasNoGestures(Pointer* pointer);
-
-  // Returns the Gesture for the specified arguments, creating if necessary.
-  Gesture* GetGesture(const ServerView* view, uint32_t gesture_id);
-
-  // Called from Pointer when a gesture is associated with a pointer.
-  void AttachGesture(Gesture* gesture,
-                     Pointer* pointer,
-                     const ServerView* view);
-
-  // Called from Pointer when a gesture is no longer associated with a
-  // pointer.
-  void DetachGesture(Gesture* gesture,
-                     Pointer* pointer,
-                     const ServerView* view);
-
-  // Cancels the supplied gesture (if it isn't canceled already). Notifies all
-  // pointers containing |gesture| that |gesture| has been canceled.
-  void CancelGesture(Gesture* gesture,
-                     Pointer* pointer,
-                     const ServerView* view);
-
-  // Chooses the supplied gesture. Notifies all pointers containing |gesture|
-  // that |gesture| has been chosen.
-  void ChooseGesture(Gesture* gesture,
-                     Pointer* pointer,
-                     const ServerView* view);
-
-  // Deletes |pointer| after processing the current event. We delay deletion
-  // until after the event as immediate deletion can cause problems for Pointer
-  // (this is because the same Pointer may be on multiple frames of the stack).
-  void ScheduleDelete(Pointer* pointer);
-
-  GestureManagerDelegate* delegate_;
-  const ServerView* root_view_;
-
-  // Map for looking up gestures. Gestures are identified by the pair of
-  // connection id and supplied gesture id.
-  std::map<GestureAndConnectionId, Gesture*> gesture_map_;
-
-  ScopedVector<Pointer> active_pointers_;
-
-  // See comment in ScheduleDelete() for details.
-  ScopedVector<Pointer> pointers_to_delete_;
-
-  // Accumulates changes as the result of SetGestures().
-  scoped_ptr<ChangeMap> current_change_;
-
-  DISALLOW_COPY_AND_ASSIGN(GestureManager);
-};
-
-}  // namespace mus
-
-#endif  // COMPONENTS_MUS_GESTURE_MANAGER_H_
diff --git a/components/mus/gesture_manager_delegate.h b/components/mus/gesture_manager_delegate.h
deleted file mode 100644
index d6a47a34..0000000
--- a/components/mus/gesture_manager_delegate.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MUS_GESTURE_MANAGER_DELEGATE_H_
-#define COMPONENTS_MUS_GESTURE_MANAGER_DELEGATE_H_
-
-#include <set>
-
-#include "components/mus/public/cpp/types.h"
-#include "ui/mojo/events/input_events.mojom.h"
-
-namespace mus {
-
-class GestureManagerDelegate {
- public:
-  // Informs the delegate of a pointer event. The delegate should asynchronously
-  // respond with the set of gestures appropriate for the view
-  // (GestureManager::SetGestures()).
-  // |has_chosen_gesture| is true if a gesture has been chosen.
-  virtual void ProcessEvent(const ServerView* view,
-                            mojo::EventPtr event,
-                            bool has_chosen_gesture) = 0;
-
- protected:
-  virtual ~GestureManagerDelegate() {}
-};
-
-}  // namespace mus
-
-#endif  // COMPONENTS_MUS_GESTURE_MANAGER_DELEGATE_H_
diff --git a/components/mus/gesture_manager_unittest.cc b/components/mus/gesture_manager_unittest.cc
deleted file mode 100644
index 847a8e0..0000000
--- a/components/mus/gesture_manager_unittest.cc
+++ /dev/null
@@ -1,469 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/mus/gesture_manager.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "components/mus/gesture_manager_delegate.h"
-#include "components/mus/public/cpp/keys.h"
-#include "components/mus/server_view.h"
-#include "components/mus/test_server_view_delegate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/mojo/events/input_events.mojom.h"
-
-namespace mus {
-namespace {
-
-const uint32_t kInvalidGestureId = GestureManager::kInvalidGestureId;
-
-void MarkAsRespondsToTouch(ServerView* view) {
-  std::vector<uint8_t> empty_vector;
-  view->SetProperty(kViewManagerKeyWantsTouchEvents, &empty_vector);
-}
-
-std::set<uint32_t> SetWith(uint32_t v1) {
-  std::set<uint32_t> result;
-  result.insert(v1);
-  return result;
-}
-
-std::set<uint32_t> SetWith(uint32_t v1, uint32_t v2) {
-  std::set<uint32_t> result;
-  result.insert(v1);
-  result.insert(v2);
-  return result;
-}
-
-std::set<uint32_t> SetWith(uint32_t v1, uint32_t v2, uint32_t v3) {
-  std::set<uint32_t> result;
-  result.insert(v1);
-  result.insert(v2);
-  result.insert(v3);
-  return result;
-}
-
-std::string EventTypeToString(mojo::EventType event_type) {
-  switch (event_type) {
-    case mojo::EVENT_TYPE_POINTER_CANCEL:
-      return "cancel";
-    case mojo::EVENT_TYPE_POINTER_DOWN:
-      return "down";
-    case mojo::EVENT_TYPE_POINTER_MOVE:
-      return "move";
-    case mojo::EVENT_TYPE_POINTER_UP:
-      return "up";
-    default:
-      break;
-  }
-  return std::string("unexpected event");
-}
-
-mojo::EventPtr CreateEvent(mojo::EventType type,
-                           int32_t pointer_id,
-                           int x,
-                           int y) {
-  mojo::EventPtr event(mojo::Event::New());
-  event->action = type;
-  event->pointer_data = mojo::PointerData::New();
-  event->pointer_data->pointer_id = pointer_id;
-  event->pointer_data->location = mojo::LocationData::New();
-  event->pointer_data->location->x = x;
-  event->pointer_data->location->y = y;
-  return event.Pass();
-}
-
-struct CompareViewByConnectionId {
-  bool operator()(const ServerView* a, const ServerView* b) {
-    return a->id().connection_id < b->id().connection_id;
-  }
-};
-
-std::string IDsToString(const std::set<uint32_t>& ids) {
-  std::string result;
-  for (uint32_t id : ids) {
-    if (!result.empty())
-      result += ",";
-    result += base::UintToString(id);
-  }
-  return result;
-}
-
-std::string GestureStateChangeToString(const ServerView* view,
-                                       const GestureStateChange& change) {
-  std::string result =
-      "connection=" + base::IntToString(view->id().connection_id);
-  if (change.chosen_gesture != GestureManager::kInvalidGestureId)
-    result += " chosen=" + base::UintToString(change.chosen_gesture);
-  if (!change.canceled_gestures.empty())
-    result += " canceled=" + IDsToString(change.canceled_gestures);
-  return result;
-}
-
-}  // namespace
-
-class TestGestureManagerDelegate : public GestureManagerDelegate {
- public:
-  TestGestureManagerDelegate() {}
-  ~TestGestureManagerDelegate() override {}
-
-  std::string GetAndClearDescriptions() {
-    const std::string result(base::JoinString(descriptions_, "\n"));
-    descriptions_.clear();
-    return result;
-  }
-
-  std::vector<std::string>& descriptions() { return descriptions_; }
-
-  void AppendDescriptionsFromResults(const ChangeMap& change_map) {
-    std::set<const ServerView*, CompareViewByConnectionId> views_by_id;
-    for (const auto& pair : change_map)
-      views_by_id.insert(pair.first);
-
-    for (auto* view : views_by_id) {
-      descriptions_.push_back(
-          GestureStateChangeToString(view, change_map.find(view)->second));
-    }
-  }
-
-  // GestureManagerDelegate:
-  void ProcessEvent(const ServerView* view,
-                    mojo::EventPtr event,
-                    bool has_chosen_gesture) override {
-    descriptions_.push_back(
-        EventTypeToString(event->action) + " pointer=" +
-        base::IntToString(event->pointer_data->pointer_id) + " connection=" +
-        base::UintToString(view->id().connection_id) + " chosen=" +
-        (has_chosen_gesture ? "true" : "false"));
-  }
-
- private:
-  std::vector<std::string> descriptions_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestGestureManagerDelegate);
-};
-
-class GestureManagerTest : public testing::Test {
- public:
-  GestureManagerTest()
-      : root_(&view_delegate_, ViewId(1, 1)),
-        child_(&view_delegate_, ViewId(2, 2)),
-        gesture_manager_(&gesture_delegate_, &root_) {
-    view_delegate_.set_root_view(&root_);
-    root_.SetVisible(true);
-    MarkAsRespondsToTouch(&root_);
-    root_.SetBounds(gfx::Rect(0, 0, 100, 100));
-  }
-  ~GestureManagerTest() override {}
-
-  void SetGestures(const ServerView* view,
-                   int32_t pointer_id,
-                   uint32_t chosen_gesture_id,
-                   const std::set<uint32_t>& possible_gesture_ids,
-                   const std::set<uint32_t>& canceled_ids) {
-    scoped_ptr<ChangeMap> result(
-        gesture_manager_.SetGestures(view, pointer_id, chosen_gesture_id,
-                                     possible_gesture_ids, canceled_ids));
-    gesture_delegate_.AppendDescriptionsFromResults(*result);
-  }
-
-  void AddChildView() {
-    MarkAsRespondsToTouch(&child_);
-    child_.SetVisible(true);
-    root_.Add(&child_);
-    child_.SetBounds(gfx::Rect(0, 0, 100, 100));
-  }
-
- protected:
-  TestServerViewDelegate view_delegate_;
-  ServerView root_;
-  ServerView child_;
-  TestGestureManagerDelegate gesture_delegate_;
-  GestureManager gesture_manager_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GestureManagerTest);
-};
-
-TEST_F(GestureManagerTest, SingleViewAndSingleGesture) {
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Choose this pointer.
-  SetGestures(&root_, pointer_id, 10u, SetWith(10u), std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=10",
-            gesture_delegate_.GetAndClearDescriptions());
-}
-
-TEST_F(GestureManagerTest, SingleViewAndTwoGestures) {
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-
-  // Delegate should have got nothing.
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Cancel 10, 5 should become active.
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              SetWith(10u));
-
-  EXPECT_EQ("connection=1 chosen=5 canceled=10",
-            gesture_delegate_.GetAndClearDescriptions());
-}
-
-TEST_F(GestureManagerTest, TwoViewsSingleGesture) {
-  AddChildView();
-
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  // Deepest child should be queried first.
-  EXPECT_EQ("down pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond from the first view, which triggers the second to be queried.
-  SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond with 5,10 for the second view. Should get nothing.
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Cancel 10 in the child.
-  SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              SetWith(10u));
-  EXPECT_EQ("connection=2 canceled=10",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Choose 5 in the root. This should choose 5 in the root and cancel 5 in
-  // the child.
-  SetGestures(&root_, pointer_id, 5u, SetWith(5u, 10u), SetWith(10u));
-  ASSERT_EQ(2u, gesture_delegate_.descriptions().size());
-  EXPECT_EQ("connection=1 chosen=5 canceled=10",
-            gesture_delegate_.descriptions()[0]);
-  EXPECT_EQ("connection=2 canceled=5", gesture_delegate_.descriptions()[1]);
-}
-
-TEST_F(GestureManagerTest, TwoViewsWaitForMoveToChoose) {
-  AddChildView();
-
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  // Deepest child should be queried first.
-  EXPECT_EQ("down pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Send a move. The move should not be processed as GestureManager is
-  // still waiting for responses.
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer_id, 6, 6));
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond from the first view, which triggers the second to be queried.
-  SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond with 1,2 for the second view.
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(1u, 2u),
-              std::set<uint32_t>());
-  // Now that we've responded to the down requests we should get a move for the
-  // child.
-  EXPECT_EQ("move pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond for the child, root should now get move.
-  SetGestures(&child_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-  EXPECT_EQ("move pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond with nothing chosen for the root. Nothing should come in as no
-  // pending moves.
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(1u, 2u),
-              std::set<uint32_t>());
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Send another move event and respond with a chosen id.
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer_id, 7, 7));
-  EXPECT_EQ("move pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-  SetGestures(&child_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>());
-  ASSERT_EQ(3u, gesture_delegate_.descriptions().size());
-  // Now that a gesture is chosen the move event is generated.
-  EXPECT_EQ("move pointer=1 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[0]);
-  EXPECT_EQ("connection=1 canceled=1,2", gesture_delegate_.descriptions()[1]);
-  EXPECT_EQ("connection=2 chosen=5 canceled=10",
-            gesture_delegate_.descriptions()[2]);
-}
-
-TEST_F(GestureManagerTest, SingleViewNewPointerAfterChoose) {
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Choose 5.
-  SetGestures(&root_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=5 canceled=10",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Start another down event with a different pointer.
-  const int32_t pointer_id2 = 2;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id2, 5, 5));
-  EXPECT_EQ("down pointer=2 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // For the new pointer supply the id of a gesture that has been chosen.
-  // Even though we didn't explicitly supply 5 as chosen, 5 is chosen because
-  // it's already in the chosen state for pointer 1.
-  SetGestures(&root_, pointer_id2, kInvalidGestureId, SetWith(5u, 11u),
-              std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=5 canceled=11",
-            gesture_delegate_.GetAndClearDescriptions());
-}
-
-TEST_F(GestureManagerTest, SingleViewChoosingConflictingGestures) {
-  // For pointer1 choose 1 with 1,2,3 as possibilities.
-  const int32_t pointer1 = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer1, 5, 5));
-  gesture_delegate_.GetAndClearDescriptions();
-  SetGestures(&root_, pointer1, 1u, SetWith(1u, 2u, 3u), std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=1 canceled=2,3",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // For pointer2 choose 11 with 11,12 as possibilities.
-  const int32_t pointer2 = 2;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer2, 5, 5));
-  gesture_delegate_.GetAndClearDescriptions();
-  SetGestures(&root_, pointer2, 11u, SetWith(11u, 12u), std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=11 canceled=12",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // For pointer3 choose 21 with 1,11,21 as possibilties.
-  const int32_t pointer3 = 3;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer3, 5, 5));
-  gesture_delegate_.GetAndClearDescriptions();
-  SetGestures(&root_, pointer3, 21u, SetWith(1u, 11u, 21u),
-              std::set<uint32_t>());
-  EXPECT_EQ("connection=1 chosen=21 canceled=1,11",
-            gesture_delegate_.GetAndClearDescriptions());
-}
-
-TEST_F(GestureManagerTest,
-       TwoViewsRespondingWithChosenGestureSendsRemainingEvents) {
-  AddChildView();
-
-  // Start two pointer downs, don't respond to either.
-  const int32_t pointer1 = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer1, 5, 5));
-  EXPECT_EQ("down pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  const int32_t pointer2 = 2;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer2, 5, 5));
-  EXPECT_EQ("down pointer=2 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Queue up a move event for pointer1. The event should not be forwarded
-  // as we're still waiting.
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_MOVE, pointer1, 5, 5));
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond with 1,2 for pointer1 (nothing chosen yet).
-  SetGestures(&child_, pointer1, kInvalidGestureId, SetWith(1u, 2u),
-              std::set<uint32_t>());
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond with 1,2 and choose 1 for pointer2. This results in the following:
-  // down for pointer 1 (because we chose a gesture in common with pointer1),
-  // move for pointer 1 in both connections (because a gesture was chosen queued
-  // up events are sent), down for pointer2 for the root and finally
-  // notification of what was chosen.
-  SetGestures(&child_, pointer2, 1u, SetWith(1u, 2u), std::set<uint32_t>());
-  ASSERT_EQ(5u, gesture_delegate_.descriptions().size());
-  EXPECT_EQ("down pointer=1 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[0]);
-  EXPECT_EQ("move pointer=1 connection=2 chosen=true",
-            gesture_delegate_.descriptions()[1]);
-  EXPECT_EQ("move pointer=1 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[2]);
-  EXPECT_EQ("down pointer=2 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[3]);
-  EXPECT_EQ("connection=2 chosen=1 canceled=2",
-            gesture_delegate_.descriptions()[4]);
-}
-
-TEST_F(GestureManagerTest, TwoViewsSingleGestureUp) {
-  AddChildView();
-
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  // Deepest child should be queried first.
-  EXPECT_EQ("down pointer=1 connection=2 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Send an up, shouldn't result in anything.
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_UP, pointer_id, 5, 5));
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond from the first view, with a chosen gesture.
-  SetGestures(&child_, pointer_id, 5u, SetWith(5u, 10u), std::set<uint32_t>());
-  ASSERT_EQ(4u, gesture_delegate_.descriptions().size());
-  EXPECT_EQ("down pointer=1 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[0]);
-  EXPECT_EQ("up pointer=1 connection=2 chosen=true",
-            gesture_delegate_.descriptions()[1]);
-  EXPECT_EQ("up pointer=1 connection=1 chosen=true",
-            gesture_delegate_.descriptions()[2]);
-  EXPECT_EQ("connection=2 chosen=5 canceled=10",
-            gesture_delegate_.descriptions()[3]);
-}
-
-TEST_F(GestureManagerTest, SingleViewSingleGestureCancel) {
-  const int32_t pointer_id = 1;
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_DOWN, pointer_id, 5, 5));
-  EXPECT_EQ("down pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-
-  // Send a cancel, shouldn't result in anything.
-  gesture_manager_.ProcessEvent(
-      *CreateEvent(mojo::EVENT_TYPE_POINTER_CANCEL, pointer_id, 5, 5));
-  EXPECT_EQ(std::string(), gesture_delegate_.GetAndClearDescriptions());
-
-  // Respond from the first view, with no gesture, should unblock cancel.
-  SetGestures(&root_, pointer_id, kInvalidGestureId, SetWith(5u, 10u),
-              std::set<uint32_t>());
-  EXPECT_EQ("cancel pointer=1 connection=1 chosen=false",
-            gesture_delegate_.GetAndClearDescriptions());
-}
-
-}  // namespace mus
diff --git a/components/mus/gles2/BUILD.gn b/components/mus/gles2/BUILD.gn
index 486af5b8..be5e03c 100644
--- a/components/mus/gles2/BUILD.gn
+++ b/components/mus/gles2/BUILD.gn
@@ -4,7 +4,8 @@
 
 source_set("gles2") {
   visibility = [
-    "//components/mus:lib",
+    "//components/mus:*",
+    "//components/mus/vm:*",
     "//components/mus/surfaces:*",
     "//mojo/runner:lib",  # For android
   ]
diff --git a/components/mus/gles2/command_buffer_type_conversions.cc b/components/mus/gles2/command_buffer_type_conversions.cc
index b33e7da..d5a9f260 100644
--- a/components/mus/gles2/command_buffer_type_conversions.cc
+++ b/components/mus/gles2/command_buffer_type_conversions.cc
@@ -5,7 +5,6 @@
 #include "components/mus/gles2/command_buffer_type_conversions.h"
 
 #include "components/mus/public/interfaces/command_buffer.mojom.h"
-#include "components/mus/public/interfaces/gpu.mojom.h"
 
 namespace mojo {
 
diff --git a/components/mus/mus_app.cc b/components/mus/mus_app.cc
index e33fa18..4c302400 100644
--- a/components/mus/mus_app.cc
+++ b/components/mus/mus_app.cc
@@ -4,16 +4,15 @@
 
 #include "components/mus/mus_app.h"
 
-#include "base/command_line.h"
 #include "base/stl_util.h"
-#include "components/mus/client_connection.h"
-#include "components/mus/connection_manager.h"
 #include "components/mus/gles2/gpu_impl.h"
 #include "components/mus/public/cpp/args.h"
 #include "components/mus/surfaces/surfaces_scheduler.h"
-#include "components/mus/view_tree_host_connection.h"
-#include "components/mus/view_tree_host_impl.h"
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/client_connection.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/view_tree_host_connection.h"
+#include "components/mus/vm/view_tree_host_impl.h"
+#include "components/mus/vm/view_tree_impl.h"
 #include "mojo/application/public/cpp/application_connection.h"
 #include "mojo/application/public/cpp/application_impl.h"
 #include "mojo/application/public/cpp/application_runner.h"
@@ -26,6 +25,7 @@
 
 #if defined(USE_X11)
 #include <X11/Xlib.h>
+#include "base/command_line.h"
 #include "ui/platform_window/x11/x11_window.h"
 #endif
 
@@ -38,7 +38,7 @@
 namespace mus {
 
 MandolineUIServicesApp::MandolineUIServicesApp()
-    : app_impl_(nullptr), is_headless_(false) {}
+    : app_impl_(nullptr) {}
 
 MandolineUIServicesApp::~MandolineUIServicesApp() {
   if (gpu_state_)
@@ -52,21 +52,19 @@
   tracing_.Initialize(app);
   surfaces_state_ = new SurfacesState;
 
-#if !defined(OS_ANDROID)
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  is_headless_ = command_line->HasSwitch(kUseHeadlessConfig);
-  if (!is_headless_) {
 #if defined(USE_X11)
-    if (command_line->HasSwitch(kUseX11TestConfig)) {
-      XInitThreads();
-      ui::test::SetUseOverrideRedirectWindowByDefault(true);
-    }
-#endif
-    gfx::GLSurface::InitializeOneOff();
-    event_source_ = ui::PlatformEventSource::CreateDefault();
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(kUseX11TestConfig)) {
+    XInitThreads();
+    ui::test::SetUseOverrideRedirectWindowByDefault(true);
   }
 #endif
 
+#if !defined(OS_ANDROID)
+  gfx::GLSurface::InitializeOneOff();
+  event_source_ = ui::PlatformEventSource::CreateDefault();
+#endif
+
   if (!gpu_state_.get())
     gpu_state_ = new GpuState;
   connection_manager_.reset(new ConnectionManager(this, surfaces_state_));
@@ -136,7 +134,7 @@
   // TODO(fsamuel): We need to make sure that only the window manager can create
   // new roots.
   ViewTreeHostImpl* host_impl = new ViewTreeHostImpl(
-      host_client.Pass(), connection_manager_.get(), is_headless_, app_impl_,
+      host_client.Pass(), connection_manager_.get(), app_impl_,
       gpu_state_, surfaces_state_);
 
   // ViewTreeHostConnection manages its own lifetime.
diff --git a/components/mus/mus_app.h b/components/mus/mus_app.h
index db528e1..9a7e8f5 100644
--- a/components/mus/mus_app.h
+++ b/components/mus/mus_app.h
@@ -8,11 +8,10 @@
 #include <set>
 
 #include "base/memory/scoped_ptr.h"
-#include "cc/surfaces/surface_manager.h"
-#include "components/mus/connection_manager_delegate.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
 #include "components/mus/public/interfaces/view_tree_host.mojom.h"
+#include "components/mus/vm/connection_manager_delegate.h"
 #include "mojo/application/public/cpp/app_lifetime_helper.h"
 #include "mojo/application/public/cpp/application_delegate.h"
 #include "mojo/application/public/cpp/interface_factory.h"
@@ -31,7 +30,6 @@
 
 class ConnectionManager;
 class GpuState;
-class SurfacesScheduler;
 class SurfacesState;
 
 class MandolineUIServicesApp
@@ -87,7 +85,6 @@
   mojo::TracingImpl tracing_;
   scoped_refptr<GpuState> gpu_state_;
   scoped_ptr<ui::PlatformEventSource> event_source_;
-  bool is_headless_;
 
   // Surfaces
   scoped_refptr<SurfacesState> surfaces_state_;
diff --git a/components/mus/public/cpp/BUILD.gn b/components/mus/public/cpp/BUILD.gn
index aa2d276..8344828 100644
--- a/components/mus/public/cpp/BUILD.gn
+++ b/components/mus/public/cpp/BUILD.gn
@@ -7,8 +7,9 @@
 mojo_sdk_source_set("cpp") {
   restrict_external_deps = false
   sources = [
-    "args.h",
-    "lib/args.cc",
+    "context_provider.h",
+    "lib/context_provider.cc",
+    "lib/output_surface.cc",
     "lib/scoped_view_ptr.cc",
     "lib/view.cc",
     "lib/view_observer.cc",
@@ -19,6 +20,7 @@
     "lib/view_tree_client_impl.h",
     "lib/view_tree_delegate.cc",
     "lib/view_tree_host_factory.cc",
+    "output_surface.h",
     "scoped_view_ptr.h",
     "view.h",
     "view_observer.h",
@@ -39,12 +41,19 @@
   ]
 
   deps = [
+    "//base",
+    "//cc",
+    "//cc/surfaces",
+    "//cc/surfaces:surface_id",
     "//mojo/application/public/cpp",
     "//mojo/application/public/interfaces",
     "//mojo/converters/surfaces",
+    "//mojo/gles2:headers",
+    "//mojo/gpu:mojo_gles2_implementation",
+    "//third_party/mojo/src/mojo/public/cpp/environment",
+    "//third_party/mojo/src/mojo/public/cpp/system",
     "//ui/mojo/events:interfaces",
     "//ui/mojo/geometry:interfaces",
-    "//base",
   ]
 
   mojo_sdk_deps = [
@@ -56,8 +65,10 @@
 
 source_set("common") {
   sources = [
+    "args.h",
     "keys.cc",
     "keys.h",
+    "lib/args.cc",
     "types.h",
     "util.h",
   ]
diff --git a/components/mus/public/cpp/args.h b/components/mus/public/cpp/args.h
index 863bbb5..6fc6f26 100644
--- a/components/mus/public/cpp/args.h
+++ b/components/mus/public/cpp/args.h
@@ -9,7 +9,6 @@
 
 // All args in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
-extern const char kUseHeadlessConfig[];
 extern const char kUseX11TestConfig[];
 
 }  // namespace mus
diff --git a/mojo/cc/context_provider_mojo.h b/components/mus/public/cpp/context_provider.h
similarity index 70%
rename from mojo/cc/context_provider_mojo.h
rename to components/mus/public/cpp/context_provider.h
index cc465d0..c07532e 100644
--- a/mojo/cc/context_provider_mojo.h
+++ b/components/mus/public/cpp/context_provider.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 MOJO_CC_CONTEXT_PROVIDER_MOJO_H_
-#define MOJO_CC_CONTEXT_PROVIDER_MOJO_H_
+#ifndef COMPONENTS_MUS_PUBLIC_CPP_CONTEXT_PROVIDER_H_
+#define COMPONENTS_MUS_PUBLIC_CPP_CONTEXT_PROVIDER_H_
 
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
@@ -12,11 +12,11 @@
 #include "third_party/mojo/src/mojo/public/c/gles2/gles2.h"
 #include "third_party/mojo/src/mojo/public/cpp/system/core.h"
 
-namespace mojo {
+namespace mus {
 
-class ContextProviderMojo : public cc::ContextProvider {
+class ContextProvider : public cc::ContextProvider {
  public:
-  explicit ContextProviderMojo(ScopedMessagePipeHandle command_buffer_handle);
+  explicit ContextProvider(mojo::ScopedMessagePipeHandle command_buffer_handle);
 
   // cc::ContextProvider implementation.
   bool BindToCurrentThread() override;
@@ -37,25 +37,25 @@
       override {}
 
  protected:
-  friend class base::RefCountedThreadSafe<ContextProviderMojo>;
-  ~ContextProviderMojo() override;
+  friend class base::RefCountedThreadSafe<ContextProvider>;
+  ~ContextProvider() override;
 
  private:
   static void ContextLostThunk(void* closure) {
-    static_cast<ContextProviderMojo*>(closure)->ContextLost();
+    static_cast<ContextProvider*>(closure)->ContextLost();
   }
   void ContextLost();
 
   cc::ContextProvider::Capabilities capabilities_;
-  ScopedMessagePipeHandle command_buffer_handle_;
+  mojo::ScopedMessagePipeHandle command_buffer_handle_;
   MojoGLES2Context context_;
   scoped_ptr<gpu::gles2::GLES2Interface> context_gl_;
 
   base::Lock context_lock_;
 
-  DISALLOW_COPY_AND_ASSIGN(ContextProviderMojo);
+  DISALLOW_COPY_AND_ASSIGN(ContextProvider);
 };
 
-}  // namespace mojo
+}  // namespace mus
 
-#endif  // MOJO_CC_CONTEXT_PROVIDER_MOJO_H_
+#endif  // COMPONENTS_MUS_PUBLIC_CPP_CONTEXT_PROVIDER_H_
diff --git a/components/mus/public/cpp/lib/DEPS b/components/mus/public/cpp/lib/DEPS
new file mode 100644
index 0000000..5e8f71d2
--- /dev/null
+++ b/components/mus/public/cpp/lib/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+mojo/gles2",
+  "+mojo/gpu"
+]
diff --git a/components/mus/public/cpp/lib/args.cc b/components/mus/public/cpp/lib/args.cc
index e17ada3..e45a9f0b 100644
--- a/components/mus/public/cpp/lib/args.cc
+++ b/components/mus/public/cpp/lib/args.cc
@@ -6,9 +6,6 @@
 
 namespace mus {
 
-// Create native viewport in headless mode.
-const char kUseHeadlessConfig[] = "use-headless-config";
-
 // Initializes X11 in threaded mode, and sets the |override_redirect| flag when
 // creating X11 windows.
 const char kUseX11TestConfig[] = "use-x11-test-config";
diff --git a/components/mus/public/cpp/lib/context_provider.cc b/components/mus/public/cpp/lib/context_provider.cc
new file mode 100644
index 0000000..e56557f
--- /dev/null
+++ b/components/mus/public/cpp/lib/context_provider.cc
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/mus/public/cpp/context_provider.h"
+
+#include "base/logging.h"
+#include "mojo/gles2/gles2_context.h"
+#include "mojo/gpu/mojo_gles2_impl_autogen.h"
+#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h"
+
+namespace mus {
+
+ContextProvider::ContextProvider(
+    mojo::ScopedMessagePipeHandle command_buffer_handle)
+    : command_buffer_handle_(command_buffer_handle.Pass()), context_(nullptr) {
+  // Enabled the CHROMIUM_image extension to use GpuMemoryBuffers. The
+  // implementation of which is used in CommandBufferDriver.
+  capabilities_.gpu.image = true;
+}
+
+bool ContextProvider::BindToCurrentThread() {
+  DCHECK(command_buffer_handle_.is_valid());
+  context_ = MojoGLES2CreateContext(command_buffer_handle_.release().value(),
+                                    nullptr, &ContextLostThunk, this,
+                                    mojo::Environment::GetDefaultAsyncWaiter());
+  context_gl_.reset(new mojo::MojoGLES2Impl(context_));
+  return !!context_;
+}
+
+gpu::gles2::GLES2Interface* ContextProvider::ContextGL() {
+  return context_gl_.get();
+}
+
+gpu::ContextSupport* ContextProvider::ContextSupport() {
+  if (!context_)
+    return NULL;
+  // TODO(rjkroege): Ensure that UIP does not take this code path.
+  return static_cast<gles2::GLES2Context*>(context_)->context_support();
+}
+
+class GrContext* ContextProvider::GrContext() {
+  return NULL;
+}
+
+void ContextProvider::InvalidateGrContext(uint32_t state) {}
+
+cc::ContextProvider::Capabilities ContextProvider::ContextCapabilities() {
+  return capabilities_;
+}
+
+void ContextProvider::SetupLock() {}
+
+base::Lock* ContextProvider::GetLock() {
+  return &context_lock_;
+}
+
+bool ContextProvider::DestroyedOnMainThread() {
+  return !context_;
+}
+
+ContextProvider::~ContextProvider() {
+  context_gl_.reset();
+  if (context_)
+    MojoGLES2DestroyContext(context_);
+}
+
+void ContextProvider::ContextLost() {}
+
+}  // namespace mus
diff --git a/mojo/cc/output_surface_mojo.cc b/components/mus/public/cpp/lib/output_surface.cc
similarity index 69%
rename from mojo/cc/output_surface_mojo.cc
rename to components/mus/public/cpp/lib/output_surface.cc
index f06835f..77b2422 100644
--- a/mojo/cc/output_surface_mojo.cc
+++ b/components/mus/public/cpp/lib/output_surface.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "mojo/cc/output_surface_mojo.h"
+#include "components/mus/public/cpp/output_surface.h"
 
 #include "base/bind.h"
 #include "cc/output/compositor_frame.h"
@@ -11,9 +11,9 @@
 #include "components/mus/public/cpp/view_surface.h"
 #include "mojo/converters/surfaces/surfaces_type_converters.h"
 
-namespace mojo {
+namespace mus {
 
-OutputSurfaceMojo::OutputSurfaceMojo(
+OutputSurface::OutputSurface(
     const scoped_refptr<cc::ContextProvider>& context_provider,
     scoped_ptr<mus::ViewSurface> surface)
     : cc::OutputSurface(context_provider), surface_(surface.Pass()) {
@@ -21,33 +21,31 @@
   capabilities_.max_frames_pending = 1;
 }
 
-OutputSurfaceMojo::~OutputSurfaceMojo() {
-}
+OutputSurface::~OutputSurface() {}
 
-bool OutputSurfaceMojo::BindToClient(cc::OutputSurfaceClient* client) {
+bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
   surface_->BindToThread();
   surface_->set_client(this);
   return cc::OutputSurface::BindToClient(client);
 }
 
-void OutputSurfaceMojo::DetachFromClient() {
+void OutputSurface::DetachFromClient() {
   surface_.reset();
   cc::OutputSurface::DetachFromClient();
 }
 
-void OutputSurfaceMojo::SwapBuffers(cc::CompositorFrame* frame) {
+void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
   // TODO(fsamuel, rjkroege): We should probably throttle compositor frames.
   client_->DidSwapBuffers();
-  // OutputSurfaceMojo owns ViewSurface, and so if OutputSurfaceMojo is
+  // OutputSurface owns ViewSurface, and so if OutputSurface is
   // destroyed then SubmitCompositorFrame's callback will never get called.
   // Thus, base::Unretained is safe here.
   surface_->SubmitCompositorFrame(
       mojo::CompositorFrame::From(*frame),
-      base::Bind(&OutputSurfaceMojo::SwapBuffersComplete,
-                 base::Unretained(this)));
+      base::Bind(&OutputSurface::SwapBuffersComplete, base::Unretained(this)));
 }
 
-void OutputSurfaceMojo::OnResourcesReturned(
+void OutputSurface::OnResourcesReturned(
     mus::ViewSurface* surface,
     mojo::Array<mojo::ReturnedResourcePtr> resources) {
   cc::CompositorFrameAck cfa;
@@ -55,8 +53,8 @@
   ReclaimResources(&cfa);
 }
 
-void OutputSurfaceMojo::SwapBuffersComplete() {
+void OutputSurface::SwapBuffersComplete() {
   client_->DidSwapBuffersComplete();
 }
 
-}  // namespace mojo
+}  // namespace mus
diff --git a/components/mus/public/cpp/output_surface.h b/components/mus/public/cpp/output_surface.h
new file mode 100644
index 0000000..e187fb3b
--- /dev/null
+++ b/components/mus/public/cpp/output_surface.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MUS_PUBLIC_CPP_OUTPUT_SURFACE_H_
+#define COMPONENTS_MUS_PUBLIC_CPP_OUTPUT_SURFACE_H_
+
+#include "base/macros.h"
+#include "cc/output/output_surface.h"
+#include "cc/surfaces/surface_id.h"
+#include "components/mus/public/cpp/view_surface.h"
+#include "components/mus/public/cpp/view_surface_client.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
+
+namespace mus {
+
+class OutputSurface : public cc::OutputSurface, public ViewSurfaceClient {
+ public:
+  OutputSurface(const scoped_refptr<cc::ContextProvider>& context_provider,
+                scoped_ptr<ViewSurface> surface);
+  ~OutputSurface() override;
+
+  // cc::OutputSurface implementation.
+  void SwapBuffers(cc::CompositorFrame* frame) override;
+  bool BindToClient(cc::OutputSurfaceClient* client) override;
+  void DetachFromClient() override;
+
+ private:
+  // ViewSurfaceClient implementation:
+  void OnResourcesReturned(
+      ViewSurface* surface,
+      mojo::Array<mojo::ReturnedResourcePtr> resources) override;
+
+  void SwapBuffersComplete();
+
+  scoped_ptr<ViewSurface> surface_;
+
+  DISALLOW_COPY_AND_ASSIGN(OutputSurface);
+};
+
+}  // namespace mus
+
+#endif  // COMPONENTS_MUS_PUBLIC_CPP_OUTPUT_SURFACE_H_
diff --git a/components/mus/surfaces/BUILD.gn b/components/mus/surfaces/BUILD.gn
index 18326b05..7686eae 100644
--- a/components/mus/surfaces/BUILD.gn
+++ b/components/mus/surfaces/BUILD.gn
@@ -4,11 +4,11 @@
 
 source_set("surfaces") {
   sources = [
+    "direct_output_surface.cc",
+    "direct_output_surface.h",
     "surfaces_context_provider.cc",
     "surfaces_context_provider.h",
     "surfaces_context_provider_delegate.h",
-    "surfaces_output_surface.cc",
-    "surfaces_output_surface.h",
     "surfaces_scheduler.cc",
     "surfaces_scheduler.h",
     "surfaces_state.cc",
diff --git a/components/mus/surfaces/surfaces_output_surface.cc b/components/mus/surfaces/direct_output_surface.cc
similarity index 95%
rename from components/mus/surfaces/surfaces_output_surface.cc
rename to components/mus/surfaces/direct_output_surface.cc
index 46ccdb6..048e5a7 100644
--- a/components/mus/surfaces/surfaces_output_surface.cc
+++ b/components/mus/surfaces/direct_output_surface.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 "components/mus/surfaces/surfaces_output_surface.h"
+#include "components/mus/surfaces/direct_output_surface.h"
 
 #include "base/bind.h"
 #include "cc/output/compositor_frame.h"
diff --git a/components/mus/surfaces/surfaces_output_surface.h b/components/mus/surfaces/direct_output_surface.h
similarity index 79%
rename from components/mus/surfaces/surfaces_output_surface.h
rename to components/mus/surfaces/direct_output_surface.h
index 3bd62df..f4be72712 100644
--- a/components/mus/surfaces/surfaces_output_surface.h
+++ b/components/mus/surfaces/direct_output_surface.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 COMPONENTS_MUS_SURFACES_SURFACES_OUTPUT_SURFACE_H_
-#define COMPONENTS_MUS_SURFACES_SURFACES_OUTPUT_SURFACE_H_
+#ifndef COMPONENTS_MUS_SURFACES_DIRECT_OUTPUT_SURFACE_H_
+#define COMPONENTS_MUS_SURFACES_DIRECT_OUTPUT_SURFACE_H_
 
 #include "cc/output/output_surface.h"
 
@@ -26,4 +26,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SURFACES_SURFACES_OUTPUT_SURFACE_H_
\ No newline at end of file
+#endif  // COMPONENTS_MUS_SURFACES_DIRECT_OUTPUT_SURFACE_H_
diff --git a/components/mus/surfaces/top_level_display_client.cc b/components/mus/surfaces/top_level_display_client.cc
index d7ec91e8..aba70d0 100644
--- a/components/mus/surfaces/top_level_display_client.cc
+++ b/components/mus/surfaces/top_level_display_client.cc
@@ -8,8 +8,8 @@
 #include "cc/surfaces/display.h"
 #include "cc/surfaces/surface.h"
 #include "components/mus/gles2/gpu_state.h"
+#include "components/mus/surfaces/direct_output_surface.h"
 #include "components/mus/surfaces/surfaces_context_provider.h"
-#include "components/mus/surfaces/surfaces_output_surface.h"
 #include "components/mus/surfaces/surfaces_scheduler.h"
 #include "components/mus/surfaces/surfaces_state.h"
 
@@ -68,14 +68,6 @@
   surfaces_state_->scheduler()->SetNeedsDraw();
 }
 
-const cc::CompositorFrame*
-TopLevelDisplayClient::GetLastCompositorFrame() const {
-  cc::Surface* surface = surfaces_state_->manager()->GetSurfaceForId(cc_id_);
-  if (!surface)
-    return nullptr;
-  return surface->GetEligibleFrame();
-}
-
 void TopLevelDisplayClient::CommitVSyncParameters(base::TimeTicks timebase,
                                                   base::TimeDelta interval) {}
 
diff --git a/components/mus/surfaces/top_level_display_client.h b/components/mus/surfaces/top_level_display_client.h
index 3d714e7..0b58da1 100644
--- a/components/mus/surfaces/top_level_display_client.h
+++ b/components/mus/surfaces/top_level_display_client.h
@@ -41,10 +41,8 @@
 
   void SubmitCompositorFrame(scoped_ptr<cc::CompositorFrame> frame,
                              const base::Closure& callback);
-
-  const cc::CompositorFrame* GetLastCompositorFrame() const;
-
   const cc::SurfaceId& surface_id() const { return cc_id_; }
+
  private:
   // DisplayClient implementation.
   // TODO(rjkroege, fsamuel): This won't work correctly with multiple displays.
diff --git a/components/mus/view_locator.cc b/components/mus/view_locator.cc
deleted file mode 100644
index 40cda4e..0000000
--- a/components/mus/view_locator.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/mus/view_locator.h"
-
-#include "components/mus/server_view.h"
-
-namespace mus {
-
-const ServerView* FindDeepestVisibleView(const ServerView* view,
-                                         const gfx::Point& location) {
-  for (const ServerView* child : view->GetChildren()) {
-    if (!child->visible())
-      continue;
-
-    // TODO(sky): support transform.
-    const gfx::Point child_location(location.x() - child->bounds().x(),
-                                    location.y() - child->bounds().y());
-    if (child_location.x() >= 0 && child_location.y() >= 0 &&
-        child_location.x() < child->bounds().width() &&
-        child_location.y() < child->bounds().height()) {
-      return FindDeepestVisibleView(child, child_location);
-    }
-  }
-  return view;
-}
-
-ServerView* FindDeepestVisibleView(ServerView* view,
-                                   const gfx::Point& location) {
-  return const_cast<ServerView*>(
-      FindDeepestVisibleView(const_cast<const ServerView*>(view), location));
-}
-
-}  // namespace mus
diff --git a/components/mus/view_locator.h b/components/mus/view_locator.h
deleted file mode 100644
index 883c625..0000000
--- a/components/mus/view_locator.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_MUS_VIEW_LOCATOR_H_
-#define COMPONENTS_MUS_VIEW_LOCATOR_H_
-
-namespace gfx {
-class Point;
-}
-
-namespace mus {
-
-class ServerView;
-
-// Finds the deepest visible view that contains the specified location.
-const ServerView* FindDeepestVisibleView(const ServerView* view,
-                                         const gfx::Point& location);
-ServerView* FindDeepestVisibleView(ServerView* view,
-                                   const gfx::Point& location);
-
-}  // namespace mus
-
-#endif  // COMPONENTS_MUS_VIEW_LOCATOR_H_
diff --git a/components/mus/vm/BUILD.gn b/components/mus/vm/BUILD.gn
new file mode 100644
index 0000000..d660c849
--- /dev/null
+++ b/components/mus/vm/BUILD.gn
@@ -0,0 +1,171 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ui.gni")
+import("//testing/test.gni")
+import("//mojo/public/mojo_application.gni")
+
+source_set("lib") {
+  sources = [
+    "access_policy.h",
+    "access_policy_delegate.h",
+    "client_connection.cc",
+    "client_connection.h",
+    "connection_manager.cc",
+    "connection_manager.h",
+    "connection_manager_delegate.h",
+    "default_access_policy.cc",
+    "default_access_policy.h",
+    "display_manager.cc",
+    "display_manager.h",
+    "display_manager_delegate.h",
+    "display_manager_factory.h",
+    "event_dispatcher.cc",
+    "event_dispatcher.h",
+    "focus_controller.cc",
+    "focus_controller.h",
+    "focus_controller_delegate.h",
+    "server_view.cc",
+    "server_view.h",
+    "server_view_delegate.h",
+    "server_view_drawn_tracker.cc",
+    "server_view_drawn_tracker.h",
+    "server_view_drawn_tracker_observer.h",
+    "server_view_observer.h",
+    "view_coordinate_conversions.cc",
+    "view_coordinate_conversions.h",
+    "view_tree_host_connection.cc",
+    "view_tree_host_connection.h",
+    "view_tree_host_delegate.h",
+    "view_tree_host_impl.cc",
+    "view_tree_host_impl.h",
+    "view_tree_impl.cc",
+    "view_tree_impl.h",
+    "window_manager_access_policy.cc",
+    "window_manager_access_policy.h",
+  ]
+
+  deps = [
+    "//base",
+    "//cc",
+    "//cc/surfaces",
+    "//cc/surfaces:surface_id",
+    "//components/mus/gles2:gles2",
+    "//components/mus/public/cpp:common",
+    "//components/mus/public/interfaces",
+    "//components/mus/surfaces",
+    "//mojo/application/public/cpp",
+    "//mojo/common:common_base",
+    "//mojo/common:tracing_impl",
+    "//mojo/converters/geometry",
+    "//mojo/converters/ime",
+    "//mojo/converters/input_events",
+    "//mojo/converters/surfaces",
+    "//third_party/mojo/src/mojo/public/cpp/bindings:callback",
+    "//ui/events",
+    "//ui/events/platform",
+    "//ui/gfx",
+    "//ui/gfx/geometry",
+    "//ui/gl:gl",
+    "//ui/gl:test_support",
+    "//ui/mojo/events:interfaces",
+    "//ui/mojo/geometry:interfaces",
+    "//ui/platform_window:platform_impls",
+    "//ui/platform_window:platform_window",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+
+  sources = [
+    "test_change_tracker.cc",
+    "test_change_tracker.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/mus/public/cpp",
+    "//components/mus/public/cpp:common",
+    "//components/mus/public/interfaces",
+    "//mojo/common",
+    "//third_party/mojo/src/mojo/public/cpp/bindings:bindings",
+    "//ui/mojo/geometry:interfaces",
+  ]
+}
+
+group("tests") {
+  testonly = true
+  deps = [
+    ":apptests",
+    ":view_manager_unittests",
+    "//components/mus/public/cpp/tests:mojo_view_manager_lib_unittests",
+  ]
+}
+
+test("view_manager_unittests") {
+  sources = [
+    "focus_controller_unittest.cc",
+    "server_view_drawn_tracker_unittest.cc",
+    "test_server_view_delegate.cc",
+    "test_server_view_delegate.h",
+    "view_coordinate_conversions_unittest.cc",
+    "view_tree_unittest.cc",
+  ]
+
+  deps = [
+    ":test_support",
+    ":lib",
+    "//base",
+    "//base/test:test_config",
+    "//components/mus/surfaces",
+    "//components/mus/public/cpp:common",
+    "//components/mus/public/interfaces",
+    "//mojo/application/public/interfaces",
+    "//mojo/converters/geometry",
+    "//mojo/converters/input_events",
+    "//mojo/converters/transform",
+    "//mojo/environment:chromium",
+    "//mojo/platform_handle",
+    "//third_party/mojo/src/mojo/edk/test:run_all_unittests",
+    "//third_party/mojo/src/mojo/public/cpp/bindings:bindings",
+    "//ui/mojo/geometry:interfaces",
+    "//ui/mojo/events:interfaces",
+    "//testing/gtest",
+    "//ui/gfx",
+    "//ui/gfx:test_support",
+    "//ui/gfx/geometry",
+  ]
+
+  if (!is_android) {  # TODO(GYP) Enable on Android when osmesa links.
+    deps += [ "//third_party/mesa:osmesa" ]
+  }
+}
+
+mojo_native_application("apptests") {
+  output_name = "mus_apptests"
+  testonly = true
+
+  sources = [
+    "view_manager_client_apptest.cc",
+    "view_tree_apptest.cc",
+  ]
+
+  deps = [
+    ":test_support",
+    "//base",
+    "//base/test:test_config",
+    "//components/mus/public/cpp",
+    "//components/mus/public/cpp/tests:test_support",
+    "//components/mus/public/interfaces",
+    "//mojo/application/public/cpp:sources",
+    "//mojo/application/public/cpp:test_support",
+    "//ui/mojo/geometry:interfaces",
+    "//ui/mojo/geometry:util",
+  ]
+
+  data_deps = [
+    ":lib",
+  ]
+}
diff --git a/components/mus/access_policy.h b/components/mus/vm/access_policy.h
similarity index 93%
rename from components/mus/access_policy.h
rename to components/mus/vm/access_policy.h
index 7537d30..d28e678 100644
--- a/components/mus/access_policy.h
+++ b/components/mus/vm/access_policy.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_ACCESS_POLICY_H_
-#define COMPONENTS_MUS_ACCESS_POLICY_H_
+#ifndef COMPONENTS_MUS_VM_ACCESS_POLICY_H_
+#define COMPONENTS_MUS_VM_ACCESS_POLICY_H_
 
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/mus_constants.mojom.h"
+#include "components/mus/vm/ids.h"
 
 namespace mus {
 
@@ -56,4 +56,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_ACCESS_POLICY_H_
+#endif  // COMPONENTS_MUS_VM_ACCESS_POLICY_H_
diff --git a/components/mus/access_policy_delegate.h b/components/mus/vm/access_policy_delegate.h
similarity index 84%
rename from components/mus/access_policy_delegate.h
rename to components/mus/vm/access_policy_delegate.h
index 146a5b6..60f5e93 100644
--- a/components/mus/access_policy_delegate.h
+++ b/components/mus/vm/access_policy_delegate.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_ACCESS_POLICY_DELEGATE_H_
-#define COMPONENTS_MUS_ACCESS_POLICY_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_ACCESS_POLICY_DELEGATE_H_
+#define COMPONENTS_MUS_VM_ACCESS_POLICY_DELEGATE_H_
 
 #include <vector>
 
 #include "base/containers/hash_tables.h"
-#include "components/mus/ids.h"
+#include "components/mus/vm/ids.h"
 
 namespace mus {
 
@@ -37,4 +37,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_ACCESS_POLICY_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_ACCESS_POLICY_DELEGATE_H_
diff --git a/components/mus/client_connection.cc b/components/mus/vm/client_connection.cc
similarity index 87%
rename from components/mus/client_connection.cc
rename to components/mus/vm/client_connection.cc
index a785084..48c8a63b 100644
--- a/components/mus/client_connection.cc
+++ b/components/mus/vm/client_connection.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/client_connection.h"
+#include "components/mus/vm/client_connection.h"
 
-#include "components/mus/connection_manager.h"
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/view_tree_impl.h"
 
 namespace mus {
 
diff --git a/components/mus/client_connection.h b/components/mus/vm/client_connection.h
similarity index 91%
rename from components/mus/client_connection.h
rename to components/mus/vm/client_connection.h
index 6954141..ecae3a94 100644
--- a/components/mus/client_connection.h
+++ b/components/mus/vm/client_connection.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 COMPONENTS_MUS_CLIENT_CONNECTION_H_
-#define COMPONENTS_MUS_CLIENT_CONNECTION_H_
+#ifndef COMPONENTS_MUS_VM_CLIENT_CONNECTION_H_
+#define COMPONENTS_MUS_VM_CLIENT_CONNECTION_H_
 
 #include "base/memory/scoped_ptr.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
@@ -54,4 +54,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_CLIENT_CONNECTION_H_
+#endif  // COMPONENTS_MUS_VM_CLIENT_CONNECTION_H_
diff --git a/components/mus/connection_manager.cc b/components/mus/vm/connection_manager.cc
similarity index 96%
rename from components/mus/connection_manager.cc
rename to components/mus/vm/connection_manager.cc
index b82ed5f4..0f01ba7 100644
--- a/components/mus/connection_manager.cc
+++ b/components/mus/vm/connection_manager.cc
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/connection_manager.h"
+#include "components/mus/vm/connection_manager.h"
 
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/quads/shared_quad_state.h"
 #include "cc/quads/surface_draw_quad.h"
-#include "components/mus/client_connection.h"
-#include "components/mus/connection_manager_delegate.h"
-#include "components/mus/server_view.h"
-#include "components/mus/view_coordinate_conversions.h"
-#include "components/mus/view_tree_host_connection.h"
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/client_connection.h"
+#include "components/mus/vm/connection_manager_delegate.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/view_coordinate_conversions.h"
+#include "components/mus/vm/view_tree_host_connection.h"
+#include "components/mus/vm/view_tree_impl.h"
 #include "mojo/application/public/cpp/application_connection.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/converters/input_events/input_events_type_converters.h"
@@ -454,13 +454,10 @@
   // better home for it. http://crbug.com/533029.
   cc::SurfaceDrawQuad* surface_quad =
       render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
-  surface_quad->SetAll(
-      sqs,
-      input->rect.To<gfx::Rect>(),
-      input->opaque_rect.To<gfx::Rect>(),
-      input->visible_rect.To<gfx::Rect>(),
-      input->needs_blending,
-      view->surface_id());
+  surface_quad->SetAll(sqs, input->rect.To<gfx::Rect>(),
+                       input->opaque_rect.To<gfx::Rect>(),
+                       input->visible_rect.To<gfx::Rect>(),
+                       input->needs_blending, view->surface_id());
   return true;
 }
 
diff --git a/components/mus/connection_manager.h b/components/mus/vm/connection_manager.h
similarity index 94%
rename from components/mus/connection_manager.h
rename to components/mus/vm/connection_manager.h
index 673ec12..d810f62 100644
--- a/components/mus/connection_manager.h
+++ b/components/mus/vm/connection_manager.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 COMPONENTS_MUS_CONNECTION_MANAGER_H_
-#define COMPONENTS_MUS_CONNECTION_MANAGER_H_
+#ifndef COMPONENTS_MUS_VM_CONNECTION_MANAGER_H_
+#define COMPONENTS_MUS_VM_CONNECTION_MANAGER_H_
 
 #include <map>
 #include <set>
@@ -11,14 +11,14 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/timer/timer.h"
-#include "components/mus/focus_controller_delegate.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
 #include "components/mus/public/interfaces/view_tree_host.mojom.h"
-#include "components/mus/server_view_delegate.h"
-#include "components/mus/server_view_observer.h"
 #include "components/mus/surfaces/surfaces_state.h"
-#include "components/mus/view_tree_host_impl.h"
+#include "components/mus/vm/focus_controller_delegate.h"
+#include "components/mus/vm/ids.h"
+#include "components/mus/vm/server_view_delegate.h"
+#include "components/mus/vm/server_view_observer.h"
+#include "components/mus/vm/view_tree_host_impl.h"
 #include "mojo/converters/surfaces/custom_surface_converter.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
@@ -153,9 +153,6 @@
   // ViewTreeHost implementation helper; see mojom for details.
   bool CloneAndAnimate(const ViewId& view_id);
 
-  // Dispatches |event| directly to the appropriate connection for |view|.
-  void DispatchInputEventToView(const ServerView* view, mojo::EventPtr event);
-
   // These functions trivially delegate to all ViewTreeImpls, which in
   // term notify their clients.
   void ProcessViewDestroyed(ServerView* view);
@@ -262,4 +259,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_CONNECTION_MANAGER_H_
+#endif  // COMPONENTS_MUS_VM_CONNECTION_MANAGER_H_
diff --git a/components/mus/connection_manager_delegate.h b/components/mus/vm/connection_manager_delegate.h
similarity index 88%
rename from components/mus/connection_manager_delegate.h
rename to components/mus/vm/connection_manager_delegate.h
index 8d7a025..a96071b 100644
--- a/components/mus/connection_manager_delegate.h
+++ b/components/mus/vm/connection_manager_delegate.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 COMPONENTS_MUS_CONNECTION_MANAGER_DELEGATE_H_
-#define COMPONENTS_MUS_CONNECTION_MANAGER_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_CONNECTION_MANAGER_DELEGATE_H_
+#define COMPONENTS_MUS_VM_CONNECTION_MANAGER_DELEGATE_H_
 
 #include <string>
 
@@ -45,4 +45,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_CONNECTION_MANAGER_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_CONNECTION_MANAGER_DELEGATE_H_
diff --git a/components/mus/default_access_policy.cc b/components/mus/vm/default_access_policy.cc
similarity index 96%
rename from components/mus/default_access_policy.cc
rename to components/mus/vm/default_access_policy.cc
index f5ffd78d..852f310 100644
--- a/components/mus/default_access_policy.cc
+++ b/components/mus/vm/default_access_policy.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/default_access_policy.h"
+#include "components/mus/vm/default_access_policy.h"
 
-#include "components/mus/access_policy_delegate.h"
-#include "components/mus/server_view.h"
+#include "components/mus/vm/access_policy_delegate.h"
+#include "components/mus/vm/server_view.h"
 
 namespace mus {
 
diff --git a/components/mus/default_access_policy.h b/components/mus/vm/default_access_policy.h
similarity index 91%
rename from components/mus/default_access_policy.h
rename to components/mus/vm/default_access_policy.h
index 7ee9b88..194c903 100644
--- a/components/mus/default_access_policy.h
+++ b/components/mus/vm/default_access_policy.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_DEFAULT_ACCESS_POLICY_H_
-#define COMPONENTS_MUS_DEFAULT_ACCESS_POLICY_H_
+#ifndef COMPONENTS_MUS_VM_DEFAULT_ACCESS_POLICY_H_
+#define COMPONENTS_MUS_VM_DEFAULT_ACCESS_POLICY_H_
 
 #include "base/basictypes.h"
-#include "components/mus/access_policy.h"
+#include "components/mus/vm/access_policy.h"
 
 namespace mus {
 
@@ -54,4 +54,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_DEFAULT_ACCESS_POLICY_H_
+#endif  // COMPONENTS_MUS_VM_DEFAULT_ACCESS_POLICY_H_
diff --git a/components/mus/display_manager.cc b/components/mus/vm/display_manager.cc
similarity index 82%
rename from components/mus/display_manager.cc
rename to components/mus/vm/display_manager.cc
index 52c5cd8..d130318 100644
--- a/components/mus/display_manager.cc
+++ b/components/mus/vm/display_manager.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 "components/mus/display_manager.h"
+#include "components/mus/vm/display_manager.h"
 
 #include "base/numerics/safe_conversions.h"
 #include "cc/output/compositor_frame.h"
@@ -10,13 +10,13 @@
 #include "cc/quads/render_pass.h"
 #include "cc/quads/shared_quad_state.h"
 #include "cc/quads/surface_draw_quad.h"
-#include "components/mus/display_manager_factory.h"
 #include "components/mus/gles2/gpu_state.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
 #include "components/mus/public/interfaces/quads.mojom.h"
-#include "components/mus/server_view.h"
 #include "components/mus/surfaces/surfaces_state.h"
-#include "components/mus/view_coordinate_conversions.h"
+#include "components/mus/vm/display_manager_factory.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/view_coordinate_conversions.h"
 #include "mojo/application/public/cpp/application_connection.h"
 #include "mojo/application/public/cpp/application_impl.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
@@ -31,7 +31,6 @@
 #include "ui/gfx/display.h"
 #include "ui/platform_window/platform_ime_controller.h"
 #include "ui/platform_window/platform_window.h"
-#include "ui/platform_window/stub/stub_window.h"
 
 #if defined(OS_WIN)
 #include "ui/platform_window/win/win_window.h"
@@ -67,10 +66,9 @@
   // TODO(rjkroege, fsamuel): Make sure we're handling alpha correctly.
   const float combined_opacity = opacity * view->opacity();
   for (auto it = children.rbegin(); it != children.rend(); ++it) {
-    DrawViewTree(pass, *it, absolute_bounds.OffsetFromOrigin(),
-                combined_opacity,
-                view->parent() &&
-                    !view->surface_id().is_null() /* skip_view */);
+    DrawViewTree(
+        pass, *it, absolute_bounds.OffsetFromOrigin(), combined_opacity,
+        view->parent() && !view->surface_id().is_null() /* skip_view */);
   }
 
   if (skip_view || view->surface_id().is_null())
@@ -101,25 +99,22 @@
 
 // static
 DisplayManager* DisplayManager::Create(
-    bool is_headless,
     mojo::ApplicationImpl* app_impl,
     const scoped_refptr<GpuState>& gpu_state,
     const scoped_refptr<SurfacesState>& surfaces_state) {
   if (factory_) {
-    return factory_->CreateDisplayManager(is_headless, app_impl, gpu_state,
+    return factory_->CreateDisplayManager(app_impl, gpu_state,
                                           surfaces_state);
   }
-  return new DefaultDisplayManager(is_headless, app_impl, gpu_state,
+  return new DefaultDisplayManager(app_impl, gpu_state,
                                    surfaces_state);
 }
 
 DefaultDisplayManager::DefaultDisplayManager(
-    bool is_headless,
     mojo::ApplicationImpl* app_impl,
     const scoped_refptr<GpuState>& gpu_state,
     const scoped_refptr<SurfacesState>& surfaces_state)
-    : is_headless_(is_headless),
-      app_impl_(app_impl),
+    : app_impl_(app_impl),
       gpu_state_(gpu_state),
       surfaces_state_(surfaces_state),
       delegate_(nullptr),
@@ -135,24 +130,21 @@
   delegate_ = delegate;
 
   gfx::Rect bounds(metrics_.size_in_pixels.To<gfx::Size>());
-  if (is_headless_) {
-    platform_window_.reset(new ui::StubWindow(this));
-  } else {
 #if defined(OS_WIN)
-    platform_window_.reset(new ui::WinWindow(this, bounds));
+  platform_window_.reset(new ui::WinWindow(this, bounds));
 #elif defined(USE_X11)
-    platform_window_.reset(new ui::X11Window(this));
+  platform_window_.reset(new ui::X11Window(this));
 #elif defined(OS_ANDROID)
-    platform_window_.reset(new ui::PlatformWindowAndroid(this));
+  platform_window_.reset(new ui::PlatformWindowAndroid(this));
 #else
-    NOTREACHED() << "Unsupported platform";
+  NOTREACHED() << "Unsupported platform";
 #endif
-  }
   platform_window_->SetBounds(bounds);
   platform_window_->Show();
 }
 
 DefaultDisplayManager::~DefaultDisplayManager() {
+  delegate_->OnTopLevelSurfaceChanged(cc::SurfaceId());
   // Invalidate WeakPtrs now to avoid callbacks back into the
   // DefaultDisplayManager during destruction of |top_level_display_client_|.
   weak_factory_.InvalidateWeakPtrs();
@@ -254,10 +246,8 @@
   render_pass->damage_rect = dirty_rect_;
   render_pass->output_rect = gfx::Rect(metrics_.size_in_pixels.To<gfx::Size>());
 
-  DrawViewTree(render_pass.get(),
-               delegate_->GetRootView(),
-               gfx::Vector2d(), 1.0f,
-               false /* skip_view */);
+  DrawViewTree(render_pass.get(), delegate_->GetRootView(), gfx::Vector2d(),
+               1.0f, false /* skip_view */);
 
   scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
   frame_data->device_scale_factor = metrics_.device_pixel_ratio;
@@ -268,14 +258,6 @@
   return frame.Pass();
 }
 
-const cc::CompositorFrame*
-DefaultDisplayManager::GetLastCompositorFrame() const {
-  if (!top_level_display_client_)
-    return nullptr;
-
-  return top_level_display_client_->GetLastCompositorFrame();
-}
-
 void DefaultDisplayManager::OnBoundsChanged(const gfx::Rect& new_bounds) {
   UpdateMetrics(new_bounds.size(), metrics_.device_pixel_ratio);
 }
@@ -287,30 +269,7 @@
 
 void DefaultDisplayManager::DispatchEvent(ui::Event* event) {
   mojo::EventPtr mojo_event(mojo::Event::From(*event));
-  ViewId id;
-  if (event->IsLocatedEvent() && !!top_level_display_client_) {
-    ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
-    gfx::Point transformed_point(located_event->location());
-    gfx::Transform transform_to_target_surface;
-    cc::SurfaceId target_surface =
-        surfaces_state_->hit_tester()->GetTargetSurfaceAtPoint(
-            top_level_display_client_->surface_id(), located_event->location(),
-            &transform_to_target_surface);
-    transform_to_target_surface.TransformPoint(&transformed_point);
-    id = ViewIdFromTransportId(
-        cc::SurfaceIdAllocator::NamespaceForId(target_surface));
-
-    mojo::LocationData* location = nullptr;
-    if (mojo_event->pointer_data)
-      location = mojo_event->pointer_data->location.get();
-    else if (mojo_event->wheel_data)
-      location = mojo_event->wheel_data->location.get();
-
-    DCHECK(location);
-    location->x = transformed_point.x();
-    location->y = transformed_point.y();
-  }
-  delegate_->OnEvent(id, mojo_event.Pass());
+  delegate_->OnEvent(mojo_event.Pass());
 
   switch (event->type()) {
     case ui::ET_MOUSE_PRESSED:
@@ -352,7 +311,7 @@
             key_press_event->GetLocatedWindowsKeyboardCode(),
             key_press_event->GetText(), key_press_event->GetUnmodifiedText())));
 
-    delegate_->OnEvent(id, mojo::Event::From(char_event));
+    delegate_->OnEvent(mojo::Event::From(char_event));
   }
 #endif
 }
@@ -376,6 +335,8 @@
   if (widget != gfx::kNullAcceleratedWidget) {
     top_level_display_client_.reset(
         new TopLevelDisplayClient(widget, gpu_state_, surfaces_state_));
+    delegate_->OnTopLevelSurfaceChanged(
+        top_level_display_client_->surface_id());
   }
   UpdateMetrics(metrics_.size_in_pixels.To<gfx::Size>(), device_pixel_ratio);
 }
diff --git a/components/mus/display_manager.h b/components/mus/vm/display_manager.h
similarity index 92%
rename from components/mus/display_manager.h
rename to components/mus/vm/display_manager.h
index dbdc99b6..14d973e 100644
--- a/components/mus/display_manager.h
+++ b/components/mus/vm/display_manager.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 COMPONENTS_MUS_DISPLAY_MANAGER_H_
-#define COMPONENTS_MUS_DISPLAY_MANAGER_H_
+#ifndef COMPONENTS_MUS_VM_DISPLAY_MANAGER_H_
+#define COMPONENTS_MUS_VM_DISPLAY_MANAGER_H_
 
 #include <map>
 
@@ -11,9 +11,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
-#include "components/mus/display_manager_delegate.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
 #include "components/mus/surfaces/top_level_display_client.h"
+#include "components/mus/vm/display_manager_delegate.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/platform_window/platform_window_delegate.h"
@@ -50,7 +50,6 @@
   virtual ~DisplayManager() {}
 
   static DisplayManager* Create(
-      bool is_headless,
       mojo::ApplicationImpl* app_impl,
       const scoped_refptr<GpuState>& gpu_state,
       const scoped_refptr<SurfacesState>& surfaces_state);
@@ -86,8 +85,7 @@
 class DefaultDisplayManager : public DisplayManager,
                               public ui::PlatformWindowDelegate {
  public:
-  DefaultDisplayManager(bool is_headless,
-                        mojo::ApplicationImpl* app_impl,
+  DefaultDisplayManager(mojo::ApplicationImpl* app_impl,
                         const scoped_refptr<GpuState>& gpu_state,
                         const scoped_refptr<SurfacesState>& surfaces_state);
   ~DefaultDisplayManager() override;
@@ -115,7 +113,6 @@
   void DidDraw();
   void UpdateMetrics(const gfx::Size& size, float device_pixel_ratio);
   scoped_ptr<cc::CompositorFrame> GenerateCompositorFrame();
-  const cc::CompositorFrame* GetLastCompositorFrame() const;
 
   // ui::PlatformWindowDelegate:
   void OnBoundsChanged(const gfx::Rect& new_bounds) override;
@@ -129,7 +126,6 @@
                                     float device_pixel_ratio) override;
   void OnActivationChanged(bool active) override;
 
-  bool is_headless_;
   mojo::ApplicationImpl* app_impl_;
   scoped_refptr<GpuState> gpu_state_;
   scoped_refptr<SurfacesState> surfaces_state_;
@@ -150,4 +146,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_DISPLAY_MANAGER_H_
+#endif  // COMPONENTS_MUS_VM_DISPLAY_MANAGER_H_
diff --git a/components/mus/display_manager_delegate.h b/components/mus/vm/display_manager_delegate.h
similarity index 74%
rename from components/mus/display_manager_delegate.h
rename to components/mus/vm/display_manager_delegate.h
index 71c8967d..e37d3a8 100644
--- a/components/mus/display_manager_delegate.h
+++ b/components/mus/vm/display_manager_delegate.h
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_DISPLAY_MANAGER_DELEGATE_H_
-#define COMPONENTS_MUS_DISPLAY_MANAGER_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_DISPLAY_MANAGER_DELEGATE_H_
+#define COMPONENTS_MUS_VM_DISPLAY_MANAGER_DELEGATE_H_
 
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
+#include "components/mus/vm/ids.h"
+
+namespace cc {
+struct SurfaceId;
+}
 
 namespace mus {
 
@@ -24,17 +28,19 @@
   virtual void OnDisplayClosed() = 0;
 
   // Called when an event arrives.
-  virtual void OnEvent(ViewId id, mojo::EventPtr event) = 0;
+  virtual void OnEvent(mojo::EventPtr event) = 0;
 
   // Signals that the metrics of this display's viewport has changed.
   virtual void OnViewportMetricsChanged(
       const mojo::ViewportMetrics& old_metrics,
       const mojo::ViewportMetrics& new_metrics) = 0;
 
+  virtual void OnTopLevelSurfaceChanged(cc::SurfaceId surface_id) = 0;
+
  protected:
   virtual ~DisplayManagerDelegate() {}
 };
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_DISPLAY_MANAGER_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_DISPLAY_MANAGER_DELEGATE_H_
diff --git a/components/mus/display_manager_factory.h b/components/mus/vm/display_manager_factory.h
similarity index 80%
rename from components/mus/display_manager_factory.h
rename to components/mus/vm/display_manager_factory.h
index e59424f..358b1bc 100644
--- a/components/mus/display_manager_factory.h
+++ b/components/mus/vm/display_manager_factory.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 COMPONENTS_MUS_DISPLAY_MANAGER_FACTORY_H_
-#define COMPONENTS_MUS_DISPLAY_MANAGER_FACTORY_H_
+#ifndef COMPONENTS_MUS_VM_DISPLAY_MANAGER_FACTORY_H_
+#define COMPONENTS_MUS_VM_DISPLAY_MANAGER_FACTORY_H_
 
 #include "components/mus/gles2/gpu_state.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h"
@@ -21,7 +21,6 @@
 class DisplayManagerFactory {
  public:
   virtual DisplayManager* CreateDisplayManager(
-      bool is_headless,
       mojo::ApplicationImpl* app_impl,
       const scoped_refptr<GpuState>& gpu_state,
       const scoped_refptr<SurfacesState>& surfaces_state) = 0;
@@ -29,4 +28,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_DISPLAY_MANAGER_FACTORY_H_
+#endif  // COMPONENTS_MUS_VM_DISPLAY_MANAGER_FACTORY_H_
diff --git a/components/mus/vm/event_dispatcher.cc b/components/mus/vm/event_dispatcher.cc
new file mode 100644
index 0000000..2fd0a6b
--- /dev/null
+++ b/components/mus/vm/event_dispatcher.cc
@@ -0,0 +1,155 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/mus/vm/event_dispatcher.h"
+
+#include "cc/surfaces/surface_id.h"
+#include "components/mus/surfaces/surfaces_state.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/server_view_delegate.h"
+#include "components/mus/vm/view_coordinate_conversions.h"
+#include "components/mus/vm/view_tree_host_impl.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+
+namespace mus {
+
+EventDispatcher::EventDispatcher(ViewTreeHostImpl* view_tree_host)
+    : view_tree_host_(view_tree_host) {}
+
+EventDispatcher::~EventDispatcher() {}
+
+void EventDispatcher::AddAccelerator(uint32_t id,
+                                     mojo::KeyboardCode keyboard_code,
+                                     mojo::EventFlags flags) {
+#if !defined(NDEBUG)
+  for (const auto& pair : accelerators_) {
+    DCHECK(pair.first != id);
+    DCHECK(pair.second.keyboard_code != keyboard_code ||
+           pair.second.flags != flags);
+  }
+#endif
+  accelerators_.insert(Entry(id, Accelerator(keyboard_code, flags)));
+}
+
+void EventDispatcher::RemoveAccelerator(uint32_t id) {
+  auto it = accelerators_.find(id);
+  DCHECK(it != accelerators_.end());
+  accelerators_.erase(it);
+}
+
+void EventDispatcher::OnEvent(mojo::EventPtr event) {
+  if (event->action == mojo::EVENT_TYPE_KEY_PRESSED &&
+      !event->key_data->is_char) {
+    uint32_t accelerator = 0u;
+    if (FindAccelerator(*event, &accelerator)) {
+      view_tree_host_->OnAccelerator(accelerator, event.Pass());
+      return;
+    }
+  }
+
+  ServerView* target = FindEventTarget(event.get());
+  if (target) {
+    // Update focus on pointer-down.
+    if (event->action == mojo::EVENT_TYPE_POINTER_DOWN)
+      view_tree_host_->SetFocusedView(target);
+    view_tree_host_->DispatchInputEventToView(target, event.Pass());
+  }
+}
+
+bool EventDispatcher::FindAccelerator(const mojo::Event& event,
+                                      uint32_t* accelerator_id) {
+  DCHECK(event.key_data);
+  for (const auto& pair : accelerators_) {
+    if (pair.second.keyboard_code == event.key_data->windows_key_code &&
+        pair.second.flags == event.flags) {
+      *accelerator_id = pair.first;
+      return true;
+    }
+  }
+  return false;
+}
+
+ServerView* EventDispatcher::FindEventTarget(mojo::Event* event) {
+  ServerView* focused_view = view_tree_host_->GetFocusedView();
+  if (event->key_data)
+    return focused_view;
+
+  DCHECK(event->pointer_data || event->wheel_data) << "Unknown event type: "
+                                                   << event->action;
+
+  mojo::LocationData* event_location = nullptr;
+  if (event->pointer_data)
+    event_location = event->pointer_data->location.get();
+  else if (event->wheel_data)
+    event_location = event->wheel_data->location.get();
+  DCHECK(event_location);
+  gfx::Point location(static_cast<int>(event_location->x),
+                      static_cast<int>(event_location->y));
+  ServerView* target = focused_view;
+  ServerView* root = view_tree_host_->root_view();
+  if (event->action == mojo::EVENT_TYPE_POINTER_DOWN || !target ||
+      !root->Contains(target)) {
+    target = FindDeepestVisibleViewFromSurface(&location);
+    // Surface-based hit-testing will not return a valid target if no
+    // compositor-frame have been submitted (e.g. in unit-tests).
+    if (!target)
+      target = FindDeepestVisibleView(root, &location);
+    CHECK(target);
+  } else {
+    gfx::Point old_point = location;
+    location = ConvertPointBetweenViews(root, target, location);
+  }
+
+  event_location->x = location.x();
+  event_location->y = location.y();
+  return target;
+}
+
+ServerView* EventDispatcher::FindDeepestVisibleView(ServerView* view,
+                                                    gfx::Point* location) {
+  for (ServerView* child : view->GetChildren()) {
+    if (!child->visible())
+      continue;
+
+    // TODO(sky): support transform.
+    gfx::Point child_location(location->x() - child->bounds().x(),
+                              location->y() - child->bounds().y());
+    if (child_location.x() >= 0 && child_location.y() >= 0 &&
+        child_location.x() < child->bounds().width() &&
+        child_location.y() < child->bounds().height()) {
+      *location = child_location;
+      return FindDeepestVisibleView(child, location);
+    }
+  }
+  return view;
+}
+
+ServerView* EventDispatcher::FindDeepestVisibleViewFromSurface(
+    gfx::Point* location) {
+  if (view_tree_host_->surface_id().is_null())
+    return nullptr;
+
+  gfx::Transform transform_to_target_surface;
+  cc::SurfaceId target_surface =
+      view_tree_host_->root_view()->delegate()
+          ->GetSurfacesState()
+          ->hit_tester()
+          ->GetTargetSurfaceAtPoint(view_tree_host_->surface_id(), *location,
+                                    &transform_to_target_surface);
+  ViewId id = ViewIdFromTransportId(
+      cc::SurfaceIdAllocator::NamespaceForId(target_surface));
+  ServerView* target = view_tree_host_->connection_manager()->GetView(id);
+  // TODO(fsamuel): This should be a DCHECK but currently we use stale
+  // information to decide where to route input events. This should be fixed
+  // once we implement a UI scheduler.
+  if (target) {
+    transform_to_target_surface.TransformPoint(location);
+    return target;
+  }
+  return nullptr;
+}
+
+}  // namespace mus
diff --git a/components/mus/event_dispatcher.h b/components/mus/vm/event_dispatcher.h
similarity index 76%
rename from components/mus/event_dispatcher.h
rename to components/mus/vm/event_dispatcher.h
index 0bb5200..28cecc4 100644
--- a/components/mus/event_dispatcher.h
+++ b/components/mus/vm/event_dispatcher.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 COMPONENTS_MUS_EVENT_DISPATCHER_H_
-#define COMPONENTS_MUS_EVENT_DISPATCHER_H_
+#ifndef COMPONENTS_MUS_VM_EVENT_DISPATCHER_H_
+#define COMPONENTS_MUS_VM_EVENT_DISPATCHER_H_
 
 #include <map>
 
@@ -12,6 +12,10 @@
 #include "ui/mojo/events/input_events.mojom.h"
 #include "ui/mojo/events/input_key_codes.mojom.h"
 
+namespace gfx {
+class Point;
+}
+
 namespace mus {
 
 class ServerView;
@@ -57,6 +61,15 @@
   // make sure it is in the returned target's coordinate space.
   ServerView* FindEventTarget(mojo::Event* event);
 
+  // Finds the deepest visible view that contains the specified location, and
+  // updates |location| to be in the returned view's coordinate space.
+  ServerView* FindDeepestVisibleView(ServerView* view, gfx::Point* location);
+
+  // Finds the deepest visible view for the specified location based on surface
+  // hit-testing. Updates |location| to be in the returned view's coordinate
+  // space.
+  ServerView* FindDeepestVisibleViewFromSurface(gfx::Point* location);
+
   ViewTreeHostImpl* view_tree_host_;
 
   using Entry = std::pair<uint32_t, Accelerator>;
@@ -67,4 +80,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_EVENT_DISPATCHER_H_
+#endif  // COMPONENTS_MUS_VM_EVENT_DISPATCHER_H_
diff --git a/components/mus/focus_controller.cc b/components/mus/vm/focus_controller.cc
similarity index 86%
rename from components/mus/focus_controller.cc
rename to components/mus/vm/focus_controller.cc
index f2b56fc1..1d0d8931 100644
--- a/components/mus/focus_controller.cc
+++ b/components/mus/vm/focus_controller.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 "components/mus/focus_controller.h"
+#include "components/mus/vm/focus_controller.h"
 
-#include "components/mus/focus_controller_delegate.h"
-#include "components/mus/server_view.h"
-#include "components/mus/server_view_drawn_tracker.h"
+#include "components/mus/vm/focus_controller_delegate.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/server_view_drawn_tracker.h"
 
 namespace mus {
 
diff --git a/components/mus/focus_controller.h b/components/mus/vm/focus_controller.h
similarity index 86%
rename from components/mus/focus_controller.h
rename to components/mus/vm/focus_controller.h
index c732a94..d0c17d74 100644
--- a/components/mus/focus_controller.h
+++ b/components/mus/vm/focus_controller.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_FOCUS_CONTROLLER_H_
-#define COMPONENTS_MUS_FOCUS_CONTROLLER_H_
+#ifndef COMPONENTS_MUS_VM_FOCUS_CONTROLLER_H_
+#define COMPONENTS_MUS_VM_FOCUS_CONTROLLER_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "components/mus/server_view_drawn_tracker_observer.h"
+#include "components/mus/vm/server_view_drawn_tracker_observer.h"
 
 namespace mus {
 
@@ -49,4 +49,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_FOCUS_CONTROLLER_H_
+#endif  // COMPONENTS_MUS_VM_FOCUS_CONTROLLER_H_
diff --git a/components/mus/focus_controller_delegate.h b/components/mus/vm/focus_controller_delegate.h
similarity index 72%
rename from components/mus/focus_controller_delegate.h
rename to components/mus/vm/focus_controller_delegate.h
index 60556e2..c0a77dd 100644
--- a/components/mus/focus_controller_delegate.h
+++ b/components/mus/vm/focus_controller_delegate.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 COMPONENTS_MUS_FOCUS_CONTROLLER_DELEGATE_H_
-#define COMPONENTS_MUS_FOCUS_CONTROLLER_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_FOCUS_CONTROLLER_DELEGATE_H_
+#define COMPONENTS_MUS_VM_FOCUS_CONTROLLER_DELEGATE_H_
 
 namespace mus {
 
@@ -20,4 +20,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_FOCUS_CONTROLLER_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_FOCUS_CONTROLLER_DELEGATE_H_
diff --git a/components/mus/focus_controller_unittest.cc b/components/mus/vm/focus_controller_unittest.cc
similarity index 93%
rename from components/mus/focus_controller_unittest.cc
rename to components/mus/vm/focus_controller_unittest.cc
index 162bcea..5e1c3c1 100644
--- a/components/mus/focus_controller_unittest.cc
+++ b/components/mus/vm/focus_controller_unittest.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 "components/mus/focus_controller.h"
+#include "components/mus/vm/focus_controller.h"
 
-#include "components/mus/focus_controller_delegate.h"
-#include "components/mus/server_view.h"
-#include "components/mus/test_server_view_delegate.h"
+#include "components/mus/vm/focus_controller_delegate.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/test_server_view_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mus {
diff --git a/components/mus/ids.h b/components/mus/vm/ids.h
similarity index 93%
rename from components/mus/ids.h
rename to components/mus/vm/ids.h
index 7099a58f..cb9ad75a 100644
--- a/components/mus/ids.h
+++ b/components/mus/vm/ids.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 COMPONENTS_MUS_IDS_H_
-#define COMPONENTS_MUS_IDS_H_
+#ifndef COMPONENTS_MUS_VM_IDS_H_
+#define COMPONENTS_MUS_VM_IDS_H_
 
 #include "components/mus/public/cpp/types.h"
 #include "components/mus/public/cpp/util.h"
@@ -51,4 +51,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_IDS_H_
+#endif  // COMPONENTS_MUS_VM_IDS_H_
diff --git a/components/mus/server_view.cc b/components/mus/vm/server_view.cc
similarity index 98%
rename from components/mus/server_view.cc
rename to components/mus/vm/server_view.cc
index d319033..968d7342 100644
--- a/components/mus/server_view.cc
+++ b/components/mus/vm/server_view.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 "components/mus/server_view.h"
+#include "components/mus/vm/server_view.h"
 
 #include <inttypes.h>
 
 #include "base/strings/stringprintf.h"
-#include "components/mus/server_view_delegate.h"
-#include "components/mus/server_view_observer.h"
 #include "components/mus/surfaces/surfaces_state.h"
+#include "components/mus/vm/server_view_delegate.h"
+#include "components/mus/vm/server_view_observer.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/converters/surfaces/surfaces_type_converters.h"
 
diff --git a/components/mus/server_view.h b/components/mus/vm/server_view.h
similarity index 95%
rename from components/mus/server_view.h
rename to components/mus/vm/server_view.h
index afd82d85..d72a68f 100644
--- a/components/mus/server_view.h
+++ b/components/mus/vm/server_view.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 COMPONENTS_MUS_SERVER_VIEW_H_
-#define COMPONENTS_MUS_SERVER_VIEW_H_
+#ifndef COMPONENTS_MUS_VM_SERVER_VIEW_H_
+#define COMPONENTS_MUS_VM_SERVER_VIEW_H_
 
 #include <vector>
 
@@ -13,8 +13,8 @@
 #include "cc/surfaces/surface_factory_client.h"
 #include "cc/surfaces/surface_id.h"
 #include "cc/surfaces/surface_id_allocator.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
+#include "components/mus/vm/ids.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/transform.h"
@@ -106,6 +106,8 @@
     return last_submitted_frame_size_;
   }
 
+  ServerViewDelegate* delegate() { return delegate_; }
+
   // mojo::Surface:
   void SubmitCompositorFrame(
       mojo::CompositorFramePtr frame,
@@ -150,4 +152,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SERVER_VIEW_H_
+#endif  // COMPONENTS_MUS_VM_SERVER_VIEW_H_
diff --git a/components/mus/server_view_delegate.h b/components/mus/vm/server_view_delegate.h
similarity index 86%
rename from components/mus/server_view_delegate.h
rename to components/mus/vm/server_view_delegate.h
index abe0aaa..6ab4f48c 100644
--- a/components/mus/server_view_delegate.h
+++ b/components/mus/vm/server_view_delegate.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 COMPONENTS_MUS_SERVER_VIEW_DELEGATE_H_
-#define COMPONENTS_MUS_SERVER_VIEW_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_SERVER_VIEW_DELEGATE_H_
+#define COMPONENTS_MUS_VM_SERVER_VIEW_DELEGATE_H_
 
 #include "base/memory/scoped_ptr.h"
 #include "components/mus/public/interfaces/compositor_frame.mojom.h"
@@ -37,4 +37,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SERVER_VIEW_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_SERVER_VIEW_DELEGATE_H_
diff --git a/components/mus/server_view_drawn_tracker.cc b/components/mus/vm/server_view_drawn_tracker.cc
similarity index 91%
rename from components/mus/server_view_drawn_tracker.cc
rename to components/mus/vm/server_view_drawn_tracker.cc
index 85a05a8..9441511 100644
--- a/components/mus/server_view_drawn_tracker.cc
+++ b/components/mus/vm/server_view_drawn_tracker.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/server_view_drawn_tracker.h"
+#include "components/mus/vm/server_view_drawn_tracker.h"
 
-#include "components/mus/server_view.h"
-#include "components/mus/server_view_drawn_tracker_observer.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/server_view_drawn_tracker_observer.h"
 
 namespace mus {
 
diff --git a/components/mus/server_view_drawn_tracker.h b/components/mus/vm/server_view_drawn_tracker.h
similarity index 87%
rename from components/mus/server_view_drawn_tracker.h
rename to components/mus/vm/server_view_drawn_tracker.h
index 294d6b48..a3f4f99 100644
--- a/components/mus/server_view_drawn_tracker.h
+++ b/components/mus/vm/server_view_drawn_tracker.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_H_
-#define COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_H_
+#ifndef COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_H_
+#define COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_H_
 
 #include <set>
 
 #include "base/basictypes.h"
-#include "components/mus/server_view_observer.h"
+#include "components/mus/vm/server_view_observer.h"
 
 namespace mus {
 
@@ -53,4 +53,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_H_
+#endif  // COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_H_
diff --git a/components/mus/server_view_drawn_tracker_observer.h b/components/mus/vm/server_view_drawn_tracker_observer.h
similarity index 80%
rename from components/mus/server_view_drawn_tracker_observer.h
rename to components/mus/vm/server_view_drawn_tracker_observer.h
index adf62c61..51239bec 100644
--- a/components/mus/server_view_drawn_tracker_observer.h
+++ b/components/mus/vm/server_view_drawn_tracker_observer.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 COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
-#define COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
+#ifndef COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
+#define COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
 
 namespace mus {
 
@@ -25,4 +25,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
+#endif  // COMPONENTS_MUS_VM_SERVER_VIEW_DRAWN_TRACKER_OBSERVER_H_
diff --git a/components/mus/server_view_drawn_tracker_unittest.cc b/components/mus/vm/server_view_drawn_tracker_unittest.cc
similarity index 95%
rename from components/mus/server_view_drawn_tracker_unittest.cc
rename to components/mus/vm/server_view_drawn_tracker_unittest.cc
index c1596cf..49db3db8 100644
--- a/components/mus/server_view_drawn_tracker_unittest.cc
+++ b/components/mus/vm/server_view_drawn_tracker_unittest.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 "components/mus/server_view_drawn_tracker.h"
+#include "components/mus/vm/server_view_drawn_tracker.h"
 
-#include "components/mus/server_view.h"
-#include "components/mus/server_view_drawn_tracker_observer.h"
-#include "components/mus/test_server_view_delegate.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/server_view_drawn_tracker_observer.h"
+#include "components/mus/vm/test_server_view_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mus {
diff --git a/components/mus/server_view_observer.h b/components/mus/vm/server_view_observer.h
similarity index 92%
rename from components/mus/server_view_observer.h
rename to components/mus/vm/server_view_observer.h
index d744639..a4b151c 100644
--- a/components/mus/server_view_observer.h
+++ b/components/mus/vm/server_view_observer.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 COMPONENTS_MUS_SERVER_VIEW_OBSERVER_H_
-#define COMPONENTS_MUS_SERVER_VIEW_OBSERVER_H_
+#ifndef COMPONENTS_MUS_VM_SERVER_VIEW_OBSERVER_H_
+#define COMPONENTS_MUS_VM_SERVER_VIEW_OBSERVER_H_
 
 #include "components/mus/public/interfaces/mus_constants.mojom.h"
 
@@ -67,4 +67,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_SERVER_VIEW_OBSERVER_H_
+#endif  // COMPONENTS_MUS_VM_SERVER_VIEW_OBSERVER_H_
diff --git a/components/mus/test_change_tracker.cc b/components/mus/vm/test_change_tracker.cc
similarity index 99%
rename from components/mus/test_change_tracker.cc
rename to components/mus/vm/test_change_tracker.cc
index 72dd0bc4..3a3dd978 100644
--- a/components/mus/test_change_tracker.cc
+++ b/components/mus/vm/test_change_tracker.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 "components/mus/test_change_tracker.h"
+#include "components/mus/vm/test_change_tracker.h"
 
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/mus/test_change_tracker.h b/components/mus/vm/test_change_tracker.h
similarity index 96%
rename from components/mus/test_change_tracker.h
rename to components/mus/vm/test_change_tracker.h
index 358a464..1896de2 100644
--- a/components/mus/test_change_tracker.h
+++ b/components/mus/vm/test_change_tracker.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 COMPONENTS_MUS_TEST_CHANGE_TRACKER_H_
-#define COMPONENTS_MUS_TEST_CHANGE_TRACKER_H_
+#ifndef COMPONENTS_MUS_VM_TEST_CHANGE_TRACKER_H_
+#define COMPONENTS_MUS_VM_TEST_CHANGE_TRACKER_H_
 
 #include <string>
 #include <vector>
@@ -153,4 +153,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_TEST_CHANGE_TRACKER_H_
+#endif  // COMPONENTS_MUS_VM_TEST_CHANGE_TRACKER_H_
diff --git a/components/mus/test_server_view_delegate.cc b/components/mus/vm/test_server_view_delegate.cc
similarity index 88%
rename from components/mus/test_server_view_delegate.cc
rename to components/mus/vm/test_server_view_delegate.cc
index 2e927c3f..132cf31 100644
--- a/components/mus/test_server_view_delegate.cc
+++ b/components/mus/vm/test_server_view_delegate.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/test_server_view_delegate.h"
-#include "components/mus/server_view.h"
+#include "components/mus/vm/test_server_view_delegate.h"
+#include "components/mus/vm/server_view.h"
 
 namespace mus {
 
diff --git a/components/mus/test_server_view_delegate.h b/components/mus/vm/test_server_view_delegate.h
similarity index 79%
rename from components/mus/test_server_view_delegate.h
rename to components/mus/vm/test_server_view_delegate.h
index 7509326a..675a0cc 100644
--- a/components/mus/test_server_view_delegate.h
+++ b/components/mus/vm/test_server_view_delegate.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_TEST_SERVER_VIEW_DELEGATE_H_
-#define COMPONENTS_MUS_TEST_SERVER_VIEW_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_TEST_SERVER_VIEW_DELEGATE_H_
+#define COMPONENTS_MUS_VM_TEST_SERVER_VIEW_DELEGATE_H_
 
 #include "base/basictypes.h"
-#include "components/mus/server_view_delegate.h"
+#include "components/mus/vm/server_view_delegate.h"
 
 namespace mus {
 
@@ -32,4 +32,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_TEST_SERVER_VIEW_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_TEST_SERVER_VIEW_DELEGATE_H_
diff --git a/components/mus/view_coordinate_conversions.cc b/components/mus/vm/view_coordinate_conversions.cc
similarity index 95%
rename from components/mus/view_coordinate_conversions.cc
rename to components/mus/vm/view_coordinate_conversions.cc
index 445d762..57e0093 100644
--- a/components/mus/view_coordinate_conversions.cc
+++ b/components/mus/vm/view_coordinate_conversions.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/view_coordinate_conversions.h"
+#include "components/mus/vm/view_coordinate_conversions.h"
 
-#include "components/mus/server_view.h"
+#include "components/mus/vm/server_view.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/point_f.h"
diff --git a/components/mus/view_coordinate_conversions.h b/components/mus/vm/view_coordinate_conversions.h
similarity index 86%
rename from components/mus/view_coordinate_conversions.h
rename to components/mus/vm/view_coordinate_conversions.h
index 2e8b494..ed9e607d 100644
--- a/components/mus/view_coordinate_conversions.h
+++ b/components/mus/vm/view_coordinate_conversions.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 COMPONENTS_MUS_VIEW_COORDINATE_CONVERSIONS_H_
-#define COMPONENTS_MUS_VIEW_COORDINATE_CONVERSIONS_H_
+#ifndef COMPONENTS_MUS_VM_VIEW_COORDINATE_CONVERSIONS_H_
+#define COMPONENTS_MUS_VM_VIEW_COORDINATE_CONVERSIONS_H_
 
 namespace gfx {
 class Point;
@@ -32,4 +32,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_VIEW_COORDINATE_CONVERSIONS_H_
+#endif  // COMPONENTS_MUS_VM_VIEW_COORDINATE_CONVERSIONS_H_
diff --git a/components/mus/view_coordinate_conversions_unittest.cc b/components/mus/vm/view_coordinate_conversions_unittest.cc
similarity index 88%
rename from components/mus/view_coordinate_conversions_unittest.cc
rename to components/mus/vm/view_coordinate_conversions_unittest.cc
index 71a220f..becea9b 100644
--- a/components/mus/view_coordinate_conversions_unittest.cc
+++ b/components/mus/vm/view_coordinate_conversions_unittest.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 "components/mus/view_coordinate_conversions.h"
+#include "components/mus/vm/view_coordinate_conversions.h"
 
-#include "components/mus/server_view.h"
-#include "components/mus/server_view_delegate.h"
-#include "components/mus/test_server_view_delegate.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/server_view_delegate.h"
+#include "components/mus/vm/test_server_view_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/components/mus/view_manager_client_apptest.cc b/components/mus/vm/view_manager_client_apptest.cc
similarity index 100%
rename from components/mus/view_manager_client_apptest.cc
rename to components/mus/vm/view_manager_client_apptest.cc
diff --git a/components/mus/view_tree_apptest.cc b/components/mus/vm/view_tree_apptest.cc
similarity index 99%
rename from components/mus/view_tree_apptest.cc
rename to components/mus/vm/view_tree_apptest.cc
index dfef44ec..d0ae5b3 100644
--- a/components/mus/view_tree_apptest.cc
+++ b/components/mus/vm/view_tree_apptest.cc
@@ -6,10 +6,10 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
 #include "components/mus/public/interfaces/view_tree_host.mojom.h"
-#include "components/mus/test_change_tracker.h"
+#include "components/mus/vm/ids.h"
+#include "components/mus/vm/test_change_tracker.h"
 #include "mojo/application/public/cpp/application_delegate.h"
 #include "mojo/application/public/cpp/application_impl.h"
 #include "mojo/application/public/cpp/application_test_base.h"
diff --git a/components/mus/view_tree_host_connection.cc b/components/mus/vm/view_tree_host_connection.cc
similarity index 92%
rename from components/mus/view_tree_host_connection.cc
rename to components/mus/vm/view_tree_host_connection.cc
index 3991b03..7dcfbda7 100644
--- a/components/mus/view_tree_host_connection.cc
+++ b/components/mus/vm/view_tree_host_connection.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/view_tree_host_connection.h"
+#include "components/mus/vm/view_tree_host_connection.h"
 
-#include "components/mus/connection_manager.h"
-#include "components/mus/view_tree_host_impl.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/view_tree_host_impl.h"
 
 namespace mus {
 
diff --git a/components/mus/view_tree_host_connection.h b/components/mus/vm/view_tree_host_connection.h
similarity index 90%
rename from components/mus/view_tree_host_connection.h
rename to components/mus/vm/view_tree_host_connection.h
index 24ae6d1..a84fbbb 100644
--- a/components/mus/view_tree_host_connection.h
+++ b/components/mus/vm/view_tree_host_connection.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_VIEW_TREE_HOST_CONNECTION_H_
-#define COMPONENTS_MUS_VIEW_TREE_HOST_CONNECTION_H_
+#ifndef COMPONENTS_MUS_VM_VIEW_TREE_HOST_CONNECTION_H_
+#define COMPONENTS_MUS_VM_VIEW_TREE_HOST_CONNECTION_H_
 
 #include "base/memory/scoped_ptr.h"
 #include "components/mus/public/interfaces/view_tree_host.mojom.h"
-#include "components/mus/view_tree_host_delegate.h"
-#include "components/mus/view_tree_host_impl.h"
+#include "components/mus/vm/view_tree_host_delegate.h"
+#include "components/mus/vm/view_tree_host_impl.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
 
 namespace mus {
@@ -79,4 +79,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_VIEW_TREE_HOST_CONNECTION_H_
+#endif  // COMPONENTS_MUS_VM_VIEW_TREE_HOST_CONNECTION_H_
diff --git a/components/mus/view_tree_host_delegate.h b/components/mus/vm/view_tree_host_delegate.h
similarity index 86%
rename from components/mus/view_tree_host_delegate.h
rename to components/mus/vm/view_tree_host_delegate.h
index 50124999..724c425d 100644
--- a/components/mus/view_tree_host_delegate.h
+++ b/components/mus/vm/view_tree_host_delegate.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 COMPONENTS_MUS_VIEW_TREE_HOST_DELEGATE_H_
-#define COMPONENTS_MUS_VIEW_TREE_HOST_DELEGATE_H_
+#ifndef COMPONENTS_MUS_VM_VIEW_TREE_HOST_DELEGATE_H_
+#define COMPONENTS_MUS_VM_VIEW_TREE_HOST_DELEGATE_H_
 
 namespace mus {
 
@@ -32,4 +32,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_VIEW_TREE_HOST_DELEGATE_H_
+#endif  // COMPONENTS_MUS_VM_VIEW_TREE_HOST_DELEGATE_H_
diff --git a/components/mus/view_tree_host_impl.cc b/components/mus/vm/view_tree_host_impl.cc
similarity index 90%
rename from components/mus/view_tree_host_impl.cc
rename to components/mus/vm/view_tree_host_impl.cc
index 32fcfe2c..6dc9c3e 100644
--- a/components/mus/view_tree_host_impl.cc
+++ b/components/mus/vm/view_tree_host_impl.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/view_tree_host_impl.h"
+#include "components/mus/vm/view_tree_host_impl.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "components/mus/connection_manager.h"
-#include "components/mus/display_manager.h"
-#include "components/mus/focus_controller.h"
 #include "components/mus/public/cpp/types.h"
-#include "components/mus/view_tree_host_delegate.h"
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/display_manager.h"
+#include "components/mus/vm/focus_controller.h"
+#include "components/mus/vm/view_tree_host_delegate.h"
+#include "components/mus/vm/view_tree_impl.h"
 #include "mojo/common/common_type_converters.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 
@@ -19,7 +19,6 @@
 ViewTreeHostImpl::ViewTreeHostImpl(
     mojo::ViewTreeHostClientPtr client,
     ConnectionManager* connection_manager,
-    bool is_headless,
     mojo::ApplicationImpl* app_impl,
     const scoped_refptr<GpuState>& gpu_state,
     const scoped_refptr<SurfacesState>& surfaces_state)
@@ -27,8 +26,7 @@
       connection_manager_(connection_manager),
       client_(client.Pass()),
       event_dispatcher_(this),
-      display_manager_(DisplayManager::Create(is_headless,
-                                              app_impl,
+      display_manager_(DisplayManager::Create(app_impl,
                                               gpu_state,
                                               surfaces_state)),
       focus_controller_(new FocusController(this)) {
@@ -106,7 +104,7 @@
   client()->OnAccelerator(accelerator_id, event.Pass());
 }
 
-void ViewTreeHostImpl::DispatchInputEventToView(const ServerView* target,
+void ViewTreeHostImpl::DispatchInputEventToView(ServerView* target,
                                                 mojo::EventPtr event) {
   // If the view is an embed root, forward to the embedded view, not the owner.
   ViewTreeImpl* connection =
@@ -149,15 +147,7 @@
   return root_.get();
 }
 
-void ViewTreeHostImpl::OnEvent(ViewId id, mojo::EventPtr event) {
-  ServerView* view = connection_manager_->GetView(id);
-  // TODO(fsamuel): This should be a DCHECK but currently we use stale
-  // information to decide where to route input events. This should be fixed
-  // once we implement a UI scheduler.
-  if (view) {
-    DispatchInputEventToView(view, event.Pass());
-    return;
-  }
+void ViewTreeHostImpl::OnEvent(mojo::EventPtr event) {
   event_dispatcher_.OnEvent(event.Pass());
 }
 
@@ -184,6 +174,10 @@
   connection_manager_->ProcessViewportMetricsChanged(old_metrics, new_metrics);
 }
 
+void ViewTreeHostImpl::OnTopLevelSurfaceChanged(cc::SurfaceId surface_id) {
+  surface_id_ = surface_id;
+}
+
 void ViewTreeHostImpl::OnFocusChanged(ServerView* old_focused_view,
                                       ServerView* new_focused_view) {
   // There are up to four connections that need to be notified:
diff --git a/components/mus/view_tree_host_impl.h b/components/mus/vm/view_tree_host_impl.h
similarity index 86%
rename from components/mus/view_tree_host_impl.h
rename to components/mus/vm/view_tree_host_impl.h
index 0b7f1b9..2bda609b 100644
--- a/components/mus/view_tree_host_impl.h
+++ b/components/mus/vm/view_tree_host_impl.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_VIEW_TREE_HOST_IMPL_H_
-#define COMPONENTS_MUS_VIEW_TREE_HOST_IMPL_H_
+#ifndef COMPONENTS_MUS_VM_VIEW_TREE_HOST_IMPL_H_
+#define COMPONENTS_MUS_VM_VIEW_TREE_HOST_IMPL_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "components/mus/display_manager.h"
-#include "components/mus/event_dispatcher.h"
-#include "components/mus/focus_controller_delegate.h"
 #include "components/mus/public/cpp/types.h"
 #include "components/mus/public/interfaces/view_tree_host.mojom.h"
-#include "components/mus/server_view.h"
+#include "components/mus/vm/display_manager.h"
+#include "components/mus/vm/event_dispatcher.h"
+#include "components/mus/vm/focus_controller_delegate.h"
+#include "components/mus/vm/server_view.h"
 
 namespace cc {
 class SurfaceManager;
@@ -42,7 +42,6 @@
   // in the DisplayManagerFactory and pass them along on DisplayManager::Create.
   ViewTreeHostImpl(mojo::ViewTreeHostClientPtr client,
                    ConnectionManager* connection_manager,
-                   bool is_headless,
                    mojo::ApplicationImpl* app_impl,
                    const scoped_refptr<GpuState>& gpu_state,
                    const scoped_refptr<SurfacesState>& surfaces_state);
@@ -55,6 +54,8 @@
 
   mojo::ViewTreeHostClient* client() const { return client_.get(); }
 
+  cc::SurfaceId surface_id() const { return surface_id_; }
+
   // Returns whether |view| is a descendant of this root but not itself a
   // root view.
   bool IsViewAttachedToRoot(const ServerView* view) const;
@@ -81,7 +82,7 @@
   void SetImeVisibility(ServerView* view, bool visible);
 
   void OnAccelerator(uint32_t accelerator_id, mojo::EventPtr event);
-  void DispatchInputEventToView(const ServerView* target, mojo::EventPtr event);
+  void DispatchInputEventToView(ServerView* target, mojo::EventPtr event);
 
   // ViewTreeHost:
   void SetSize(mojo::SizePtr size) override;
@@ -96,11 +97,12 @@
 
   // DisplayManagerDelegate:
   ServerView* GetRootView() override;
-  void OnEvent(ViewId id, mojo::EventPtr event) override;
+  void OnEvent(mojo::EventPtr event) override;
   void OnDisplayClosed() override;
   void OnViewportMetricsChanged(
       const mojo::ViewportMetrics& old_metrics,
       const mojo::ViewportMetrics& new_metrics) override;
+  void OnTopLevelSurfaceChanged(cc::SurfaceId surface_id) override;
 
   // FocusControllerDelegate:
   void OnFocusChanged(ServerView* old_focused_view,
@@ -113,10 +115,11 @@
   scoped_ptr<ServerView> root_;
   scoped_ptr<DisplayManager> display_manager_;
   scoped_ptr<FocusController> focus_controller_;
+  cc::SurfaceId surface_id_;
 
   DISALLOW_COPY_AND_ASSIGN(ViewTreeHostImpl);
 };
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_VIEW_TREE_HOST_IMPL_H_
+#endif  // COMPONENTS_MUS_VM_VIEW_TREE_HOST_IMPL_H_
diff --git a/components/mus/view_tree_impl.cc b/components/mus/vm/view_tree_impl.cc
similarity index 98%
rename from components/mus/view_tree_impl.cc
rename to components/mus/vm/view_tree_impl.cc
index b97583e1..794f56b9 100644
--- a/components/mus/view_tree_impl.cc
+++ b/components/mus/vm/view_tree_impl.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/view_tree_impl.h"
 
 #include "base/bind.h"
 #include "base/stl_util.h"
-#include "components/mus/connection_manager.h"
-#include "components/mus/default_access_policy.h"
-#include "components/mus/display_manager.h"
-#include "components/mus/server_view.h"
-#include "components/mus/view_tree_host_impl.h"
-#include "components/mus/window_manager_access_policy.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/default_access_policy.h"
+#include "components/mus/vm/display_manager.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/view_tree_host_impl.h"
+#include "components/mus/vm/window_manager_access_policy.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/converters/ime/ime_type_converters.h"
 #include "mojo/converters/input_events/input_events_type_converters.h"
diff --git a/components/mus/view_tree_impl.h b/components/mus/vm/view_tree_impl.h
similarity index 97%
rename from components/mus/view_tree_impl.h
rename to components/mus/vm/view_tree_impl.h
index 8549585..f573b55 100644
--- a/components/mus/view_tree_impl.h
+++ b/components/mus/vm/view_tree_impl.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 COMPONENTS_MUS_VIEW_TREE_IMPL_H_
-#define COMPONENTS_MUS_VIEW_TREE_IMPL_H_
+#ifndef COMPONENTS_MUS_VM_VIEW_TREE_IMPL_H_
+#define COMPONENTS_MUS_VM_VIEW_TREE_IMPL_H_
 
 #include <set>
 #include <string>
@@ -13,10 +13,10 @@
 #include "base/containers/hash_tables.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "components/mus/access_policy_delegate.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/interfaces/surface_id.mojom.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
+#include "components/mus/vm/access_policy_delegate.h"
+#include "components/mus/vm/ids.h"
 
 namespace gfx {
 class Rect;
@@ -249,4 +249,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_VIEW_TREE_IMPL_H_
+#endif  // COMPONENTS_MUS_VM_VIEW_TREE_IMPL_H_
diff --git a/components/mus/view_tree_unittest.cc b/components/mus/vm/view_tree_unittest.cc
similarity index 93%
rename from components/mus/view_tree_unittest.cc
rename to components/mus/vm/view_tree_unittest.cc
index 8918c2da..a775d039 100644
--- a/components/mus/view_tree_unittest.cc
+++ b/components/mus/vm/view_tree_unittest.cc
@@ -6,20 +6,20 @@
 #include <vector>
 
 #include "base/message_loop/message_loop.h"
-#include "components/mus/client_connection.h"
-#include "components/mus/connection_manager.h"
-#include "components/mus/connection_manager_delegate.h"
-#include "components/mus/display_manager.h"
-#include "components/mus/display_manager_factory.h"
-#include "components/mus/ids.h"
 #include "components/mus/public/cpp/types.h"
 #include "components/mus/public/cpp/util.h"
 #include "components/mus/public/interfaces/view_tree.mojom.h"
-#include "components/mus/server_view.h"
 #include "components/mus/surfaces/surfaces_state.h"
-#include "components/mus/test_change_tracker.h"
-#include "components/mus/view_tree_host_connection.h"
-#include "components/mus/view_tree_impl.h"
+#include "components/mus/vm/client_connection.h"
+#include "components/mus/vm/connection_manager.h"
+#include "components/mus/vm/connection_manager_delegate.h"
+#include "components/mus/vm/display_manager.h"
+#include "components/mus/vm/display_manager_factory.h"
+#include "components/mus/vm/ids.h"
+#include "components/mus/vm/server_view.h"
+#include "components/mus/vm/test_change_tracker.h"
+#include "components/mus/vm/view_tree_host_connection.h"
+#include "components/mus/vm/view_tree_impl.h"
 #include "mojo/application/public/interfaces/service_provider.mojom.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -235,7 +235,6 @@
   TestDisplayManagerFactory() {}
   ~TestDisplayManagerFactory() {}
   DisplayManager* CreateDisplayManager(
-      bool is_headless,
       mojo::ApplicationImpl* app_impl,
       const scoped_refptr<GpuState>& gpu_state,
       const scoped_refptr<SurfacesState>& surfaces_state) override {
@@ -308,7 +307,7 @@
         new ConnectionManager(&delegate_, scoped_refptr<SurfacesState>()));
     ViewTreeHostImpl* host = new ViewTreeHostImpl(
         mojo::ViewTreeHostClientPtr(), connection_manager_.get(),
-        true /* is_headless */, nullptr, scoped_refptr<GpuState>(),
+        nullptr, scoped_refptr<GpuState>(),
         scoped_refptr<SurfacesState>());
     // TODO(fsamuel): This is way too magical. We need to find a better way to
     // manage lifetime.
@@ -361,7 +360,7 @@
   connection1_client->tracker()->changes()->clear();
   wm_client()->tracker()->changes()->clear();
 
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerDownEvent(21, 22));
+  display_manager_delegate()->OnEvent(CreatePointerDownEvent(21, 22));
   // Focus should go to child1. This result in notifying both the window
   // manager and client connection being notified.
   EXPECT_EQ(v1, connection1->GetHost()->GetFocusedView());
@@ -373,14 +372,14 @@
       "Focused id=2,1",
       ChangesToDescription1(*connection1_client->tracker()->changes())[0]);
 
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerUpEvent(21, 22));
+  display_manager_delegate()->OnEvent(CreatePointerUpEvent(21, 22));
   wm_client()->tracker()->changes()->clear();
   connection1_client->tracker()->changes()->clear();
 
   // Press outside of the embedded view. Focus should go to the root. Notice
   // the client1 doesn't see who has focus as the focused view (root) isn't
   // visible to it.
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerDownEvent(61, 22));
+  display_manager_delegate()->OnEvent(CreatePointerDownEvent(61, 22));
   EXPECT_EQ(host_connection()->view_tree_host()->root_view(),
             host_connection()->view_tree_host()->GetFocusedView());
   ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u);
@@ -391,13 +390,13 @@
       "Focused id=null",
       ChangesToDescription1(*connection1_client->tracker()->changes())[0]);
 
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerUpEvent(21, 22));
+  display_manager_delegate()->OnEvent(CreatePointerUpEvent(21, 22));
   wm_client()->tracker()->changes()->clear();
   connection1_client->tracker()->changes()->clear();
 
   // Press in the same location. Should not get a focus change event (only input
   // event).
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerDownEvent(61, 22));
+  display_manager_delegate()->OnEvent(CreatePointerDownEvent(61, 22));
   EXPECT_EQ(host_connection()->view_tree_host()->root_view(),
             host_connection()->view_tree_host()->GetFocusedView());
   ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u);
@@ -438,7 +437,7 @@
 
   // Send an event to |v1|. |embed_connection| should get the event, not
   // |wm_client|, since |v1| lives inside an embedded view.
-  display_manager_delegate()->OnEvent(ViewId(), CreatePointerDownEvent(21, 22));
+  display_manager_delegate()->OnEvent(CreatePointerDownEvent(21, 22));
   ASSERT_EQ(1u, wm_client()->tracker()->changes()->size());
   EXPECT_EQ("Focused id=2,1",
             ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
diff --git a/components/mus/window_manager_access_policy.cc b/components/mus/vm/window_manager_access_policy.cc
similarity index 95%
rename from components/mus/window_manager_access_policy.cc
rename to components/mus/vm/window_manager_access_policy.cc
index 7e9e5b0..a7da4972 100644
--- a/components/mus/window_manager_access_policy.cc
+++ b/components/mus/vm/window_manager_access_policy.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/mus/window_manager_access_policy.h"
+#include "components/mus/vm/window_manager_access_policy.h"
 
-#include "components/mus/access_policy_delegate.h"
-#include "components/mus/server_view.h"
+#include "components/mus/vm/access_policy_delegate.h"
+#include "components/mus/vm/server_view.h"
 
 namespace mus {
 
diff --git a/components/mus/window_manager_access_policy.h b/components/mus/vm/window_manager_access_policy.h
similarity index 89%
rename from components/mus/window_manager_access_policy.h
rename to components/mus/vm/window_manager_access_policy.h
index 885ad7a7..78f9513 100644
--- a/components/mus/window_manager_access_policy.h
+++ b/components/mus/vm/window_manager_access_policy.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MUS_WINDOW_MANAGER_ACCESS_POLICY_H_
-#define COMPONENTS_MUS_WINDOW_MANAGER_ACCESS_POLICY_H_
+#ifndef COMPONENTS_MUS_VM_WINDOW_MANAGER_ACCESS_POLICY_H_
+#define COMPONENTS_MUS_VM_WINDOW_MANAGER_ACCESS_POLICY_H_
 
 #include "base/basictypes.h"
-#include "components/mus/access_policy.h"
+#include "components/mus/vm/access_policy.h"
 
 namespace mus {
 
@@ -52,4 +52,4 @@
 
 }  // namespace mus
 
-#endif  // COMPONENTS_MUS_WINDOW_MANAGER_ACCESS_POLICY_H_
+#endif  // COMPONENTS_MUS_VM_WINDOW_MANAGER_ACCESS_POLICY_H_
diff --git a/components/navigation_interception.gypi b/components/navigation_interception.gypi
index 35112010..7ccc4cd8 100644
--- a/components/navigation_interception.gypi
+++ b/components/navigation_interception.gypi
@@ -23,8 +23,8 @@
       ],
       'sources': [
         # Note: sources list duplicated in GN build.
-        'navigation_interception/intercept_navigation_resource_throttle.cc',
-        'navigation_interception/intercept_navigation_resource_throttle.h',
+        'navigation_interception/intercept_navigation_throttle.cc',
+        'navigation_interception/intercept_navigation_throttle.h',
         'navigation_interception/navigation_params.cc',
         'navigation_interception/navigation_params.h',
       ],
diff --git a/components/navigation_interception/BUILD.gn b/components/navigation_interception/BUILD.gn
index 12456ff3..f268510b 100644
--- a/components/navigation_interception/BUILD.gn
+++ b/components/navigation_interception/BUILD.gn
@@ -8,8 +8,8 @@
 
 source_set("navigation_interception") {
   sources = [
-    "intercept_navigation_resource_throttle.cc",
-    "intercept_navigation_resource_throttle.h",
+    "intercept_navigation_throttle.cc",
+    "intercept_navigation_throttle.h",
     "navigation_params.cc",
     "navigation_params.h",
   ]
@@ -49,7 +49,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "intercept_navigation_resource_throttle_unittest.cc",
+    "intercept_navigation_throttle_unittest.cc",
   ]
   deps = [
     ":navigation_interception",
diff --git a/components/navigation_interception/intercept_navigation_delegate.cc b/components/navigation_interception/intercept_navigation_delegate.cc
index f5816bf..93c4d442 100644
--- a/components/navigation_interception/intercept_navigation_delegate.cc
+++ b/components/navigation_interception/intercept_navigation_delegate.cc
@@ -7,9 +7,10 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/callback.h"
-#include "components/navigation_interception/intercept_navigation_resource_throttle.h"
+#include "components/navigation_interception/intercept_navigation_throttle.h"
 #include "components/navigation_interception/navigation_params_android.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/resource_request_info.h"
@@ -83,10 +84,12 @@
 }
 
 // static
-content::ResourceThrottle* InterceptNavigationDelegate::CreateThrottleFor(
-    net::URLRequest* request) {
-  return new InterceptNavigationResourceThrottle(
-      request, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread));
+scoped_ptr<content::NavigationThrottle>
+InterceptNavigationDelegate::CreateThrottleFor(
+    content::NavigationHandle* handle) {
+  return scoped_ptr<content::NavigationThrottle>(
+      new InterceptNavigationThrottle(
+          handle, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread)));
 }
 
 // static
diff --git a/components/navigation_interception/intercept_navigation_delegate.h b/components/navigation_interception/intercept_navigation_delegate.h
index d84969f0..57858fd 100644
--- a/components/navigation_interception/intercept_navigation_delegate.h
+++ b/components/navigation_interception/intercept_navigation_delegate.h
@@ -12,7 +12,8 @@
 class GURL;
 
 namespace content {
-class ResourceThrottle;
+class NavigationHandle;
+class NavigationThrottle;
 class WebContents;
 }
 
@@ -32,9 +33,8 @@
 // 1) the Java-side interface implementation must be associated (via the
 //    Associate method) with a WebContents for which URLRequests are to be
 //    intercepted,
-// 2) the ResourceThrottle obtained via CreateThrottleFor must be associated
-//    with the URLRequests in the ResourceDispatcherHostDelegate
-//    implementation.
+// 2) the NavigationThrottle obtained via CreateThrottleFor must be associated
+//    with the NavigationHandle in the ContentBrowserClient implementation.
 class InterceptNavigationDelegate : public base::SupportsUserData::Data {
  public:
   InterceptNavigationDelegate(JNIEnv* env, jobject jdelegate);
@@ -50,10 +50,10 @@
   // can be null.
   static InterceptNavigationDelegate* Get(content::WebContents* web_contents);
 
-  // Creates a InterceptNavigationResourceThrottle that will direct all
-  // callbacks to the InterceptNavigationDelegate.
-  static content::ResourceThrottle* CreateThrottleFor(
-      net::URLRequest* request);
+  // Creates a InterceptNavigationThrottle that will direct all callbacks to
+  // the InterceptNavigationDelegate.
+  static scoped_ptr<content::NavigationThrottle> CreateThrottleFor(
+      content::NavigationHandle* handle);
 
   // Updates information to determine whether to have user gesture carryover or
   // not.
diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.cc b/components/navigation_interception/intercept_navigation_resource_throttle.cc
deleted file mode 100644
index 1b0b89f..0000000
--- a/components/navigation_interception/intercept_navigation_resource_throttle.cc
+++ /dev/null
@@ -1,146 +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 "components/navigation_interception/intercept_navigation_resource_throttle.h"
-
-#include "components/navigation_interception/navigation_params.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_security_policy.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/resource_context.h"
-#include "content/public/browser/resource_controller.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/referrer.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/redirect_info.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job_factory.h"
-#include "net/url_request/url_request.h"
-#include "ui/base/page_transition_types.h"
-
-using content::BrowserThread;
-using content::ChildProcessSecurityPolicy;
-using ui::PageTransition;
-using content::Referrer;
-using content::RenderProcessHost;
-using content::ResourceRequestInfo;
-
-namespace navigation_interception {
-
-namespace {
-
-void CheckIfShouldIgnoreNavigationOnUIThread(
-    int render_process_id,
-    int render_frame_id,
-    const NavigationParams& navigation_params,
-    InterceptNavigationResourceThrottle::CheckOnUIThreadCallback
-    should_ignore_callback,
-    base::Callback<void(bool)> callback) {
-  bool should_ignore_navigation = false;
-  RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
-  if (rph) {
-    NavigationParams validated_params(navigation_params);
-    rph->FilterURL(false, &validated_params.url());
-
-    content::RenderFrameHost* render_frame_host =
-        content::RenderFrameHost::FromID(render_process_id, render_frame_id);
-    content::WebContents* web_contents =
-        content::WebContents::FromRenderFrameHost(render_frame_host);
-
-    if (web_contents) {
-      should_ignore_navigation = should_ignore_callback.Run(web_contents,
-                                                            validated_params);
-    }
-  }
-
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(callback, should_ignore_navigation));
-}
-
-} // namespace
-
-InterceptNavigationResourceThrottle::InterceptNavigationResourceThrottle(
-    net::URLRequest* request,
-    CheckOnUIThreadCallback should_ignore_callback)
-    : request_(request),
-      should_ignore_callback_(should_ignore_callback),
-      weak_ptr_factory_(this) {
-}
-
-InterceptNavigationResourceThrottle::~InterceptNavigationResourceThrottle() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-void InterceptNavigationResourceThrottle::WillStartRequest(bool* defer) {
-  *defer =
-      CheckIfShouldIgnoreNavigation(request_->url(), request_->method(), false);
-}
-
-void InterceptNavigationResourceThrottle::WillRedirectRequest(
-    const net::RedirectInfo& redirect_info,
-    bool* defer) {
-  *defer = CheckIfShouldIgnoreNavigation(redirect_info.new_url,
-                                         redirect_info.new_method, true);
-}
-
-const char* InterceptNavigationResourceThrottle::GetNameForLogging() const {
-  return "InterceptNavigationResourceThrottle";
-}
-
-bool InterceptNavigationResourceThrottle::CheckIfShouldIgnoreNavigation(
-    const GURL& url,
-    const std::string& method,
-    bool is_redirect) {
-  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
-  if (!info)
-    return false;
-
-  int render_process_id, render_frame_id;
-  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
-    return false;
-
-  bool is_external_protocol =
-      !info->GetContext()->GetRequestContext()->job_factory()->IsHandledURL(
-          url);
-  NavigationParams navigation_params(
-      url,
-      Referrer::SanitizeForRequest(
-          url, Referrer(GURL(request_->referrer()), info->GetReferrerPolicy())),
-      info->HasUserGesture(), method == "POST", info->GetPageTransition(),
-      is_redirect, is_external_protocol, true);
-
-  BrowserThread::PostTask(
-      BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(
-          &CheckIfShouldIgnoreNavigationOnUIThread,
-          render_process_id,
-          render_frame_id,
-          navigation_params,
-          should_ignore_callback_,
-          base::Bind(
-              &InterceptNavigationResourceThrottle::OnResultObtained,
-              weak_ptr_factory_.GetWeakPtr())));
-
-  // Defer request while we wait for the UI thread to check if the navigation
-  // should be ignored.
-  return true;
-}
-
-void InterceptNavigationResourceThrottle::OnResultObtained(
-    bool should_ignore_navigation) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  if (should_ignore_navigation) {
-    controller()->CancelAndIgnore();
-  } else {
-    controller()->Resume();
-  }
-}
-
-}  // namespace navigation_interception
diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.h b/components/navigation_interception/intercept_navigation_resource_throttle.h
deleted file mode 100644
index db3a714..0000000
--- a/components/navigation_interception/intercept_navigation_resource_throttle.h
+++ /dev/null
@@ -1,63 +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 COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_
-#define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/resource_throttle.h"
-
-class GURL;
-
-namespace content {
-class WebContents;
-}
-
-namespace net {
-class URLRequest;
-}
-
-namespace navigation_interception {
-
-class NavigationParams;
-
-// This class allows the provider of the Callback to selectively ignore top
-// level navigations.
-class InterceptNavigationResourceThrottle : public content::ResourceThrottle {
- public:
-  typedef base::Callback<bool(
-          content::WebContents* /* source */,
-          const NavigationParams& /* navigation_params */)>
-      CheckOnUIThreadCallback;
-
-  InterceptNavigationResourceThrottle(
-      net::URLRequest* request,
-      CheckOnUIThreadCallback should_ignore_callback);
-  ~InterceptNavigationResourceThrottle() override;
-
-  // content::ResourceThrottle implementation:
-  void WillStartRequest(bool* defer) override;
-  void WillRedirectRequest(const net::RedirectInfo& redirect_info,
-                           bool* defer) override;
-  const char* GetNameForLogging() const override;
-
- private:
-  bool CheckIfShouldIgnoreNavigation(const GURL& url,
-                                     const std::string& method,
-                                     bool is_redirect);
-  void OnResultObtained(bool should_ignore_navigation);
-
-  net::URLRequest* request_;
-  CheckOnUIThreadCallback should_ignore_callback_;
-  base::WeakPtrFactory<InterceptNavigationResourceThrottle> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(InterceptNavigationResourceThrottle);
-};
-
-}  // namespace navigation_interception
-
-#endif  // COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_
diff --git a/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc
deleted file mode 100644
index 8855f42..0000000
--- a/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "components/navigation_interception/intercept_navigation_resource_throttle.h"
-#include "components/navigation_interception/navigation_params.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/resource_context.h"
-#include "content/public/browser/resource_controller.h"
-#include "content/public/browser/resource_dispatcher_host.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/browser/resource_throttle.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_renderer_host.h"
-#include "net/base/request_priority.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_response_info.h"
-#include "net/url_request/redirect_info.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using content::ResourceType;
-using testing::_;
-using testing::Eq;
-using testing::Ne;
-using testing::Property;
-using testing::Return;
-
-namespace navigation_interception {
-
-namespace {
-
-const char kTestUrl[] = "http://www.test.com/";
-const char kUnsafeTestUrl[] = "about:crash";
-
-// The MS C++ compiler complains about not being able to resolve which url()
-// method (const or non-const) to use if we use the Property matcher to check
-// the return value of the NavigationParams::url() method.
-// It is possible to suppress the error by specifying the types directly but
-// that results in very ugly syntax, which is why these custom matchers are
-// used instead.
-MATCHER(NavigationParamsUrlIsTest, "") {
-  return arg.url() == GURL(kTestUrl);
-}
-
-MATCHER(NavigationParamsUrlIsSafe, "") {
-  return arg.url() != GURL(kUnsafeTestUrl);
-}
-
-}  // namespace
-
-
-// MockInterceptCallbackReceiver ----------------------------------------------
-
-class MockInterceptCallbackReceiver {
- public:
-  MOCK_METHOD2(ShouldIgnoreNavigation,
-               bool(content::WebContents* source,
-                    const NavigationParams& navigation_params));
-};
-
-// MockResourceController -----------------------------------------------------
-class MockResourceController : public content::ResourceController {
- public:
-  enum Status {
-    UNKNOWN,
-    RESUMED,
-    CANCELLED
-  };
-
-  MockResourceController()
-      : status_(UNKNOWN) {
-  }
-
-  Status status() const { return status_; }
-
-  // ResourceController:
-  void Cancel() override { NOTREACHED(); }
-  void CancelAndIgnore() override { status_ = CANCELLED; }
-  void CancelWithError(int error_code) override { NOTREACHED(); }
-  void Resume() override {
-    DCHECK(status_ == UNKNOWN);
-    status_ = RESUMED;
-  }
-
- private:
-  Status status_;
-};
-
-// TestIOThreadState ----------------------------------------------------------
-
-enum RedirectMode {
-  REDIRECT_MODE_NO_REDIRECT,
-  REDIRECT_MODE_302,
-};
-
-class TestIOThreadState {
- public:
-  TestIOThreadState(const GURL& url,
-                    int render_process_id,
-                    int render_frame_id,
-                    const std::string& request_method,
-                    RedirectMode redirect_mode,
-                    MockInterceptCallbackReceiver* callback_receiver)
-      : resource_context_(&test_url_request_context_),
-        request_(resource_context_.GetRequestContext()->CreateRequest(
-                     url,
-                     net::DEFAULT_PRIORITY,
-                     NULL /* delegate */)) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    if (render_process_id != MSG_ROUTING_NONE &&
-        render_frame_id != MSG_ROUTING_NONE) {
-      content::ResourceRequestInfo::AllocateForTesting(
-          request_.get(),
-          content::RESOURCE_TYPE_MAIN_FRAME,
-          &resource_context_,
-          render_process_id,
-          MSG_ROUTING_NONE,
-          render_frame_id,
-          true,    // is_main_frame
-          false,   // parent_is_main_frame
-          true,    // allow_download
-          false);  // is_async
-    }
-    throttle_.reset(new InterceptNavigationResourceThrottle(
-        request_.get(),
-        base::Bind(&MockInterceptCallbackReceiver::ShouldIgnoreNavigation,
-                   base::Unretained(callback_receiver))));
-    throttle_->set_controller_for_testing(&throttle_controller_);
-    request_->set_method(request_method);
-
-    if (redirect_mode == REDIRECT_MODE_302) {
-      net::HttpResponseInfo& response_info =
-          const_cast<net::HttpResponseInfo&>(request_->response_info());
-      response_info.headers = new net::HttpResponseHeaders(
-          "Status: 302 Found\0\0");
-    }
-  }
-
-  void ThrottleWillStartRequest(bool* defer) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    throttle_->WillStartRequest(defer);
-  }
-
-  void ThrottleWillRedirectRequest(const net::RedirectInfo& redirect_info,
-                                   bool* defer) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    throttle_->WillRedirectRequest(redirect_info, defer);
-  }
-
-  bool request_resumed() const {
-    return throttle_controller_.status() ==
-        MockResourceController::RESUMED;
-  }
-
-  bool request_cancelled() const {
-    return throttle_controller_.status() ==
-        MockResourceController::CANCELLED;
-  }
-
- private:
-  net::TestURLRequestContext test_url_request_context_;
-  content::MockResourceContext resource_context_;
-  scoped_ptr<net::URLRequest> request_;
-  scoped_ptr<InterceptNavigationResourceThrottle> throttle_;
-  MockResourceController throttle_controller_;
-};
-
-// InterceptNavigationResourceThrottleTest ------------------------------------
-
-class InterceptNavigationResourceThrottleTest
-  : public content::RenderViewHostTestHarness {
- public:
-  InterceptNavigationResourceThrottleTest()
-      : mock_callback_receiver_(new MockInterceptCallbackReceiver()),
-        io_thread_state_(NULL) {
-  }
-
-  void SetUp() override { RenderViewHostTestHarness::SetUp(); }
-
-  void TearDown() override {
-    if (web_contents())
-      web_contents()->SetDelegate(NULL);
-
-    content::BrowserThread::DeleteSoon(
-        content::BrowserThread::IO, FROM_HERE, io_thread_state_);
-
-    RenderViewHostTestHarness::TearDown();
-  }
-
-  void SetIOThreadState(TestIOThreadState* io_thread_state) {
-    io_thread_state_ = io_thread_state;
-  }
-
-  void RunThrottleWillStartRequestOnIOThread(
-      const GURL& url,
-      const std::string& request_method,
-      RedirectMode redirect_mode,
-      int render_process_id,
-      int render_frame_id,
-      bool* defer) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    TestIOThreadState* io_thread_state =
-        new TestIOThreadState(url, render_process_id, render_frame_id,
-                              request_method, redirect_mode,
-                              mock_callback_receiver_.get());
-
-    SetIOThreadState(io_thread_state);
-
-    if (redirect_mode == REDIRECT_MODE_NO_REDIRECT) {
-      io_thread_state->ThrottleWillStartRequest(defer);
-    } else {
-      // 302 redirects convert POSTs to gets.
-      net::RedirectInfo redirect_info;
-      redirect_info.new_url = url;
-      redirect_info.new_method = "GET";
-      io_thread_state->ThrottleWillRedirectRequest(redirect_info, defer);
-    }
-  }
-
- protected:
-  enum ShouldIgnoreNavigationCallbackAction {
-    IgnoreNavigation,
-    DontIgnoreNavigation
-  };
-
-  void SetUpWebContentsDelegateAndDrainRunLoop(
-      ShouldIgnoreNavigationCallbackAction callback_action,
-      bool* defer) {
-    ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
-      .WillByDefault(Return(callback_action == IgnoreNavigation));
-    EXPECT_CALL(*mock_callback_receiver_,
-                ShouldIgnoreNavigation(web_contents(),
-                                       NavigationParamsUrlIsTest()))
-      .Times(1);
-
-    content::BrowserThread::PostTask(
-        content::BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(
-            &InterceptNavigationResourceThrottleTest::
-                RunThrottleWillStartRequestOnIOThread,
-            base::Unretained(this),
-            GURL(kTestUrl),
-            "GET",
-            REDIRECT_MODE_NO_REDIRECT,
-            web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-            web_contents()->GetMainFrame()->GetRoutingID(),
-            base::Unretained(defer)));
-
-    // Wait for the request to finish processing.
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void WaitForPreviouslyScheduledIoThreadWork() {
-    base::WaitableEvent io_thread_work_done(true, false);
-    content::BrowserThread::PostTask(
-        content::BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(
-          &base::WaitableEvent::Signal,
-          base::Unretained(&io_thread_work_done)));
-    io_thread_work_done.Wait();
-  }
-
-  scoped_ptr<MockInterceptCallbackReceiver> mock_callback_receiver_;
-  TestIOThreadState* io_thread_state_;
-};
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       RequestDeferredAndResumedIfNavigationNotIgnored) {
-  bool defer = false;
-  SetUpWebContentsDelegateAndDrainRunLoop(DontIgnoreNavigation, &defer);
-
-  EXPECT_TRUE(defer);
-  ASSERT_TRUE(io_thread_state_);
-  EXPECT_TRUE(io_thread_state_->request_resumed());
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       RequestDeferredAndCancelledIfNavigationIgnored) {
-  bool defer = false;
-  SetUpWebContentsDelegateAndDrainRunLoop(IgnoreNavigation, &defer);
-
-  EXPECT_TRUE(defer);
-  ASSERT_TRUE(io_thread_state_);
-  EXPECT_TRUE(io_thread_state_->request_cancelled());
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       NoCallbackMadeIfContentsDeletedWhileThrottleRunning) {
-  bool defer = false;
-
-  // The tested scenario is when the WebContents is deleted after the
-  // ResourceThrottle has finished processing on the IO thread but before the
-  // UI thread callback has been processed.  Since both threads in this test
-  // are serviced by one message loop, the post order is the execution order.
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(_, _))
-      .Times(0);
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-          RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kTestUrl),
-          "GET",
-          REDIRECT_MODE_NO_REDIRECT,
-          web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-          web_contents()->GetMainFrame()->GetRoutingID(),
-          base::Unretained(&defer)));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(
-          &RenderViewHostTestHarness::DeleteContents,
-          base::Unretained(this)));
-
-  // The WebContents will now be deleted and only after that will the UI-thread
-  // callback posted by the ResourceThrottle be executed.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_TRUE(defer);
-  ASSERT_TRUE(io_thread_state_);
-  EXPECT_TRUE(io_thread_state_->request_resumed());
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       RequestNotDeferredForRequestNotAssociatedWithARenderView) {
-  bool defer = false;
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-              RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kTestUrl),
-          "GET",
-          REDIRECT_MODE_NO_REDIRECT,
-          MSG_ROUTING_NONE,
-          MSG_ROUTING_NONE,
-          base::Unretained(&defer)));
-
-  // Wait for the request to finish processing.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_FALSE(defer);
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       CallbackCalledWithFilteredUrl) {
-  bool defer = false;
-
-  ON_CALL(*mock_callback_receiver_,
-          ShouldIgnoreNavigation(_, NavigationParamsUrlIsSafe()))
-      .WillByDefault(Return(false));
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(_, NavigationParamsUrlIsSafe()))
-      .Times(1);
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-              RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kUnsafeTestUrl),
-          "GET",
-          REDIRECT_MODE_NO_REDIRECT,
-          web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-          web_contents()->GetMainFrame()->GetRoutingID(),
-          base::Unretained(&defer)));
-
-  // Wait for the request to finish processing.
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       CallbackIsPostFalseForGet) {
-  bool defer = false;
-
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(_, AllOf(
-                  NavigationParamsUrlIsSafe(),
-                  Property(&NavigationParams::is_post, Eq(false)))))
-      .WillOnce(Return(false));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-              RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kTestUrl),
-          "GET",
-          REDIRECT_MODE_NO_REDIRECT,
-          web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-          web_contents()->GetMainFrame()->GetRoutingID(),
-          base::Unretained(&defer)));
-
-  // Wait for the request to finish processing.
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       CallbackIsPostTrueForPost) {
-  bool defer = false;
-
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(_, AllOf(
-                  NavigationParamsUrlIsSafe(),
-                  Property(&NavigationParams::is_post, Eq(true)))))
-      .WillOnce(Return(false));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-              RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kTestUrl),
-          "POST",
-          REDIRECT_MODE_NO_REDIRECT,
-          web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-          web_contents()->GetMainFrame()->GetRoutingID(),
-          base::Unretained(&defer)));
-
-  // Wait for the request to finish processing.
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterceptNavigationResourceThrottleTest,
-       CallbackIsPostFalseForPostConvertedToGetBy302) {
-  bool defer = false;
-
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(_, AllOf(
-                  NavigationParamsUrlIsSafe(),
-                  Property(&NavigationParams::is_post, Eq(false)))))
-      .WillOnce(Return(false));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &InterceptNavigationResourceThrottleTest::
-              RunThrottleWillStartRequestOnIOThread,
-          base::Unretained(this),
-          GURL(kTestUrl),
-          "POST",
-          REDIRECT_MODE_302,
-          web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
-          web_contents()->GetMainFrame()->GetRoutingID(),
-          base::Unretained(&defer)));
-
-  // Wait for the request to finish processing.
-  base::RunLoop().RunUntilIdle();
-}
-
-}  // namespace navigation_interception
diff --git a/components/navigation_interception/intercept_navigation_throttle.cc b/components/navigation_interception/intercept_navigation_throttle.cc
new file mode 100644
index 0000000..cc256a12
--- /dev/null
+++ b/components/navigation_interception/intercept_navigation_throttle.cc
@@ -0,0 +1,49 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/navigation_interception/intercept_navigation_throttle.h"
+
+#include "components/navigation_interception/navigation_params.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
+
+namespace navigation_interception {
+
+InterceptNavigationThrottle::InterceptNavigationThrottle(
+    content::NavigationHandle* navigation_handle,
+    CheckCallback should_ignore_callback)
+    : content::NavigationThrottle(navigation_handle),
+      should_ignore_callback_(should_ignore_callback) {}
+
+InterceptNavigationThrottle::~InterceptNavigationThrottle() {}
+
+content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::WillStartRequest() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return CheckIfShouldIgnoreNavigation(false);
+}
+
+content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::WillRedirectRequest() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return CheckIfShouldIgnoreNavigation(true);
+}
+
+content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation(bool is_redirect) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  NavigationParams navigation_params(
+      navigation_handle()->GetURL(), navigation_handle()->GetReferrer(),
+      navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(),
+      navigation_handle()->GetPageTransition(), is_redirect,
+      navigation_handle()->IsExternalProtocol(), true);
+
+  bool should_ignore_navigation = should_ignore_callback_.Run(
+      navigation_handle()->GetWebContents(), navigation_params);
+  return should_ignore_navigation
+             ? content::NavigationThrottle::CANCEL_AND_IGNORE
+             : content::NavigationThrottle::PROCEED;
+}
+
+}  // namespace navigation_interception
diff --git a/components/navigation_interception/intercept_navigation_throttle.h b/components/navigation_interception/intercept_navigation_throttle.h
new file mode 100644
index 0000000..0b7f7460
--- /dev/null
+++ b/components/navigation_interception/intercept_navigation_throttle.h
@@ -0,0 +1,51 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_
+#define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/navigation_throttle.h"
+
+class GURL;
+
+namespace content {
+class NavigationHandle;
+class WebContents;
+}
+
+namespace navigation_interception {
+
+class NavigationParams;
+
+// This class allows the provider of the Callback to selectively ignore top
+// level navigations. This is a UI thread class.
+class InterceptNavigationThrottle : public content::NavigationThrottle {
+ public:
+  typedef base::Callback<bool(content::WebContents* /* source */,
+                              const NavigationParams& /* navigation_params */)>
+      CheckCallback;
+
+  InterceptNavigationThrottle(content::NavigationHandle* navigation_handle,
+                              CheckCallback should_ignore_callback);
+  ~InterceptNavigationThrottle() override;
+
+  // content::NavigationThrottle implementation:
+  ThrottleCheckResult WillStartRequest() override;
+  ThrottleCheckResult WillRedirectRequest() override;
+
+ private:
+  ThrottleCheckResult CheckIfShouldIgnoreNavigation(bool is_redirect);
+
+  CheckCallback should_ignore_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterceptNavigationThrottle);
+};
+
+}  // namespace navigation_interception
+
+#endif  // COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_
diff --git a/components/navigation_interception/intercept_navigation_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_throttle_unittest.cc
new file mode 100644
index 0000000..15e05ef
--- /dev/null
+++ b/components/navigation_interception/intercept_navigation_throttle_unittest.cc
@@ -0,0 +1,165 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "components/navigation_interception/intercept_navigation_throttle.h"
+#include "components/navigation_interception/navigation_params.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_renderer_host.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::NavigationThrottle;
+using testing::_;
+using testing::Eq;
+using testing::Ne;
+using testing::Property;
+using testing::Return;
+
+namespace navigation_interception {
+
+namespace {
+
+const char kTestUrl[] = "http://www.test.com/";
+
+// The MS C++ compiler complains about not being able to resolve which url()
+// method (const or non-const) to use if we use the Property matcher to check
+// the return value of the NavigationParams::url() method.
+// It is possible to suppress the error by specifying the types directly but
+// that results in very ugly syntax, which is why these custom matchers are
+// used instead.
+MATCHER(NavigationParamsUrlIsTest, "") {
+  return arg.url() == GURL(kTestUrl);
+}
+
+}  // namespace
+
+// MockInterceptCallbackReceiver ----------------------------------------------
+
+class MockInterceptCallbackReceiver {
+ public:
+  MOCK_METHOD2(ShouldIgnoreNavigation,
+               bool(content::WebContents* source,
+                    const NavigationParams& navigation_params));
+};
+
+// InterceptNavigationThrottleTest ------------------------------------
+
+class InterceptNavigationThrottleTest
+    : public content::RenderViewHostTestHarness {
+ public:
+  InterceptNavigationThrottleTest()
+      : mock_callback_receiver_(new MockInterceptCallbackReceiver()) {}
+
+  NavigationThrottle::ThrottleCheckResult
+  SimulateWillStart(const GURL& url, const GURL& sanitized_url, bool is_post) {
+    scoped_ptr<content::NavigationHandle> test_handle =
+        content::NavigationHandle::CreateNavigationHandleForTesting(
+            url, true, web_contents());
+    test_handle->RegisterThrottleForTesting(
+        scoped_ptr<NavigationThrottle>(
+            new InterceptNavigationThrottle(
+                test_handle.get(),
+                base::Bind(
+                    &MockInterceptCallbackReceiver::ShouldIgnoreNavigation,
+                    base::Unretained(mock_callback_receiver_.get()))))
+            .Pass());
+    return test_handle->CallWillStartRequestForTesting(
+        is_post, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false);
+  }
+
+  NavigationThrottle::ThrottleCheckResult Simulate302() {
+    scoped_ptr<content::NavigationHandle> test_handle =
+        content::NavigationHandle::CreateNavigationHandleForTesting(
+            GURL(kTestUrl), true, web_contents());
+    test_handle->RegisterThrottleForTesting(
+        scoped_ptr<NavigationThrottle>(
+            new InterceptNavigationThrottle(
+                test_handle.get(),
+                base::Bind(
+                    &MockInterceptCallbackReceiver::ShouldIgnoreNavigation,
+                    base::Unretained(mock_callback_receiver_.get()))))
+            .Pass());
+    test_handle->CallWillStartRequestForTesting(
+        true, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false);
+    return test_handle->CallWillRedirectRequestForTesting(GURL(kTestUrl), false,
+                                                          GURL(), false);
+  }
+
+  scoped_ptr<MockInterceptCallbackReceiver> mock_callback_receiver_;
+};
+
+TEST_F(InterceptNavigationThrottleTest,
+       RequestDeferredAndResumedIfNavigationNotIgnored) {
+  ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
+      .WillByDefault(Return(false));
+  EXPECT_CALL(
+      *mock_callback_receiver_,
+      ShouldIgnoreNavigation(web_contents(), NavigationParamsUrlIsTest()));
+  NavigationThrottle::ThrottleCheckResult result =
+      SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false);
+
+  EXPECT_EQ(NavigationThrottle::PROCEED, result);
+}
+
+TEST_F(InterceptNavigationThrottleTest,
+       RequestDeferredAndCancelledIfNavigationIgnored) {
+  ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
+      .WillByDefault(Return(true));
+  EXPECT_CALL(
+      *mock_callback_receiver_,
+      ShouldIgnoreNavigation(web_contents(), NavigationParamsUrlIsTest()));
+  NavigationThrottle::ThrottleCheckResult result =
+      SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false);
+
+  EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, result);
+}
+
+TEST_F(InterceptNavigationThrottleTest, CallbackIsPostFalseForGet) {
+  EXPECT_CALL(*mock_callback_receiver_,
+              ShouldIgnoreNavigation(
+                  _, AllOf(NavigationParamsUrlIsTest(),
+                           Property(&NavigationParams::is_post, Eq(false)))))
+      .WillOnce(Return(false));
+
+  NavigationThrottle::ThrottleCheckResult result =
+      SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false);
+
+  EXPECT_EQ(NavigationThrottle::PROCEED, result);
+}
+
+TEST_F(InterceptNavigationThrottleTest, CallbackIsPostTrueForPost) {
+  EXPECT_CALL(*mock_callback_receiver_,
+              ShouldIgnoreNavigation(
+                  _, AllOf(NavigationParamsUrlIsTest(),
+                           Property(&NavigationParams::is_post, Eq(true)))))
+      .WillOnce(Return(false));
+  NavigationThrottle::ThrottleCheckResult result =
+      SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), true);
+
+  EXPECT_EQ(NavigationThrottle::PROCEED, result);
+}
+
+TEST_F(InterceptNavigationThrottleTest,
+       CallbackIsPostFalseForPostConvertedToGetBy302) {
+  EXPECT_CALL(*mock_callback_receiver_,
+              ShouldIgnoreNavigation(
+                  _, AllOf(NavigationParamsUrlIsTest(),
+                           Property(&NavigationParams::is_post, Eq(true)))))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_callback_receiver_,
+              ShouldIgnoreNavigation(
+                  _, AllOf(NavigationParamsUrlIsTest(),
+                           Property(&NavigationParams::is_post, Eq(false)))))
+      .WillOnce(Return(false));
+  NavigationThrottle::ThrottleCheckResult result = Simulate302();
+
+  EXPECT_EQ(NavigationThrottle::PROCEED, result);
+}
+
+}  // namespace navigation_interception
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index c6767dd9..c33278f 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -11,7 +11,6 @@
 #include "base/format_macros.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/user_metrics.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -477,10 +476,6 @@
     bool has_selected_text,
     bool prevent_inline_autocomplete,
     bool entering_keyword_mode) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 OmniboxEditModel::StartAutocomplete"));
   size_t cursor_position;
   if (inline_autocomplete_text_.empty()) {
     // Cursor position is equivalent to the current selection's end.
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc
index 0ec1e08..622b7e4e 100644
--- a/components/omnibox/browser/omnibox_popup_model.cc
+++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -161,6 +161,8 @@
   view_->InvalidateLine(prev_selected_line);
   view_->InvalidateLine(selected_line_);
 
+  view_->OnLineSelected(selected_line_);
+
   // Update the edit with the new data for this match.
   // TODO(pkasting): If |selected_line_| moves to the controller, this can be
   // eliminated and just become a call to the observer on the edit.
diff --git a/components/omnibox/browser/omnibox_popup_view.h b/components/omnibox/browser/omnibox_popup_view.h
index 57823da..5ba71fe 100644
--- a/components/omnibox/browser/omnibox_popup_view.h
+++ b/components/omnibox/browser/omnibox_popup_view.h
@@ -27,6 +27,9 @@
   // Invalidates one line of the autocomplete popup.
   virtual void InvalidateLine(size_t line) = 0;
 
+  // Invoked when the specified line has been selected.
+  virtual void OnLineSelected(size_t line) = 0;
+
   // Redraws the popup window to match any changes in the result set; this may
   // mean opening or closing the window.
   virtual void UpdatePopupAppearance() = 0;
diff --git a/components/omnibox/browser/suggestion_answer.cc b/components/omnibox/browser/suggestion_answer.cc
index 8e8b62f5..dc48910 100644
--- a/components/omnibox/browser/suggestion_answer.cc
+++ b/components/omnibox/browser/suggestion_answer.cc
@@ -4,6 +4,7 @@
 
 #include "components/omnibox/browser/suggestion_answer.h"
 
+#include "base/i18n/rtl.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -23,6 +24,15 @@
 static const char kAnswerJsonImage[] = "i";
 static const char kAnswerJsonImageData[] = "i.d";
 
+void AppendWithSpace(const SuggestionAnswer::TextField* text,
+                     base::string16* output) {
+  if (!text)
+    return;
+  if (!output->empty() && !text->text().empty())
+    *output += ' ';
+  *output += text->text();
+}
+
 }  // namespace
 
 // SuggestionAnswer::TextField -------------------------------------------------
@@ -145,6 +155,17 @@
   return image_url_ == line.image_url_;
 }
 
+// TODO(jdonnelly): When updating the display of answers in RTL languages,
+// modify this to be consistent.
+base::string16 SuggestionAnswer::ImageLine::AccessibleText() const {
+  base::string16 result;
+  for (const TextField& text_field : text_fields_)
+    AppendWithSpace(&text_field, &result);
+  AppendWithSpace(additional_text_.get(), &result);
+  AppendWithSpace(status_text_.get(), &result);
+  return result;
+}
+
 // SuggestionAnswer ------------------------------------------------------------
 
 SuggestionAnswer::SuggestionAnswer() : type_(-1) {}
diff --git a/components/omnibox/browser/suggestion_answer.h b/components/omnibox/browser/suggestion_answer.h
index 08a2016..e64fe4d 100644
--- a/components/omnibox/browser/suggestion_answer.h
+++ b/components/omnibox/browser/suggestion_answer.h
@@ -98,6 +98,10 @@
 
     bool Equals(const ImageLine& line) const;
 
+    // Returns a string appropriate for use as a readable representation of the
+    // content of this line.
+    base::string16 AccessibleText() const;
+
    private:
     // Forbid assignment.
     ImageLine& operator=(const ImageLine&);
diff --git a/components/onc/docs/onc_spec.html b/components/onc/docs/onc_spec.html
index f5f342e..df43eb8 100644
--- a/components/onc/docs/onc_spec.html
+++ b/components/onc/docs/onc_spec.html
@@ -2250,7 +2250,7 @@
     <dt class="field">HomeProvider</dt>
     <dd>
       <span class="field_meta">(optional, read-only)
-        <span class="type">array of CellularProvider</span>
+        <span class="type">CellularProvider</span>
       </span>
       Description of the operator that issued the SIM card currently installed
       in the modem.
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index 3a1fbd9..fdde938 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -47,16 +47,99 @@
   return true;
 }
 
+base::Time WallTimeFromTimeTicks(base::TimeTicks time) {
+  return base::Time::FromDoubleT(
+      (time - base::TimeTicks::UnixEpoch()).InSecondsF());
+}
+
 }  // namespace
 
+#define PAGE_LOAD_HISTOGRAM(name, sample)                           \
+  UMA_HISTOGRAM_CUSTOM_TIMES(name, sample,                          \
+                             base::TimeDelta::FromMilliseconds(10), \
+                             base::TimeDelta::FromMinutes(10), 100)
+
+PageLoadTracker::PageLoadTracker(bool in_foreground)
+    : has_commit_(false), started_in_foreground_(in_foreground) {}
+
+PageLoadTracker::~PageLoadTracker() {
+  if (has_commit_)
+    RecordTimingHistograms();
+}
+
+void PageLoadTracker::WebContentsHidden() {
+  // Only log the first time we background in a given page load.
+  if (background_time_.is_null()) {
+    background_time_ = base::TimeTicks::Now();
+  }
+}
+
+void PageLoadTracker::Commit() {
+  has_commit_ = true;
+}
+
+bool PageLoadTracker::UpdateTiming(const PageLoadTiming& timing) {
+  // Throw away IPCs that are not relevant to the current navigation.
+  if (!timing_.navigation_start.is_null() &&
+      timing_.navigation_start != timing.navigation_start) {
+    // TODO(csharrison) uma log a counter here
+    return false;
+  }
+  if (IsValidPageLoadTiming(timing)) {
+    timing_ = timing;
+    return true;
+  }
+  return false;
+}
+
+void PageLoadTracker::RecordTimingHistograms() {
+  DCHECK(has_commit_);
+  // This method is similar to how blink converts TimeTicks to epoch time.
+  // There may be slight inaccuracies due to inter-process timestamps, but
+  // this solution is the best we have right now.
+  base::TimeDelta background_delta;
+  if (started_in_foreground_) {
+    background_delta = background_time_.is_null()
+        ? base::TimeDelta::Max()
+        : WallTimeFromTimeTicks(background_time_) - timing_.navigation_start;
+  }
+
+  if (!timing_.dom_content_loaded_event_start.is_zero()) {
+    if (timing_.dom_content_loaded_event_start < background_delta) {
+      PAGE_LOAD_HISTOGRAM(
+          "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired",
+          timing_.dom_content_loaded_event_start);
+    } else {
+      PAGE_LOAD_HISTOGRAM(
+          "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.BG",
+          timing_.dom_content_loaded_event_start);
+    }
+  }
+  if (!timing_.load_event_start.is_zero()) {
+    if (timing_.load_event_start < background_delta) {
+      PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToLoadEventFired",
+                          timing_.load_event_start);
+    } else {
+      PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToLoadEventFired.BG",
+                          timing_.load_event_start);
+    }
+  }
+  if (!timing_.first_layout.is_zero()) {
+    if (timing_.first_layout < background_delta) {
+      PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout",
+                          timing_.first_layout);
+    } else {
+      PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout.BG",
+                          timing_.first_layout);
+    }
+  }
+}
+
 MetricsWebContentsObserver::MetricsWebContentsObserver(
     content::WebContents* web_contents)
-    : content::WebContentsObserver(web_contents) {}
+    : content::WebContentsObserver(web_contents), in_foreground_(false) {}
 
-// This object is tied to a single WebContents for its entire lifetime.
-MetricsWebContentsObserver::~MetricsWebContentsObserver() {
-  RecordTimingHistograms();
-}
+MetricsWebContentsObserver::~MetricsWebContentsObserver() {}
 
 bool MetricsWebContentsObserver::OnMessageReceived(
     const IPC::Message& message,
@@ -71,32 +154,74 @@
   return handled;
 }
 
+void MetricsWebContentsObserver::DidStartNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (!navigation_handle->IsInMainFrame())
+    return;
+  // We can have two provisional loads in some cases. E.g. a same-site
+  // navigation can have a concurrent cross-process navigation started
+  // from the omnibox.
+  DCHECK_GT(2ul, provisional_loads_.size());
+  provisional_loads_.insert(
+      navigation_handle, make_scoped_ptr(new PageLoadTracker(in_foreground_)));
+}
+
 void MetricsWebContentsObserver::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
+  if (!navigation_handle->IsInMainFrame())
+    return;
+
+  scoped_ptr<PageLoadTracker> finished_nav(
+      provisional_loads_.take_and_erase(navigation_handle));
+  DCHECK(finished_nav);
+
+  // TODO(csharrison) handle the two error cases:
+  // 1. Error pages that replace the previous page.
+  // 2. Error pages that leave the user on the previous page.
+  // For now these cases will be ignored.
   if (!navigation_handle->HasCommitted())
     return;
-  if (navigation_handle->IsInMainFrame() && !navigation_handle->IsSamePage())
-    RecordTimingHistograms();
-  if (IsRelevantNavigation(navigation_handle))
-    current_timing_.reset(new PageLoadTiming());
+
+  // Don't treat a same-page nav as a new page load.
+  if (navigation_handle->IsSamePage())
+    return;
+
+  // Eagerly log the previous UMA even if we don't care about the current
+  // navigation.
+  committed_load_.reset();
+
+  if (!IsRelevantNavigation(navigation_handle))
+    return;
+
+  committed_load_ = finished_nav.Pass();
+  committed_load_->Commit();
 }
 
-// This will occur when the process for the main RenderFrameHost exits.
-// This will happen with a normal exit or a crash.
+void MetricsWebContentsObserver::WasShown() {
+  in_foreground_ = true;
+}
+
+void MetricsWebContentsObserver::WasHidden() {
+  in_foreground_ = false;
+  if (committed_load_)
+    committed_load_->WebContentsHidden();
+  for (const auto& kv : provisional_loads_) {
+    kv.second->WebContentsHidden();
+  }
+}
+
+// This will occur when the process for the main RenderFrameHost exits, either
+// normally or from a crash. We eagerly log data from the last committed load if
+// we have one.
 void MetricsWebContentsObserver::RenderProcessGone(
     base::TerminationStatus status) {
-  RecordTimingHistograms();
+  committed_load_.reset();
 }
 
-#define PAGE_LOAD_HISTOGRAM(name, sample)                           \
-  UMA_HISTOGRAM_CUSTOM_TIMES(name, sample,                          \
-                             base::TimeDelta::FromMilliseconds(10), \
-                             base::TimeDelta::FromMinutes(10), 100);
-
 void MetricsWebContentsObserver::OnTimingUpdated(
     content::RenderFrameHost* render_frame_host,
     const PageLoadTiming& timing) {
-  if (!current_timing_)
+  if (!committed_load_)
     return;
 
   // We may receive notifications from frames that have been navigated away
@@ -110,36 +235,7 @@
   if (!web_contents()->GetLastCommittedURL().SchemeIsHTTPOrHTTPS())
     return;
 
-  // Throw away IPCs that are not relevant to the current navigation.
-  if (!current_timing_->navigation_start.is_null() &&
-      timing.navigation_start != current_timing_->navigation_start) {
-    // TODO(csharrison) uma log a counter here
-    return;
-  }
-
-  *current_timing_ = timing;
-}
-
-void MetricsWebContentsObserver::RecordTimingHistograms() {
-  if (!current_timing_ || !IsValidPageLoadTiming(*current_timing_))
-    return;
-
-  if (!current_timing_->dom_content_loaded_event_start.is_zero()) {
-    PAGE_LOAD_HISTOGRAM(
-        "PageLoad.Timing.NavigationToDOMContentLoadedEventFired",
-        current_timing_->dom_content_loaded_event_start);
-  }
-
-  if (!current_timing_->load_event_start.is_zero()) {
-    PAGE_LOAD_HISTOGRAM("PageLoad.Timing.NavigationToLoadEventFired",
-                        current_timing_->load_event_start);
-  }
-
-  if (!current_timing_->first_layout.is_zero()) {
-    PAGE_LOAD_HISTOGRAM("PageLoad.Timing.NavigationToFirstLayout",
-                        current_timing_->first_layout);
-  }
-  current_timing_.reset();
+  committed_load_->UpdateTiming(timing);
 }
 
 bool MetricsWebContentsObserver::IsRelevantNavigation(
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.h b/components/page_load_metrics/browser/metrics_web_contents_observer.h
index 5fa52c0..45780c1 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.h
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_WEB_CONTENTS_OBSERVER_H_
 #define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_WEB_CONTENTS_OBSERVER_H_
 
+#include "base/containers/scoped_ptr_map.h"
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "components/page_load_metrics/common/page_load_timing.h"
@@ -23,6 +24,32 @@
 
 namespace page_load_metrics {
 
+class PageLoadTracker {
+ public:
+  explicit PageLoadTracker(bool in_foreground);
+  ~PageLoadTracker();
+  void Commit();
+  void WebContentsHidden();
+
+  // Returns true if the timing was successfully updated.
+  bool UpdateTiming(const PageLoadTiming& timing);
+
+ private:
+  void RecordTimingHistograms();
+
+  bool has_commit_;
+
+  // We record separate metrics for events that occur after a background,
+  // because metrics like layout/paint are delayed artificially
+  // when they occur in the bacground.
+  base::TimeTicks background_time_;
+  bool started_in_foreground_;
+
+  PageLoadTiming timing_;
+
+  DISALLOW_COPY_AND_ASSIGN(PageLoadTracker);
+};
+
 // MetricsWebContentsObserver logs page load UMA metrics based on
 // IPC messages received from a MetricsRenderFrameObserver.
 class MetricsWebContentsObserver
@@ -34,8 +61,14 @@
   // content::WebContentsObserver implementation:
   bool OnMessageReceived(const IPC::Message& message,
                          content::RenderFrameHost* render_frame_host) override;
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
+
+  void WasShown() override;
+  void WasHidden() override;
+
   void RenderProcessGone(base::TerminationStatus status) override;
 
  private:
@@ -44,13 +77,19 @@
   friend class MetricsWebContentsObserverTest;
 
   void OnTimingUpdated(content::RenderFrameHost*, const PageLoadTiming& timing);
-  void RecordTimingHistograms();
 
   bool IsRelevantNavigation(content::NavigationHandle* navigation_handle);
 
-  // Will be null before any navigations have committed. When a navigation
-  // commits we will initialize this as empty.
-  scoped_ptr<PageLoadTiming> current_timing_;
+  // True if the web contents is currently in the foreground.
+  bool in_foreground_;
+
+  // This map tracks all of the navigations ongoing that are not committed
+  // yet. Once a navigation is committed, it moves from the map to
+  // committed_load_. Note that a PageLoadTrackers NavigationHandle is only
+  // valid until commit time, when we remove it from the map.
+  base::ScopedPtrMap<content::NavigationHandle*, scoped_ptr<PageLoadTracker>>
+      provisional_loads_;
+  scoped_ptr<PageLoadTracker> committed_load_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserver);
 };
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
index ee2639f..c72e647 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
@@ -23,12 +23,18 @@
 const char kDefaultTestUrl2[] = "https://whatever.com";
 
 const char kHistogramNameFirstLayout[] =
-    "PageLoad.Timing.NavigationToFirstLayout";
+    "PageLoad.Timing2.NavigationToFirstLayout";
 const char kHistogramNameDomContent[] =
-    "PageLoad.Timing.NavigationToDOMContentLoadedEventFired";
+    "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired";
 const char kHistogramNameLoad[] =
-    "PageLoad.Timing.NavigationToLoadEventFired";
+    "PageLoad.Timing2.NavigationToLoadEventFired";
 
+const char kBGHistogramNameFirstLayout[] =
+    "PageLoad.Timing2.NavigationToFirstLayout.BG";
+const char kBGHistogramNameDomContent[] =
+    "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.BG";
+const char kBGHistogramNameLoad[] =
+    "PageLoad.Timing2.NavigationToLoadEventFired.BG";
 }  //  namespace
 
 class MetricsWebContentsObserverTest
@@ -39,6 +45,7 @@
   void SetUp() override {
     RenderViewHostTestHarness::SetUp();
     observer_ = make_scoped_ptr(new MetricsWebContentsObserver(web_contents()));
+    observer_->WasShown();
   }
 
   void AssertNoHistogramsLogged() {
@@ -211,4 +218,120 @@
                                       1);
 }
 
+TEST_F(MetricsWebContentsObserverTest, BackgroundDifferentHistogram) {
+  base::TimeDelta first_layout = base::TimeDelta::FromSeconds(2);
+
+  PageLoadTiming timing;
+  timing.navigation_start = base::Time::FromDoubleT(
+      (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InSecondsF());
+  timing.first_layout = first_layout;
+
+  content::WebContentsTester* web_contents_tester =
+      content::WebContentsTester::For(web_contents());
+
+  // Simulate "Open link in new tab."
+  observer_->WasHidden();
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+
+  observer_->OnMessageReceived(
+      PageLoadMetricsMsg_TimingUpdated(observer_->routing_id(), timing),
+      web_contents()->GetMainFrame());
+
+  // Simulate switching to the tab and making another navigation.
+  observer_->WasShown();
+  AssertNoHistogramsLogged();
+
+  // Navigate again to force histogram recording.
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2));
+
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameDomContent, 0);
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameLoad, 0);
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameFirstLayout, 1);
+  histogram_tester_.ExpectBucketCount(kBGHistogramNameFirstLayout,
+                                      first_layout.InMilliseconds(), 1);
+
+  histogram_tester_.ExpectTotalCount(kHistogramNameDomContent, 0);
+  histogram_tester_.ExpectTotalCount(kHistogramNameLoad, 0);
+  histogram_tester_.ExpectTotalCount(kHistogramNameFirstLayout, 0);
+}
+
+TEST_F(MetricsWebContentsObserverTest, OnlyBackgroundLaterEvents) {
+  PageLoadTiming timing;
+  timing.navigation_start = base::Time::FromDoubleT(
+      (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InSecondsF() - 1);
+
+  timing.response_start = base::TimeDelta::FromMilliseconds(1);
+  timing.dom_content_loaded_event_start = base::TimeDelta::FromMilliseconds(1);
+
+  content::WebContentsTester* web_contents_tester =
+      content::WebContentsTester::For(web_contents());
+
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+  observer_->OnMessageReceived(
+      PageLoadMetricsMsg_TimingUpdated(observer_->routing_id(), timing),
+      web_contents()->GetMainFrame());
+
+  // Background the tab, then forground it.
+  observer_->WasHidden();
+  observer_->WasShown();
+  timing.first_layout = base::TimeDelta::FromSeconds(3);
+  observer_->OnMessageReceived(
+      PageLoadMetricsMsg_TimingUpdated(observer_->routing_id(), timing),
+      web_contents()->GetMainFrame());
+
+  // Navigate again to force histogram recording.
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2));
+
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameDomContent, 0);
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameLoad, 0);
+  histogram_tester_.ExpectTotalCount(kBGHistogramNameFirstLayout, 1);
+  histogram_tester_.ExpectBucketCount(kBGHistogramNameFirstLayout,
+                                      timing.first_layout.InMilliseconds(), 1);
+
+  histogram_tester_.ExpectTotalCount(kHistogramNameDomContent, 1);
+  histogram_tester_.ExpectBucketCount(
+      kHistogramNameDomContent,
+      timing.dom_content_loaded_event_start.InMilliseconds(), 1);
+  histogram_tester_.ExpectTotalCount(kHistogramNameLoad, 0);
+  histogram_tester_.ExpectTotalCount(kHistogramNameFirstLayout, 0);
+}
+
+TEST_F(MetricsWebContentsObserverTest, DontBackgroundQuickerLoad) {
+  base::TimeDelta first_layout = base::TimeDelta::FromMilliseconds(1);
+
+  PageLoadTiming timing;
+  timing.navigation_start = base::Time::FromDoubleT(1);
+  timing.first_layout = first_layout;
+
+  observer_->WasHidden();
+
+  // Open in new tab
+  content::WebContentsTester* web_contents_tester =
+      content::WebContentsTester::For(web_contents());
+
+  web_contents_tester->StartNavigation(GURL(kDefaultTestUrl));
+
+  content::RenderFrameHostTester* rfh_tester =
+      content::RenderFrameHostTester::For(main_rfh());
+
+  // Switch to the tab
+  observer_->WasShown();
+
+  // Start another provisional load
+  web_contents_tester->StartNavigation(GURL(kDefaultTestUrl2));
+  rfh_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2));
+  observer_->OnMessageReceived(
+      PageLoadMetricsMsg_TimingUpdated(observer_->routing_id(), timing),
+      main_rfh());
+  rfh_tester->SimulateNavigationStop();
+
+  // Navigate again to see if the timing updated for a subframe message.
+  web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+
+  histogram_tester_.ExpectTotalCount(kHistogramNameDomContent, 0);
+  histogram_tester_.ExpectTotalCount(kHistogramNameLoad, 0);
+  histogram_tester_.ExpectTotalCount(kHistogramNameFirstLayout, 1);
+  histogram_tester_.ExpectBucketCount(kHistogramNameFirstLayout,
+                                      first_layout.InMilliseconds(), 1);
+}
 }  // namespace page_load_metrics
diff --git a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
index e289b6a..7d06f9a 100644
--- a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
+++ b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
@@ -25,7 +25,7 @@
   return base::Time::FromDoubleT(event) - base::Time::FromDoubleT(start);
 }
 
-} //  namespace
+}  //  namespace
 
 MetricsRenderFrameObserver::MetricsRenderFrameObserver(
     content::RenderFrame* render_frame)
diff --git a/components/password_manager/core/browser/affiliated_match_helper.cc b/components/password_manager/core/browser/affiliated_match_helper.cc
index f01cc04..4c18384 100644
--- a/components/password_manager/core/browser/affiliated_match_helper.cc
+++ b/components/password_manager/core/browser/affiliated_match_helper.cc
@@ -133,20 +133,6 @@
          facet_uri.IsValidWebFacetURI();
 }
 
-// static
-ScopedVector<autofill::PasswordForm>
-AffiliatedMatchHelper::TransformAffiliatedAndroidCredentials(
-    const autofill::PasswordForm& observed_form,
-    ScopedVector<autofill::PasswordForm> android_credentials) {
-  for (autofill::PasswordForm* form : android_credentials) {
-    DCHECK_EQ(form->scheme, autofill::PasswordForm::SCHEME_HTML);
-    form->origin = observed_form.origin;
-    form->original_signon_realm = form->signon_realm;
-    form->signon_realm = observed_form.signon_realm;
-  }
-  return android_credentials.Pass();
-}
-
 void AffiliatedMatchHelper::SetTaskRunnerUsedForWaitingForTesting(
     const scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   task_runner_for_waiting_ = task_runner;
diff --git a/components/password_manager/core/browser/affiliated_match_helper.h b/components/password_manager/core/browser/affiliated_match_helper.h
index 18cb0d5c..5197174222 100644
--- a/components/password_manager/core/browser/affiliated_match_helper.h
+++ b/components/password_manager/core/browser/affiliated_match_helper.h
@@ -90,15 +90,6 @@
   // purposes of affiliation-based matching.
   static bool IsValidWebCredential(const autofill::PasswordForm& form);
 
-  // Consumes a list of |android_credentials| corresponding to applications that
-  // are affiliated with the realm of |observed_form|, and transforms them so
-  // as to make them fillable into |observed_form|. This can be called from any
-  // thread.
-  static ScopedVector<autofill::PasswordForm>
-  TransformAffiliatedAndroidCredentials(
-      const autofill::PasswordForm& observed_form,
-      ScopedVector<autofill::PasswordForm> android_credentials);
-
   // Sets the task runner to be used to delay I/O heavy initialization. Should
   // be called before Initialize(). Used only for testing.
   void SetTaskRunnerUsedForWaitingForTesting(
diff --git a/components/password_manager/core/browser/affiliated_match_helper_unittest.cc b/components/password_manager/core/browser/affiliated_match_helper_unittest.cc
index df14a14..633924f 100644
--- a/components/password_manager/core/browser/affiliated_match_helper_unittest.cc
+++ b/components/password_manager/core/browser/affiliated_match_helper_unittest.cc
@@ -99,7 +99,6 @@
 const char kTestAndroidFacetURIBeta3[] =
     "android://hash@com.yetanother.beta.android";
 const char kTestWebRealmBeta1[] = "https://one.beta.example.com/";
-const char kTestWebOriginBeta1[] = "https://one.beta.example.com/login";
 const char kTestAndroidRealmBeta2[] =
     "android://hash@com.example.beta.android/";
 const char kTestAndroidRealmBeta3[] =
@@ -564,44 +563,4 @@
   ASSERT_NO_FATAL_FAILURE(RunDeferredInitialization());
 }
 
-TEST_F(AffiliatedMatchHelperTest, TransformAffiliatedAndroidCredentials) {
-  const char kTestUsername2[] = "JohnDoe2";
-  const char kTestPassword2[] = "secret2";
-
-  autofill::PasswordForm observed_form(
-      GetTestObservedWebForm(kTestWebRealmBeta1, kTestWebOriginBeta1));
-
-  ScopedVector<autofill::PasswordForm> matched_forms;
-  matched_forms.push_back(make_scoped_ptr(new autofill::PasswordForm(
-      GetTestAndroidCredentials(kTestAndroidRealmBeta2))));
-  matched_forms.push_back(make_scoped_ptr(new autofill::PasswordForm(
-      GetTestAndroidCredentials(kTestAndroidRealmBeta3))));
-  matched_forms[1]->username_value = base::ASCIIToUTF16(kTestUsername2);
-  matched_forms[1]->password_value = base::ASCIIToUTF16(kTestPassword2);
-
-  ScopedVector<autofill::PasswordForm> transformed_forms =
-      AffiliatedMatchHelper::TransformAffiliatedAndroidCredentials(
-          observed_form, matched_forms.Pass());
-
-  ASSERT_EQ(2u, transformed_forms.size());
-
-  EXPECT_EQ(base::ASCIIToUTF16(kTestUsername),
-            transformed_forms[0]->username_value);
-  EXPECT_EQ(base::ASCIIToUTF16(kTestPassword),
-            transformed_forms[0]->password_value);
-  EXPECT_EQ(GURL(kTestWebOriginBeta1), transformed_forms[0]->origin);
-  EXPECT_EQ(kTestWebRealmBeta1, transformed_forms[0]->signon_realm);
-  EXPECT_EQ(kTestAndroidRealmBeta2,
-            transformed_forms[0]->original_signon_realm);
-
-  EXPECT_EQ(base::ASCIIToUTF16(kTestUsername2),
-            transformed_forms[1]->username_value);
-  EXPECT_EQ(base::ASCIIToUTF16(kTestPassword2),
-            transformed_forms[1]->password_value);
-  EXPECT_EQ(GURL(kTestWebOriginBeta1), transformed_forms[1]->origin);
-  EXPECT_EQ(kTestWebRealmBeta1, transformed_forms[1]->signon_realm);
-  EXPECT_EQ(kTestAndroidRealmBeta3,
-            transformed_forms[1]->original_signon_realm);
-}
-
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/credential_manager_pending_request_task.cc b/components/password_manager/core/browser/credential_manager_pending_request_task.cc
index 23ffc12..f51edc8 100644
--- a/components/password_manager/core/browser/credential_manager_pending_request_task.cc
+++ b/components/password_manager/core/browser/credential_manager_pending_request_task.cc
@@ -53,6 +53,7 @@
       form = nullptr;
     } else if (affiliated_realms_.count(form->signon_realm) &&
                AffiliatedMatchHelper::IsValidAndroidCredential(*form)) {
+      form->is_affiliated = true;
       affiliated_results.push_back(form);
       form = nullptr;
     }
@@ -69,13 +70,9 @@
     // TODO(mkwst): This doesn't create a PasswordForm that we can use to create
     // a FederatedCredential (via CreatePasswordFormFromCredentialInfo). We need
     // to fix that.
-    ScopedVector<autofill::PasswordForm> more_local_results(
-        AffiliatedMatchHelper::TransformAffiliatedAndroidCredentials(
-            delegate_->GetSynthesizedFormForOrigin(),
-            affiliated_results.Pass()));
-    local_results.insert(local_results.end(), more_local_results.begin(),
-                         more_local_results.end());
-    more_local_results.weak_clear();
+    local_results.insert(local_results.end(), affiliated_results.begin(),
+                         affiliated_results.end());
+    affiliated_results.weak_clear();
   }
 
   if ((local_results.empty() && federated_results.empty())) {
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 62194a5..788b4f4 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -936,9 +936,9 @@
 }
 
 bool LoginDatabase::RemoveLogin(const PasswordForm& form) {
-  if (form.IsPublicSuffixMatch()) {
-    // Do not try to remove |form|. It is a modified copy of a password stored
-    // for a different origin, and it is not contained in the database.
+  if (form.is_public_suffix_match) {
+    // TODO(dvadym): Discuss whether we should allow to remove PSL matched
+    // credentials.
     return false;
   }
   // Remove a login by UNIQUE-constrained fields.
@@ -1227,16 +1227,7 @@
       }
 
       psl_domain_match_metric = PSL_DOMAIN_MATCH_FOUND;
-      // This is not a perfect match, so we need to create a new valid result.
-      // We do this by copying over origin, signon realm and action from the
-      // observed form and setting the original signon realm to what we found
-      // in the database. We use the fact that |original_signon_realm| is
-      // non-empty to communicate that this match was found using public
-      // suffix matching.
-      new_form->original_signon_realm = new_form->signon_realm;
-      new_form->origin = psl_match->origin;
-      new_form->signon_realm = psl_match->signon_realm;
-      new_form->action = psl_match->action;
+      new_form->is_public_suffix_match = true;
     }
     forms->push_back(new_form.Pass());
   }
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index 2868f81..7faa7f6fd 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -339,8 +339,8 @@
   // Match against the mobile site.
   EXPECT_TRUE(db().GetLogins(form2, &result));
   EXPECT_EQ(1U, result.size());
-  EXPECT_EQ("https://mobile.foo.com/", result[0]->signon_realm);
-  EXPECT_EQ("https://foo.com/", result[0]->original_signon_realm);
+  EXPECT_EQ("https://foo.com/", result[0]->signon_realm);
+  EXPECT_TRUE(result[0]->is_public_suffix_match);
 
   // Try to remove PSL matched form
   EXPECT_FALSE(db().RemoveLogin(*result[0]));
@@ -461,8 +461,8 @@
   // Match against the mobile site.
   EXPECT_TRUE(db().GetLogins(form2, &result));
   EXPECT_EQ(1U, result.size());
-  EXPECT_EQ("https://mobile.foo.com/", result[0]->signon_realm);
-  EXPECT_EQ("https://foo.com/", result[0]->original_signon_realm);
+  EXPECT_EQ("https://foo.com/", result[0]->signon_realm);
+  EXPECT_TRUE(result[0]->is_public_suffix_match);
   result.clear();
 
   // Add baz.com desktop site.
@@ -493,8 +493,8 @@
   // Match against the mobile site of baz.com.
   EXPECT_TRUE(db().GetLogins(form3, &result));
   EXPECT_EQ(1U, result.size());
-  EXPECT_EQ("https://m.baz.com/", result[0]->signon_realm);
-  EXPECT_EQ("https://baz.com/", result[0]->original_signon_realm);
+  EXPECT_EQ("https://baz.com/", result[0]->signon_realm);
+  EXPECT_TRUE(result[0]->is_public_suffix_match);
   result.clear();
 }
 
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 1908ec56..6ba4ba22 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -234,7 +234,7 @@
 }
 
 bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const {
-  return pending_credentials_.IsPublicSuffixMatch();
+  return pending_credentials_.is_public_suffix_match;
 }
 
 void PasswordFormManager::ProvisionallySave(
@@ -442,27 +442,22 @@
 
       if (is_credential_protected)
         protected_credentials.push_back(login.Pass());
+      else
+        not_best_matches_.push_back(login.Pass());
       continue;
     }
 
-    // If there is another best-score match for the same username, replace it.
-    // TODO(vabr): Spare the replacing and keep the first instead of the last
-    // candidate.
+    // If there is another best-score match for the same username then leave it
+    // and add the current form to |not_best_matches_|.
     const base::string16& username = login->username_value;
     auto best_match_username = best_matches_.find(username);
-    if (best_match_username != best_matches_.end() &&
-        best_match_username->second == preferred_match_) {
-      preferred_match_ = nullptr;
+    if (best_match_username == best_matches_.end()) {
+      if (login->preferred)
+        preferred_match_ = login.get();
+      best_matches_.insert(username, login.Pass());
+    } else {
+      not_best_matches_.push_back(login.Pass());
     }
-    // Transfer ownership into the map.
-    const PasswordForm* best_match = login.get();
-    // TODO(mgiuca): Directly assign to |best_match_username|, instead of doing
-    // a second map traversal. This will only be possible once we have C++11
-    // library support (then |best_matches_| can be a map of scoped_ptrs instead
-    // of a ScopedPtrMap).
-    best_matches_.set(username, login.Pass());
-    if (best_match->preferred)
-      preferred_match_ = best_match;
   }
 
   // Add the protected results if we don't already have a result with the same
@@ -473,7 +468,10 @@
     scoped_ptr<PasswordForm> protege(*it);
     *it = nullptr;
     const base::string16& username = protege->username_value;
-    best_matches_.insert(username, protege.Pass());
+    if (best_matches_.find(username) == best_matches_.end())
+      best_matches_.insert(username, protege.Pass());
+    else
+      not_best_matches_.push_back(protege.Pass());
   }
 
   UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
@@ -525,10 +523,10 @@
   // TODO(engedy): Clean this up. See: https://crbug.com/476519.
   bool wait_for_username =
       client_->IsOffTheRecord() ||
-      (!IsValidAndroidFacetURI(preferred_match_->original_signon_realm) &&
+      (!IsValidAndroidFacetURI(preferred_match_->signon_realm) &&
        (observed_form_.action.GetWithEmptyPath() !=
             preferred_match_->action.GetWithEmptyPath() ||
-        preferred_match_->IsPublicSuffixMatch() ||
+        preferred_match_->is_public_suffix_match ||
         observed_form_.IsPossibleChangePasswordForm()));
   if (wait_for_username)
     manager_action_ = kManagerActionNone;
@@ -664,6 +662,7 @@
 
   UpdatePreferredLoginState(password_store);
 
+  bool password_was_updated = false;
   // Update the new preferred login.
   if (!selected_username_.empty()) {
     // Username has changed. We set this selected username as the real
@@ -689,8 +688,28 @@
     pending_credentials_.submit_element = observed_form_.submit_element;
     password_store->UpdateLoginWithPrimaryKey(pending_credentials_,
                                               old_primary_key);
+    password_was_updated = true;
   } else {
     password_store->UpdateLogin(pending_credentials_);
+    password_was_updated = true;
+  }
+  // If this was password update then update all non-best matches entries with
+  // the same username and the same old password.
+  if (password_was_updated) {
+    PasswordFormMap::const_iterator updated_password_it =
+        best_matches_.find(pending_credentials_.username_value);
+    DCHECK(best_matches_.end() != updated_password_it);
+    const base::string16& old_password =
+        updated_password_it->second->password_value;
+    for (size_t i = 0; i < not_best_matches_.size(); ++i) {
+      if (not_best_matches_[i]->username_value ==
+              pending_credentials_.username_value &&
+          not_best_matches_[i]->password_value == old_password) {
+        not_best_matches_[i]->password_value =
+            pending_credentials_.password_value;
+        password_store->UpdateLogin(*not_best_matches_[i]);
+      }
+    }
   }
 }
 
@@ -793,10 +812,11 @@
     pending_credentials_ = *it->second;
     password_overridden_ =
         pending_credentials_.password_value != password_to_save;
-    if (IsPendingCredentialsPublicSuffixMatch()) {
-      // If the autofilled credentials were only a PSL match, store a copy with
-      // the current origin and signon realm. This ensures that on the next
-      // visit, a precise match is found.
+    if (IsPendingCredentialsPublicSuffixMatch() ||
+        IsValidAndroidFacetURI(preferred_match_->signon_realm)) {
+      // If the autofilled credentials were a PSL match or credentials stored
+      // from Android apps store a copy with the current origin and signon
+      // realm. This ensures that on the next visit, a precise match is found.
       is_new_login_ = true;
       user_action_ = password_overridden_ ? kUserActionOverridePassword
                                           : kUserActionChoosePslMatch;
@@ -816,6 +836,11 @@
       // passwords. This is a much larger change.
       UpdateMetadataForUsage(pending_credentials_);
 
+      // Update |pending_credentials_| in order to be able correctly save it.
+      pending_credentials_.origin = provisionally_saved_form_->origin;
+      pending_credentials_.signon_realm =
+          provisionally_saved_form_->signon_realm;
+
       // Normally, the copy of the PSL matched credentials, adapted for the
       // current domain, is saved automatically without asking the user, because
       // the copy likely represents the same account, i.e., the one for which
@@ -825,9 +850,9 @@
       // that the autofilled credentials and |provisionally_saved_form_|
       // actually correspond  to two different accounts (see
       // http://crbug.com/385619). In that case the user should be asked again
-      // before saving the password. This is ensured by clearing
-      // |original_signon_realm| on |pending_credentials_|, which unmarks it as
-      // a PSL match.
+      // before saving the password. This is ensured by setting
+      // |password_overriden_| on |pending_credentials_| to false and setting
+      // |origin| and |signon_realm| to correct values.
       //
       // There is still the edge case when the autofilled credentials represent
       // the same account as |provisionally_saved_form_| but the stored password
@@ -839,8 +864,8 @@
       // user by asking them is not significant, so we are fine with asking
       // here again.
       if (password_overridden_) {
-        pending_credentials_.original_signon_realm.clear();
-        DCHECK(!IsPendingCredentialsPublicSuffixMatch());
+        pending_credentials_.is_public_suffix_match = false;
+        password_overridden_ = false;
       }
     } else {  // Not a PSL match.
       is_new_login_ = false;
@@ -896,6 +921,7 @@
   }
 
   pending_credentials_.action = provisionally_saved_form_->action;
+
   // If the user selected credentials we autofilled from a PasswordForm
   // that contained no action URL (IE6/7 imported passwords, for example),
   // bless it with the action URL from the observed form. See bug 1107719.
@@ -943,7 +969,7 @@
       std::min(form_path_segments_.size(), kSegmentCountCap);
 
   uint32_t score = 0u;
-  if (!candidate.IsPublicSuffixMatch()) {
+  if (!candidate.is_public_suffix_match) {
     score += 1u << 7;
   }
   if (candidate.origin == observed_form_.origin) {
@@ -986,7 +1012,7 @@
     const autofill::PasswordForm& blacklisted_form) const {
   DCHECK(blacklisted_form.blacklisted_by_user);
 
-  if (blacklisted_form.IsPublicSuffixMatch())
+  if (blacklisted_form.is_public_suffix_match)
     return false;
   if (blacklisted_form.origin.GetOrigin() != observed_form_.origin.GetOrigin())
     return false;
@@ -1014,7 +1040,7 @@
   }
   for (auto iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
     PasswordForm* form = iter->second;
-    if (!form->IsPublicSuffixMatch() && form->username_value.empty() &&
+    if (!form->is_public_suffix_match && form->username_value.empty() &&
         form->password_value == pending_credentials_.password_value)
       password_store->RemoveLogin(*form);
   }
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 745f0566..1740d89 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -383,6 +383,10 @@
   // frequently require lookups by username value in IsNewLogin.
   autofill::PasswordFormMap best_matches_;
 
+  // Set of forms from PasswordStore that correspond to the current site and
+  // that are not in |best_matches_|.
+  ScopedVector<autofill::PasswordForm> not_best_matches_;
+
   // Set of blacklisted forms from the PasswordStore that best match the current
   // form.
   ScopedVector<autofill::PasswordForm> blacklisted_matches_;
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 474abf5..2584b1b3 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -184,7 +184,12 @@
 
   // Types of possible outcomes of simulated matching, see
   // SimulateMatchingPhase.
-  enum ResultOfSimulatedMatching { RESULT_MATCH_FOUND, RESULT_NO_MATCH };
+  enum ResultOfSimulatedMatching {
+    RESULT_NO_MATCH,
+    RESULT_SAVED_MATCH = 1 << 0,  // Include saved_match_ in store results.
+    RESULT_PSL_MATCH = 1 << 1,    // Include psl_saved_match_ in store results.
+  };
+  typedef int ResultOfSimulatedMatchingMask;
 
   void SetUp() override {
     observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
@@ -203,6 +208,13 @@
     saved_match_.other_possible_usernames.push_back(
         ASCIIToUTF16("test2@gmail.com"));
 
+    psl_saved_match_ = saved_match_;
+    psl_saved_match_.is_public_suffix_match = true;
+    psl_saved_match_.origin =
+        GURL("http://m.accounts.google.com/a/ServiceLoginAuth");
+    psl_saved_match_.action = GURL("http://m.accounts.google.com/a/Login");
+    psl_saved_match_.signon_realm = "http://m.accounts.google.com";
+
     autofill::FormFieldData field;
     field.label = ASCIIToUTF16("full_name");
     field.name = ASCIIToUTF16("full_name");
@@ -235,7 +247,7 @@
   MockPasswordStore* mock_store() const { return mock_store_.get(); }
 
   void SimulateMatchingPhase(PasswordFormManager* p,
-                             ResultOfSimulatedMatching result) {
+                             ResultOfSimulatedMatchingMask result) {
     const PasswordStore::AuthorizationPromptPolicy auth_policy =
         PasswordStore::DISALLOW_PROMPT;
     EXPECT_CALL(*mock_store(), GetLogins(p->observed_form(), auth_policy, p));
@@ -245,9 +257,13 @@
       return;
     }
 
-    scoped_ptr<PasswordForm> match(new PasswordForm(saved_match_));
     ScopedVector<PasswordForm> result_form;
-    result_form.push_back(match.Pass());
+    if (result & RESULT_SAVED_MATCH) {
+      result_form.push_back(new PasswordForm(saved_match_));
+    }
+    if (result & RESULT_PSL_MATCH) {
+      result_form.push_back(new PasswordForm(psl_saved_match_));
+    }
     p->OnGetPasswordStoreResults(result_form.Pass());
   }
 
@@ -311,6 +327,7 @@
 
   PasswordForm* observed_form() { return &observed_form_; }
   PasswordForm* saved_match() { return &saved_match_; }
+  PasswordForm* psl_saved_match() { return &psl_saved_match_; }
   PasswordForm* CreateSavedMatch(bool blacklisted) {
     // Owned by the caller of this method.
     PasswordForm* match = new PasswordForm(saved_match_);
@@ -333,6 +350,7 @@
 
   PasswordForm observed_form_;
   PasswordForm saved_match_;
+  PasswordForm psl_saved_match_;
   scoped_refptr<NiceMock<MockPasswordStore>> mock_store_;
   scoped_ptr<TestPasswordManagerClient> client_;
   scoped_ptr<PasswordManager> password_manager_;
@@ -375,7 +393,7 @@
   // Now, suppose the user re-visits the site and wants to save an additional
   // login for the site with a new username. In this case, the matching phase
   // will yield the previously saved login.
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   // Set up the new login.
   base::string16 new_user = ASCIIToUTF16("newuser");
   base::string16 new_pass = ASCIIToUTF16("newpass");
@@ -406,7 +424,7 @@
 TEST_F(PasswordFormManagerTest, TestBlacklist) {
   saved_match()->origin = observed_form()->origin;
   saved_match()->action = observed_form()->action;
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   // Set up the new login.
   PasswordForm credentials = *observed_form();
   credentials.username_value = ASCIIToUTF16("newuser");
@@ -442,7 +460,8 @@
 
   // Doesn't match because of PSL.
   PasswordForm blacklisted_psl = *observed_form();
-  blacklisted_psl.original_signon_realm = "http://m.accounts.google.com";
+  blacklisted_psl.signon_realm = "http://m.accounts.google.com";
+  blacklisted_psl.is_public_suffix_match = true;
   blacklisted_psl.blacklisted_by_user = true;
 
   // Doesn't match because of different origin.
@@ -508,8 +527,7 @@
 TEST_F(PasswordFormManagerTest,
        OverriddenPSLMatchedCredentialsNotMarkedAsPSLMatched) {
   // The suggestion needs to be PSL-matched.
-  saved_match()->original_signon_realm = "www.example.org";
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_PSL_MATCH);
 
   // User modifies the suggested password and submits the form.
   PasswordForm credentials(*observed_form());
@@ -525,8 +543,8 @@
 
 TEST_F(PasswordFormManagerTest, PSLMatchedCredentialsMetadataUpdated) {
   // The suggestion needs to be PSL-matched.
-  saved_match()->original_signon_realm = "www.example.org";
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  saved_match()->is_public_suffix_match = true;
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 
   PasswordForm submitted_form(*observed_form());
   submitted_form.preferred = true;
@@ -539,9 +557,8 @@
   expected_saved_form.times_used = 1;
   expected_saved_form.other_possible_usernames.clear();
   expected_saved_form.form_data = saved_match()->form_data;
-  expected_saved_form.origin = saved_match()->origin;
-  expected_saved_form.original_signon_realm =
-      saved_match()->original_signon_realm;
+  expected_saved_form.origin = observed_form()->origin;
+  expected_saved_form.is_public_suffix_match = true;
   PasswordForm actual_saved_form;
 
   EXPECT_CALL(*(client()->mock_driver()->mock_autofill_manager()),
@@ -597,7 +614,7 @@
 }
 
 TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 
   // User submits credentials for the observed form using a username previously
   // stored, but a new password. Note that the observed form may have different
@@ -644,7 +661,7 @@
 
   PasswordFormManager form_manager(password_manager(), client(),
                                    client()->driver(), *observed_form(), false);
-  SimulateMatchingPhase(&form_manager, RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH);
 
   // User submits current and new credentials to the observed form.
   PasswordForm credentials(*observed_form());
@@ -751,7 +768,7 @@
 
 TEST_F(PasswordFormManagerTest, TestEmptyAction) {
   saved_match()->action = GURL();
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   // User logs in with the autofilled username / password from saved_match.
   PasswordForm login = *observed_form();
   login.username_value = saved_match()->username_value;
@@ -766,7 +783,7 @@
 }
 
 TEST_F(PasswordFormManagerTest, TestUpdateAction) {
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   // User logs in with the autofilled username / password from saved_match.
   PasswordForm login = *observed_form();
   login.username_value = saved_match()->username_value;
@@ -957,10 +974,10 @@
   ScopedVector<PasswordForm> simulated_results;
   simulated_results.push_back(CreateSavedMatch(false));
   simulated_results.push_back(CreateSavedMatch(false));
-  simulated_results[1]->username_value = ASCIIToUTF16("other@gmail.com");
-  simulated_results[1]->password_element = ASCIIToUTF16("signup_password");
-  simulated_results[1]->username_element = ASCIIToUTF16("signup_username");
-  simulated_results[1]->type = PasswordForm::TYPE_GENERATED;
+  simulated_results[0]->username_value = ASCIIToUTF16("other@gmail.com");
+  simulated_results[0]->password_element = ASCIIToUTF16("signup_password");
+  simulated_results[0]->username_element = ASCIIToUTF16("signup_username");
+  simulated_results[0]->type = PasswordForm::TYPE_GENERATED;
   form_manager()->SimulateFetchMatchingLoginsFromPasswordStore();
 
   autofill::PasswordFormFillData fill_data;
@@ -1108,7 +1125,7 @@
   ScopedVector<PasswordForm> simulated_results;
   simulated_results.push_back(CreateSavedMatch(false));
   simulated_results.push_back(CreateSavedMatch(false));
-  simulated_results[0]->original_signon_realm = "http://accounts2.google.com";
+  simulated_results[0]->is_public_suffix_match = true;
   simulated_results[1]->origin =
       GURL("http://accounts.google.com/a/ServiceLoginAuth2");
   simulated_results[1]->action =
@@ -1122,10 +1139,8 @@
   form_manager()->OnGetPasswordStoreResults(simulated_results.Pass());
   EXPECT_TRUE(fill_data.additional_logins.empty());
   EXPECT_EQ(1u, form_manager()->best_matches().size());
-  EXPECT_TRUE(form_manager()
-                  ->best_matches()
-                  .begin()
-                  ->second->original_signon_realm.empty());
+  EXPECT_TRUE(
+      !form_manager()->best_matches().begin()->second->is_public_suffix_match);
 }
 
 TEST_F(PasswordFormManagerTest, AndroidCredentialsAreAutofilled) {
@@ -1136,9 +1151,7 @@
   // filled on username-select.
   ScopedVector<PasswordForm> simulated_results;
   simulated_results.push_back(new PasswordForm());
-  simulated_results[0]->signon_realm = observed_form()->signon_realm;
-  simulated_results[0]->original_signon_realm =
-      "android://hash@com.google.android";
+  simulated_results[0]->signon_realm = "android://hash@com.google.android";
   simulated_results[0]->origin = observed_form()->origin;
   simulated_results[0]->username_value = saved_match()->username_value;
   simulated_results[0]->password_value = saved_match()->password_value;
@@ -1282,9 +1295,9 @@
   form_manager()->SimulateFetchMatchingLoginsFromPasswordStore();
   form_manager()->OnGetPasswordStoreResults(result.Pass());
 
-  // We always take the last credential with a particular username, regardless
+  // We always take the first credential with a particular username, regardless
   // of which ones are labeled preferred.
-  EXPECT_EQ(ASCIIToUTF16("second"),
+  EXPECT_EQ(ASCIIToUTF16("first"),
             form_manager()->preferred_match()->password_value);
 
   PasswordForm login(*observed_form());
@@ -1476,7 +1489,7 @@
 
   PasswordFormManager form_manager(password_manager(), client(),
                                    client()->driver(), *observed_form(), false);
-  SimulateMatchingPhase(&form_manager, RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH);
 
   // The user submits a password on a change-password form, which does not use
   // the "autocomplete=username" mark-up (therefore Chrome had to guess what is
@@ -1493,7 +1506,7 @@
 
 TEST_F(PasswordFormManagerTest,
        IsIngnorableChangePasswordForm_NotMatchingPassword) {
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 
   // The user submits a password on a change-password form, which does not use
   // the "autocomplete=username" mark-up (therefore Chrome had to guess what is
@@ -1510,7 +1523,7 @@
 
 TEST_F(PasswordFormManagerTest,
        IsIngnorableChangePasswordForm_NotMatchingUsername) {
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 
   // The user submits a password on a change-password form, which does not use
   // the "autocomplete=username" mark-up (therefore Chrome had to guess what is
@@ -1606,7 +1619,7 @@
   PasswordFormManager form_manager(password_manager(), client(),
                                    client()->driver(), *observed_form(), false);
 
-  SimulateMatchingPhase(&form_manager, RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH);
   // User submits current and new credentials to the observed form.
   PasswordForm credentials(*observed_form());
   credentials.username_element.clear();
@@ -1664,7 +1677,7 @@
   PasswordFormManager form_manager(password_manager(), client(),
                                    client()->driver(), *observed_form(), false);
 
-  SimulateMatchingPhase(&form_manager, RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH);
   // User submits current and new credentials to the observed form.
   PasswordForm credentials(*observed_form());
   // The |username_value| contains a text that's unlikely to be real username.
@@ -1825,7 +1838,7 @@
 TEST_F(PasswordFormManagerTest, NotRemovePSLNoUsernameAccounts) {
   PasswordForm saved_form = *saved_match();
   saved_form.username_value.clear();
-  saved_form.original_signon_realm = "www.example.org";
+  saved_form.is_public_suffix_match = true;
   ScopedVector<PasswordForm> result;
   result.push_back(new PasswordForm(saved_form));
   form_manager()->SimulateFetchMatchingLoginsFromPasswordStore();
@@ -2032,12 +2045,12 @@
 
 TEST_F(PasswordFormManagerTest, ProcessFrame) {
   EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 }
 
 TEST_F(PasswordFormManagerTest, ProcessFrame_MoreProcessFrameMoreFill) {
   EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   form_manager()->ProcessFrame(client()->mock_driver()->AsWeakPtr());
 }
 
@@ -2046,7 +2059,7 @@
 
   EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
   EXPECT_CALL(second_driver, FillPasswordForm(_));
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
   form_manager()->ProcessFrame(second_driver.AsWeakPtr());
 }
 
@@ -2073,8 +2086,8 @@
 
 TEST_F(PasswordFormManagerTest, ProcessFrame_StoreUpdatesCausesAutofill) {
   EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
-  SimulateMatchingPhase(form_manager(), RESULT_MATCH_FOUND);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
+  SimulateMatchingPhase(form_manager(), RESULT_SAVED_MATCH);
 }
 
 TEST_F(PasswordFormManagerTest, UpdateFormManagers_IsCalled) {
@@ -2103,4 +2116,154 @@
   form_manager()->Save();
 }
 
+TEST_F(PasswordFormManagerTest, TestUpdatePSLMatchedCredentials) {
+  PasswordFormManager form_manager(password_manager(), client(),
+                                   client()->driver(), *observed_form(), false);
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH | RESULT_PSL_MATCH);
+
+  // User submits a credentials with an old username and a new password.
+  PasswordForm credentials(*observed_form());
+  credentials.username_value = saved_match()->username_value;
+  credentials.password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager.ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  // Successful login. The PasswordManager would instruct PasswordFormManager
+  // to save, and since this is an update, it should know not to save as a new
+  // login.
+  EXPECT_FALSE(form_manager.IsNewLogin());
+
+  // Trigger saving to exercise some special case handling in UpdateLogin().
+  PasswordForm new_credentials[2];
+  EXPECT_CALL(*mock_store(), UpdateLogin(_))
+      .WillOnce(testing::SaveArg<0>(&new_credentials[0]))
+      .WillOnce(testing::SaveArg<0>(&new_credentials[1]));
+
+  form_manager.Save();
+  Mock::VerifyAndClearExpectations(mock_store());
+
+  // No meta-information should be updated, only the password.
+  EXPECT_EQ(credentials.password_value, new_credentials[0].password_value);
+  EXPECT_EQ(saved_match()->username_value, new_credentials[0].username_value);
+  EXPECT_EQ(saved_match()->username_element,
+            new_credentials[0].username_element);
+  EXPECT_EQ(saved_match()->password_element,
+            new_credentials[0].password_element);
+  EXPECT_EQ(saved_match()->origin, new_credentials[0].origin);
+
+  EXPECT_EQ(credentials.password_value, new_credentials[1].password_value);
+  EXPECT_EQ(psl_saved_match()->username_element,
+            new_credentials[1].username_element);
+  EXPECT_EQ(psl_saved_match()->username_element,
+            new_credentials[1].username_element);
+  EXPECT_EQ(psl_saved_match()->password_element,
+            new_credentials[1].password_element);
+  EXPECT_EQ(psl_saved_match()->origin, new_credentials[1].origin);
+}
+
+TEST_F(PasswordFormManagerTest,
+       TestNotUpdatePSLMatchedCredentialsWithAnotherUsername) {
+  PasswordFormManager form_manager(password_manager(), client(),
+                                   client()->driver(), *observed_form(), false);
+  psl_saved_match()->username_value += ASCIIToUTF16("1");
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH | RESULT_PSL_MATCH);
+
+  // User submits a credentials with an old username and a new password.
+  PasswordForm credentials(*observed_form());
+  credentials.username_value = saved_match()->username_value;
+  credentials.password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager.ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  // Successful login. The PasswordManager would instruct PasswordFormManager
+  // to save, and since this is an update, it should know not to save as a new
+  // login.
+  EXPECT_FALSE(form_manager.IsNewLogin());
+
+  // Trigger saving to exercise some special case handling in UpdateLogin().
+  PasswordForm new_credentials;
+  EXPECT_CALL(*mock_store(), UpdateLogin(_))
+      .WillOnce(testing::SaveArg<0>(&new_credentials));
+
+  form_manager.Save();
+  Mock::VerifyAndClearExpectations(mock_store());
+
+  // No meta-information should be updated, only the password.
+  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
+  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
+  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
+  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
+  EXPECT_EQ(saved_match()->origin, new_credentials.origin);
+}
+
+TEST_F(PasswordFormManagerTest,
+       TestNotUpdatePSLMatchedCredentialsWithAnotherPassword) {
+  PasswordFormManager form_manager(password_manager(), client(),
+                                   client()->driver(), *observed_form(), false);
+  psl_saved_match()->password_value += ASCIIToUTF16("1");
+  SimulateMatchingPhase(&form_manager, RESULT_SAVED_MATCH | RESULT_PSL_MATCH);
+
+  // User submits a credentials with an old username and a new password.
+  PasswordForm credentials(*observed_form());
+  credentials.username_value = saved_match()->username_value;
+  credentials.password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager.ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  // Successful login. The PasswordManager would instruct PasswordFormManager
+  // to save, and since this is an update, it should know not to save as a new
+  // login.
+  EXPECT_FALSE(form_manager.IsNewLogin());
+
+  // Trigger saving to exercise some special case handling in UpdateLogin().
+  PasswordForm new_credentials;
+  EXPECT_CALL(*mock_store(), UpdateLogin(_))
+      .WillOnce(testing::SaveArg<0>(&new_credentials));
+
+  form_manager.Save();
+  Mock::VerifyAndClearExpectations(mock_store());
+
+  // No meta-information should be updated, only the password.
+  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
+  EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
+  EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
+  EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
+  EXPECT_EQ(saved_match()->origin, new_credentials.origin);
+}
+
+TEST_F(PasswordFormManagerTest, TestNotUpdateWhenOnlyPSLMatched) {
+  PasswordFormManager form_manager(password_manager(), client(),
+                                   client()->driver(), *observed_form(), false);
+  SimulateMatchingPhase(&form_manager, RESULT_PSL_MATCH);
+
+  // User submits a credentials with an old username and a new password.
+  PasswordForm credentials(*observed_form());
+  credentials.username_value = saved_match()->username_value;
+  credentials.password_value = ASCIIToUTF16("new_password");
+  credentials.preferred = true;
+  form_manager.ProvisionallySave(
+      credentials, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  EXPECT_TRUE(form_manager.IsNewLogin());
+
+  // PSL matched credential should not be updated, since we are not sure that
+  // this is the same credential as submitted one.
+  PasswordForm new_credentials;
+  EXPECT_CALL(*mock_store(), UpdateLogin(_)).Times(0);
+  EXPECT_CALL(*mock_store(), AddLogin(_))
+      .WillOnce(testing::SaveArg<0>(&new_credentials));
+
+  form_manager.Save();
+  Mock::VerifyAndClearExpectations(mock_store());
+
+  EXPECT_EQ(credentials.password_value, new_credentials.password_value);
+  EXPECT_EQ(credentials.username_value, new_credentials.username_value);
+  EXPECT_EQ(credentials.password_element, new_credentials.password_element);
+  EXPECT_EQ(credentials.username_element, new_credentials.username_element);
+  EXPECT_EQ(credentials.origin, new_credentials.origin);
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index 6a1e311..001c97c 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -383,8 +383,7 @@
     android_form.scheme = PasswordForm::SCHEME_HTML;
     android_form.signon_realm = realm;
     ScopedVector<PasswordForm> more_results(
-        AffiliatedMatchHelper::TransformAffiliatedAndroidCredentials(
-            form, FillMatchingLogins(android_form, DISALLOW_PROMPT)));
+        FillMatchingLogins(android_form, DISALLOW_PROMPT));
     results.insert(results.end(), more_results.begin(), more_results.end());
     more_results.weak_clear();
   }
@@ -408,7 +407,7 @@
       FillMatchingLogins(primary_key, DISALLOW_PROMPT));
   for (PasswordForm*& candidate : candidates) {
     if (ArePasswordFormUniqueKeyEqual(*candidate, primary_key) &&
-        !candidate->IsPublicSuffixMatch()) {
+        !candidate->is_public_suffix_match) {
       scoped_ptr<PasswordForm> result(candidate);
       candidate = nullptr;
       return result.Pass();
@@ -452,7 +451,7 @@
       // non-HTML login forms; PSL matches; logins with a different username;
       // and logins with the same password (to avoid generating no-op updates).
       if (!AffiliatedMatchHelper::IsValidWebCredential(*web_login) ||
-          web_login->IsPublicSuffixMatch() ||
+          web_login->is_public_suffix_match ||
           web_login->username_value != updated_android_form.username_value ||
           web_login->password_value == updated_android_form.password_value)
         continue;
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index 3dc5f13..ba7c217 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -450,11 +450,8 @@
   expected_results.push_back(new PasswordForm(*all_credentials[0]));
   expected_results.push_back(new PasswordForm(*all_credentials[1]));
   for (PasswordForm* result : expected_results) {
-    if (result->signon_realm == observed_form.signon_realm)
-      continue;
-    result->original_signon_realm = result->signon_realm;
-    result->origin = observed_form.origin;
-    result->signon_realm = observed_form.signon_realm;
+    if (result->signon_realm != observed_form.signon_realm)
+      result->is_public_suffix_match = true;
   }
 
   std::vector<std::string> no_affiliated_android_realms;
@@ -516,7 +513,8 @@
        kTestUnrelatedAndroidRealm,
        "", "", L"", L"", L"",
        L"username_value_5",
-       L"", true, true, 1}};
+       L"", true, true, 1}
+       };
   /* clang-format on */
 
   scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
@@ -549,11 +547,9 @@
   expected_results.push_back(new PasswordForm(*all_credentials[3]));
   expected_results.push_back(new PasswordForm(*all_credentials[4]));
   for (PasswordForm* result : expected_results) {
-    if (result->signon_realm == observed_form.signon_realm)
-      continue;
-    result->original_signon_realm = result->signon_realm;
-    result->signon_realm = observed_form.signon_realm;
-    result->origin = observed_form.origin;
+    if (result->signon_realm != observed_form.signon_realm &&
+        !IsValidAndroidFacetURI(result->signon_realm))
+      result->is_public_suffix_match = true;
   }
 
   std::vector<std::string> affiliated_android_realms;
diff --git a/components/pdf_viewer/BUILD.gn b/components/pdf_viewer/BUILD.gn
index 2b4dfb8f..06ceabc 100644
--- a/components/pdf_viewer/BUILD.gn
+++ b/components/pdf_viewer/BUILD.gn
@@ -36,7 +36,6 @@
 
   data_deps = [
     "//components/clipboard",
-    "//components/mus",
     "//components/resource_provider",
     "//mojo/services/network:network",
   ]
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc
index 339f583..40c4a5a 100644
--- a/components/plugins/renderer/loadable_plugin_placeholder.cc
+++ b/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -286,17 +286,7 @@
     blink::WebSerializedScriptValue message_data =
         blink::WebSerializedScriptValue::serialize(converter->ToV8Value(
             &value, element.document().frame()->mainWorldScriptContext()));
-
-    blink::WebDOMEvent event = element.document().createEvent("MessageEvent");
-    blink::WebDOMMessageEvent msg_event = event.to<blink::WebDOMMessageEvent>();
-    msg_event.initMessageEvent("message",           // type
-                               false,               // canBubble
-                               false,               // cancelable
-                               message_data,        // data
-                               "",                  // origin [*]
-                               NULL,                // source [*]
-                               element.document(),  // target document
-                               "");                 // lastEventId
+    blink::WebDOMMessageEvent msg_event(message_data);
     element.dispatchEvent(msg_event);
   }
 }
diff --git a/components/policy/core/common/policy_loader_win.cc b/components/policy/core/common/policy_loader_win.cc
index 279a936..0ed6714 100644
--- a/components/policy/core/common/policy_loader_win.cc
+++ b/components/policy/core/common/policy_loader_win.cc
@@ -674,14 +674,14 @@
   DCHECK(is_initialized_);
   if (!user_policy_watcher_failed_ &&
       !user_policy_watcher_.GetWatchedObject() &&
-      !user_policy_watcher_.StartWatching(
+      !user_policy_watcher_.StartWatchingOnce(
           user_policy_changed_event_.handle(), this)) {
     DLOG(WARNING) << "Failed to start watch for user policy change event";
     user_policy_watcher_failed_ = true;
   }
   if (!machine_policy_watcher_failed_ &&
       !machine_policy_watcher_.GetWatchedObject() &&
-      !machine_policy_watcher_.StartWatching(
+      !machine_policy_watcher_.StartWatchingOnce(
           machine_policy_changed_event_.handle(), this)) {
     DLOG(WARNING) << "Failed to start watch for machine policy change event";
     machine_policy_watcher_failed_ = true;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 6b9d615..273f7a8 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -4113,17 +4113,17 @@
       'name': 'DisableSSLRecordSplitting',
       'type': 'main',
       'schema': { 'type': 'boolean' },
-      'supported_on': ['chrome.*:18-', 'chrome_os:18-'],
+      'supported_on': ['chrome.*:18-46', 'chrome_os:18-46'],
       'features': {
         'dynamic_refresh': True,
         'per_profile': False,
       },
       'example_value': True,
       'id': 118,
-      'caption': '''Disable SSL record splitting''',
-      'desc': '''Specifies whether SSL record splitting should be disabled. Record splitting is a workaround for a weakness in SSL 3.0 and TLS 1.0 but can cause compatibility issues with some HTTPS servers and proxies.
+      'caption': '''Disable TLS False Start''',
+      'desc': '''Specifies whether the TLS False Start optimization should be disabled. For historical reasons, this policy is named DisableSSLRecordSplitting.
 
-      If the policy is not set, or is set to false, then record splitting will be used on SSL/TLS connections which use CBC ciphersuites.''',
+      If the policy is not set, or is set to false, then TLS False Start will be enabled. If it is set to true, TLS False Start will be disabled.''',
     },
     {
       'name': 'EnableOnlineRevocationChecks',
@@ -6950,7 +6950,14 @@
       'caption': '''Managed Bookmarks''',
       'desc': '''Configures a list of managed bookmarks.
 
-      The policy is a list of bookmarks, and each bookmark is a dictionary containing the bookmark "name" and the target "url". A bookmark can also be configured as a folder. In that case, define the folder "name" but don't define an "url"; instead, define the folder contents as another list of bookmarks under the "children" key. Chrome will amend incomplete URLs as if they were submitted via the Omnibox. For example, "google.com" becomes "https://google.com/".
+      The policy consists of a list of bookmarks whereas each bookmark is a
+      dictionary containing the keys "name" and "url" which hold the bookmark's
+      name and its target. A subfolder may be configured by defining a bookmark
+      without an "url" key but with an additional "children" key which itself
+      contains a list of bookmarks as defined above (some of which may be
+      folders again). <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>
+      amends incomplete URLs as if they were submitted via the Omnibox, for
+      example "google.com" becomes "https://google.com/".
 
       These bookmarks are placed in a Managed bookmarks folder that can't be modified by the user, but the user can choose to hide it from the bookmark bar. Managed bookmarks are not synced to the user account and can't be modified by extensions.''',
     },
@@ -7448,10 +7455,10 @@
       },
       'example_value': {
         'extension1': {
-          'allowCorporateKeyUsage': 'true'
+          'allowCorporateKeyUsage': True
         },
         'extension2': {
-          'allowCorporateKeyUsage': 'false'
+          'allowCorporateKeyUsage': False
         }
       },
       'id': 302,
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi
index 9b66331..0c3fcd6 100644
--- a/components/proximity_auth.gypi
+++ b/components/proximity_auth.gypi
@@ -67,6 +67,10 @@
         "proximity_auth/metrics.cc",
         "proximity_auth/metrics.h",
         "proximity_auth/proximity_auth_client.h",
+        "proximity_auth/proximity_auth_pref_manager.cc",
+        "proximity_auth/proximity_auth_pref_manager.h",
+        "proximity_auth/proximity_auth_pref_names.cc",
+        "proximity_auth/proximity_auth_pref_names.h",
         "proximity_auth/proximity_auth_system.cc",
         "proximity_auth/proximity_auth_system.h",
         "proximity_auth/proximity_monitor.h",
diff --git a/components/proximity_auth/BUILD.gn b/components/proximity_auth/BUILD.gn
index 13b68e0..74c766f 100644
--- a/components/proximity_auth/BUILD.gn
+++ b/components/proximity_auth/BUILD.gn
@@ -36,6 +36,10 @@
     "metrics.cc",
     "metrics.h",
     "proximity_auth_client.h",
+    "proximity_auth_pref_manager.cc",
+    "proximity_auth_pref_manager.h",
+    "proximity_auth_pref_names.cc",
+    "proximity_auth_pref_names.h",
     "proximity_auth_system.cc",
     "proximity_auth_system.h",
     "proximity_monitor.h",
@@ -106,6 +110,7 @@
     "device_to_device_operations_unittest.cc",
     "device_to_device_secure_context_unittest.cc",
     "messenger_impl_unittest.cc",
+    "proximity_auth_pref_manager_unittest.cc",
     "proximity_auth_system_unittest.cc",
     "proximity_monitor_impl_unittest.cc",
     "remote_device_life_cycle_impl_unittest.cc",
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection.cc
index e1e62099..52af29b 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection.cc
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection.cc
@@ -48,12 +48,6 @@
 // write request. This is not the connection MTU, we are assuming that the
 // remote device allows for writes larger than MTU.
 const int kMaxChunkSize = 500;
-
-// This delay is necessary as a workaroud for crbug.com/507325. Reading/writing
-// characteristics immediatelly after the connection is complete fails with
-// GATT_ERROR_FAILED.
-const int kDelayAfterGattConnectionMilliseconds = 1000;
-
 }  // namespace
 
 BluetoothLowEnergyConnection::BluetoothLowEnergyConnection(
@@ -74,8 +68,6 @@
       write_remote_characteristic_pending_(false),
       max_number_of_write_attempts_(max_number_of_write_attempts),
       max_chunk_size_(kMaxChunkSize),
-      delay_after_gatt_connection_(base::TimeDelta::FromMilliseconds(
-          kDelayAfterGattConnectionMilliseconds)),
       weak_ptr_factory_(this) {
   DCHECK(adapter_);
   DCHECK(adapter_->IsInitialized());
@@ -227,12 +219,12 @@
                                                  BluetoothDevice* device) {
   DCHECK(device);
   if (sub_status() == SubStatus::DISCONNECTED ||
-      device->GetAddress() != GetRemoteDeviceAddress())
+      device->GetAddress() != GetDeviceAddress())
     return;
 
   if (sub_status() != SubStatus::WAITING_GATT_CONNECTION &&
       !device->IsConnected()) {
-    PA_LOG(INFO) << "GATT connection dropped " << GetRemoteDeviceAddress()
+    PA_LOG(INFO) << "GATT connection dropped " << GetDeviceAddress()
                  << "\ndevice connected: " << device->IsConnected()
                  << "\ngatt connection: "
                  << (gatt_connection_ ? gatt_connection_->IsConnected()
@@ -245,10 +237,10 @@
                                                  BluetoothDevice* device) {
   DCHECK(device);
   if (sub_status_ == SubStatus::DISCONNECTED ||
-      device->GetAddress() != GetRemoteDeviceAddress())
+      device->GetAddress() != GetDeviceAddress())
     return;
 
-  PA_LOG(INFO) << "Device removed " << GetRemoteDeviceAddress();
+  PA_LOG(INFO) << "Device removed " << GetDeviceAddress();
   Disconnect();
 }
 
@@ -349,6 +341,10 @@
   DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION);
   PA_LOG(INFO) << "GATT connection with " << gatt_connection->GetDeviceAddress()
                << " created.";
+  PrintTimeElapsed();
+
+  // Informing |bluetooth_trottler_| a new connection was established.
+  bluetooth_throttler_->OnConnection(this);
 
   gatt_connection_ = gatt_connection.Pass();
   SetSubStatus(SubStatus::WAITING_CHARACTERISTICS);
@@ -357,9 +353,6 @@
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&BluetoothLowEnergyConnection::OnCharacteristicsFinderError,
                  weak_ptr_factory_.GetWeakPtr())));
-
-  // Informing |bluetooth_trottler_| a new connection was established.
-  bluetooth_throttler_->OnConnection(this);
 }
 
 BluetoothLowEnergyCharacteristicsFinder*
@@ -377,6 +370,9 @@
     const RemoteAttribute& service,
     const RemoteAttribute& to_peripheral_char,
     const RemoteAttribute& from_peripheral_char) {
+  PA_LOG(INFO) << "Remote chacteristics found.";
+  PrintTimeElapsed();
+
   DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS);
   remote_service_ = service;
   to_peripheral_char_ = to_peripheral_char;
@@ -440,6 +436,7 @@
   DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION);
   PA_LOG(INFO) << "Notification session started "
                << notify_session->GetCharacteristicIdentifier();
+  PrintTimeElapsed();
 
   SetSubStatus(SubStatus::NOTIFY_SESSION_READY);
   notify_session_ = notify_session.Pass();
@@ -464,14 +461,7 @@
             static_cast<uint32>(ControlSignal::kInviteToConnectSignal)),
         std::vector<uint8>(), false);
 
-    // This is a workaround for crbug.com/498850. Currently, trying to
-    // write/read characteristics immediatelly after the GATT connection was
-    // established fails with GATT_ERROR_FAILED.
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&BluetoothLowEnergyConnection::WriteRemoteCharacteristic,
-                   weak_ptr_factory_.GetWeakPtr(), write_request),
-        delay_after_gatt_connection_);
+    WriteRemoteCharacteristic(write_request);
   }
 }
 
@@ -550,7 +540,11 @@
     write_requests_queue_.pop();
 }
 
-std::string BluetoothLowEnergyConnection::GetRemoteDeviceAddress() {
+void BluetoothLowEnergyConnection::PrintTimeElapsed() {
+  PA_LOG(INFO) << "Time elapsed: " << base::TimeTicks::Now() - start_time_;
+}
+
+std::string BluetoothLowEnergyConnection::GetDeviceAddress() {
   // When the remote device is connected we should rely on the address given by
   // |gatt_connection_|. As the device address may change if the device is
   // paired. The address in |gatt_connection_| is automatically updated in this
@@ -561,15 +555,15 @@
 
 BluetoothDevice* BluetoothLowEnergyConnection::GetRemoteDevice() {
   // It's not possible to simply use
-  // |adapter_->GetDevice(GetRemoteDeviceAddress())| to find the device with MAC
-  // address |GetRemoteDeviceAddress()|. For paired devices,
+  // |adapter_->GetDevice(GetDeviceAddress())| to find the device with MAC
+  // address |GetDeviceAddress()|. For paired devices,
   // BluetoothAdapter::GetDevice(XXX) searches for the temporary MAC address
-  // XXX, whereas |GetRemoteDeviceAddress()| is the real MAC address. This is a
+  // XXX, whereas |GetDeviceAddress()| is the real MAC address. This is a
   // bug in the way device::BluetoothAdapter is storing the devices (see
   // crbug.com/497841).
   std::vector<BluetoothDevice*> devices = adapter_->GetDevices();
   for (const auto& device : devices) {
-    if (device->GetAddress() == GetRemoteDeviceAddress())
+    if (device->GetAddress() == GetDeviceAddress())
       return device;
   }
 
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection.h b/components/proximity_auth/ble/bluetooth_low_energy_connection.h
index b45a21d..b316f641 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection.h
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection.h
@@ -96,6 +96,7 @@
   // proximity_auth::Connection:
   void Connect() override;
   void Disconnect() override;
+  std::string GetDeviceAddress() override;
 
  protected:
   // Exposed for testing.
@@ -221,8 +222,8 @@
   // Clears |write_requests_queue_|.
   void ClearWriteRequestsQueue();
 
-  // Returns the Bluetooth address of the remote device.
-  std::string GetRemoteDeviceAddress();
+  // Prints the time elapsed since |Connect()| was called.
+  void PrintTimeElapsed();
 
   // Returns the device corresponding to |remote_device_address_|.
   device::BluetoothDevice* GetRemoteDevice();
@@ -301,12 +302,6 @@
   // Stores when the instace was created.
   base::TimeTicks start_time_;
 
-  // Delay imposed after a GATT connection is created and before any read/write
-  // request is sent to the characteristics. This delay is necessary as a
-  // workaroud for crbug.com/507325. Reading/writing characteristics
-  // immediatelly after the connection is complete fails with GATT_ERROR_FAILED.
-  base::TimeDelta delay_after_gatt_connection_;
-
   base::WeakPtrFactory<BluetoothLowEnergyConnection> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyConnection);
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
index 5f8f860..bf50796 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
@@ -189,10 +189,21 @@
   adapter_ = adapter;
   adapter_->AddObserver(this);
 
-  // Note: it's not possible to connect with the paired directly, as the
-  // temporary MAC may not be resolved automatically (see crbug.com/495402). The
-  // Bluetooth adapter will fire |OnDeviceChanged| notifications for all
-  // Bluetooth Low Energy devices that are advertising.
+  // This is important for debugging. To eliminate the case where the device was
+  // removed (forgotten) by the user, or BlueZ didn't load the device correctly.
+  if (finder_strategy_ == FIND_PAIRED_DEVICE) {
+    PA_LOG(INFO) << "Looking for paired device: "
+                 << remote_device_.bluetooth_address;
+    for (auto& device : adapter_->GetDevices()) {
+      if (device->IsPaired())
+        PA_LOG(INFO) << device->GetAddress() << " is paired";
+    }
+  }
+
+  // Note: It's possible to connect to the paired directly, so when using
+  // FIND_PAIRED_DEVICE strategy this is not necessary. However, the discovery
+  // doesn't add a lot of latency, and the makes the code path for both
+  // strategies more similar.
   StartDiscoverySession();
 }
 
@@ -227,33 +238,10 @@
           weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStopped() {
-  PA_LOG(INFO) << "Discovery session stopped";
-  discovery_session_.reset();
-}
-
-void BluetoothLowEnergyConnectionFinder::OnStopDiscoverySessionError() {
-  PA_LOG(WARNING) << "Error stopping discovery session";
-}
-
 void BluetoothLowEnergyConnectionFinder::StopDiscoverySession() {
   PA_LOG(INFO) << "Stopping discovery session";
-
-  if (!adapter_) {
-    PA_LOG(WARNING) << "Adapter not initialized";
-    return;
-  }
-  if (!discovery_session_ || !discovery_session_->IsActive()) {
-    PA_LOG(INFO) << "No Active discovery session";
-    return;
-  }
-
-  discovery_session_->Stop(
-      base::Bind(&BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStopped,
-                 weak_ptr_factory_.GetWeakPtr()),
-      base::Bind(
-          &BluetoothLowEnergyConnectionFinder::OnStopDiscoverySessionError,
-          weak_ptr_factory_.GetWeakPtr()));
+  // Destroying the discovery session also stops it.
+  discovery_session_.reset();
 }
 
 scoped_ptr<Connection> BluetoothLowEnergyConnectionFinder::CreateConnection(
@@ -281,36 +269,27 @@
     // If we invoke the callback now, the callback function may install its own
     // observer to |connection_|. Because we are in the ConnectionObserver
     // callstack, this new observer will receive this connection event.
-    // Therefore, we need to invoke the callback asynchronously.
+    // Therefore, we need to invoke the callback or restart discovery
+    // asynchronously.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::Bind(&BluetoothLowEnergyConnectionFinder::InvokeCallbackAsync,
                    weak_ptr_factory_.GetWeakPtr()));
   } else if (old_status == Connection::IN_PROGRESS) {
     PA_LOG(WARNING) << "Connection failed. Retrying.";
-    RestartDiscoverySessionWhenReady();
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionAsync,
+            weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
-void BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionWhenReady() {
-  PA_LOG(INFO) << "Trying to restart discovery.";
-
-  // To restart scanning for devices, it's necessary to ensure that:
-  // (i) the GATT connection to |remove_device_| is closed;
-  // (ii) there is no pending call to
-  // |device::BluetoothDiscoverySession::Stop()|.
-  // The second condition is satisfied when |OnDiscoveryStopped| is called and
-  // |discovery_session_| is reset.
-  if (!discovery_session_) {
-    PA_LOG(INFO) << "Ready to start discovery.";
-    connection_.reset();
+void BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionAsync() {
+  PA_LOG(INFO) << "Restarting discovery session.";
+  connection_.reset();
+  if (!discovery_session_ || !discovery_session_->IsActive())
     StartDiscoverySession();
-  } else {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&BluetoothLowEnergyConnectionFinder::
-                                  RestartDiscoverySessionWhenReady,
-                              weak_ptr_factory_.GetWeakPtr()));
-  }
 }
 
 BluetoothDevice* BluetoothLowEnergyConnectionFinder::GetDevice(
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h
index 91ee6ec9..0b33310 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h
@@ -102,12 +102,6 @@
   // Starts a discovery session for |adapter_|.
   void StartDiscoverySession();
 
-  // Callback called when |discovery_session_| is stopped.
-  void OnDiscoverySessionStopped();
-
-  // Callback called when there is an error stopping |discovery_session_|.
-  void OnStopDiscoverySessionError();
-
   // Stops the discovery session given by |discovery_session_|.
   void StopDiscoverySession();
 
@@ -119,7 +113,7 @@
   bool HasService(device::BluetoothDevice* device);
 
   // Restarts the discovery session after creating |connection_| fails.
-  void RestartDiscoverySessionWhenReady();
+  void RestartDiscoverySessionAsync();
 
   // Used to invoke |connection_callback_| asynchronously, decoupling the
   // callback invocation from the ConnectionObserver callstack.
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc
index c2af8047..16d9338 100644
--- a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder_unittest.cc
@@ -153,8 +153,7 @@
     discovery_callback.Run(discovery_session.Pass());
   }
 
-  void ExpectStopDiscoveryAndRemoveObserver() {
-    EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
+  void ExpectRemoveObserver() {
     EXPECT_CALL(*adapter_, RemoveObserver(_)).Times(AtLeast(1));
   }
 
@@ -221,7 +220,6 @@
   EXPECT_CALL(*adapter_, AddObserver(_));
   connection_finder.Find(connection_callback_);
 
-  EXPECT_CALL(*discovery_session_alias, Stop(_, _));
   ASSERT_FALSE(discovery_callback.is_null());
   discovery_callback.Run(discovery_session.Pass());
 
@@ -235,7 +233,7 @@
       device_whitelist_.get(),
       BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   std::vector<device::BluetoothUUID> uuids;
   ON_CALL(*device_, GetUUIDs()).WillByDefault(Return(uuids));
@@ -253,7 +251,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
 
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kServiceUUID, kTestRemoteDeviceBluetoothAddress, false);
   ON_CALL(*device_, GetName())
@@ -269,7 +267,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
 
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kOtherUUID, kTestRemoteDeviceBluetoothAddress, false);
   ON_CALL(*device_, GetName())
@@ -285,7 +283,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
 
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kServiceUUID, kTestRemoteDeviceBluetoothAddress, true);
   connection_finder.ExpectCreateConnection();
@@ -297,7 +295,7 @@
   StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kOtherUUID, "", true);
   EXPECT_CALL(connection_finder, CreateConnectionProxy()).Times(0);
@@ -310,7 +308,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
 
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kServiceUUID, kTestRemoteDeviceBluetoothAddress, true);
   connection_finder.ExpectCreateConnection();
@@ -323,7 +321,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
 
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   PrepareDevice(kOtherUUID, "", true);
   EXPECT_CALL(connection_finder, CreateConnectionProxy()).Times(0);
@@ -335,7 +333,7 @@
   StrictMock<MockBluetoothLowEnergyConnectionFinder> connection_finder(
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_ANY_DEVICE);
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   // Prepare to add |device_|.
   PrepareDevice(kServiceUUID, kTestRemoteDeviceBluetoothAddress, true);
@@ -365,7 +363,7 @@
       nullptr, BluetoothLowEnergyConnectionFinder::FIND_PAIRED_DEVICE);
   // Starting discovery.
   FindAndExpectStartDiscovery(connection_finder);
-  ExpectStopDiscoveryAndRemoveObserver();
+  ExpectRemoveObserver();
 
   // Finding and creating a connection to the right device.
   FakeConnection* connection = connection_finder.ExpectCreateConnection();
@@ -388,9 +386,6 @@
 
   // Starting discovery.
   FindAndExpectStartDiscovery(connection_finder);
-  base::Closure stop_discovery_session_callback;
-  EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _))
-      .WillOnce(SaveArg<0>(&stop_discovery_session_callback));
 
   // Preparing to create a GATT connection to the right device.
   PrepareDevice(kServiceUUID, kTestRemoteDeviceBluetoothAddress, true);
@@ -401,10 +396,6 @@
   ASSERT_FALSE(last_found_connection_);
   connection->SetStatus(Connection::IN_PROGRESS);
 
-  // Stopping the discovery session.
-  ASSERT_FALSE(stop_discovery_session_callback.is_null());
-  stop_discovery_session_callback.Run();
-
   // Preparing to restart the discovery session.
   device::BluetoothAdapter::DiscoverySessionCallback discovery_callback;
   std::vector<const device::BluetoothDevice*> devices;
@@ -413,7 +404,11 @@
       .WillOnce(SaveArg<1>(&discovery_callback));
 
   // Connection fails.
-  connection->SetStatus(Connection::DISCONNECTED);
+  {
+    base::RunLoop run_loop;
+    connection->SetStatus(Connection::DISCONNECTED);
+    run_loop.RunUntilIdle();
+  }
 
   // Restarting the discovery session.
   scoped_ptr<device::MockBluetoothDiscoverySession> discovery_session(
@@ -430,14 +425,15 @@
 
   // Trying to create a connection.
   connection_finder.DeviceAdded(adapter_.get(), device_.get());
-  EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
 
   // Completing the connection.
-  base::RunLoop run_loop;
-  EXPECT_FALSE(last_found_connection_);
-  connection->SetStatus(Connection::IN_PROGRESS);
-  connection->SetStatus(Connection::CONNECTED);
-  run_loop.RunUntilIdle();
+  {
+    base::RunLoop run_loop;
+    EXPECT_FALSE(last_found_connection_);
+    connection->SetStatus(Connection::IN_PROGRESS);
+    connection->SetStatus(Connection::CONNECTED);
+    run_loop.RunUntilIdle();
+  }
   EXPECT_TRUE(last_found_connection_);
 }
 
@@ -483,7 +479,6 @@
 
   // Trying to create a connection.
   connection_finder.DeviceAdded(adapter_.get(), device_.get());
-  EXPECT_CALL(*last_discovery_session_alias_, Stop(_, _)).Times(AtLeast(1));
 
   // Completing the connection.
   base::RunLoop run_loop;
diff --git a/components/proximity_auth/bluetooth_connection.cc b/components/proximity_auth/bluetooth_connection.cc
index f06d52f..7adf8ef 100644
--- a/components/proximity_auth/bluetooth_connection.cc
+++ b/components/proximity_auth/bluetooth_connection.cc
@@ -88,6 +88,16 @@
                 base::Bind(&BluetoothConnection::OnSendError, weak_this));
 }
 
+void BluetoothConnection::DeviceChanged(device::BluetoothAdapter* adapter,
+                                        device::BluetoothDevice* device) {
+  DCHECK_EQ(adapter, adapter_.get());
+  if (device->GetAddress() == remote_device().bluetooth_address &&
+      status() != DISCONNECTED && !device->IsConnected()) {
+    PA_LOG(INFO) << "Device disconnected...";
+    Disconnect();
+  }
+}
+
 void BluetoothConnection::DeviceRemoved(device::BluetoothAdapter* adapter,
                                         device::BluetoothDevice* device) {
   DCHECK_EQ(adapter, adapter_.get());
@@ -96,7 +106,8 @@
 
   DCHECK_NE(status(), DISCONNECTED);
   PA_LOG(INFO) << "Device disconnected...";
-  Disconnect();
+  if (status() != DISCONNECTED)
+    Disconnect();
 }
 
 void BluetoothConnection::StartReceive() {
diff --git a/components/proximity_auth/bluetooth_connection.h b/components/proximity_auth/bluetooth_connection.h
index 8b39116a..63483eac 100644
--- a/components/proximity_auth/bluetooth_connection.h
+++ b/components/proximity_auth/bluetooth_connection.h
@@ -44,6 +44,8 @@
   void SendMessageImpl(scoped_ptr<WireMessage> message) override;
 
   // BluetoothAdapter::Observer:
+  void DeviceChanged(device::BluetoothAdapter* adapter,
+                     device::BluetoothDevice* device) override;
   void DeviceRemoved(device::BluetoothAdapter* adapter,
                      device::BluetoothDevice* device) override;
 
diff --git a/components/proximity_auth/bluetooth_connection_unittest.cc b/components/proximity_auth/bluetooth_connection_unittest.cc
index 33c49ebf..7eb0491 100644
--- a/components/proximity_auth/bluetooth_connection_unittest.cc
+++ b/components/proximity_auth/bluetooth_connection_unittest.cc
@@ -67,6 +67,7 @@
 
   using BluetoothConnection::status;
   using BluetoothConnection::Connect;
+  using BluetoothConnection::DeviceChanged;
   using BluetoothConnection::DeviceRemoved;
   using BluetoothConnection::Disconnect;
 
@@ -108,6 +109,7 @@
   // Transition the connection into an in-progress state.
   void BeginConnecting(MockBluetoothConnection* connection) {
     EXPECT_EQ(Connection::DISCONNECTED, connection->status());
+    ON_CALL(device_, IsConnected()).WillByDefault(Return(false));
 
     ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
     EXPECT_CALL(*connection, SetStatusProxy(Connection::IN_PROGRESS));
@@ -140,6 +142,7 @@
     callback.Run(socket_);
 
     EXPECT_EQ(Connection::CONNECTED, connection->status());
+    ON_CALL(device_, IsConnected()).WillByDefault(Return(true));
   }
 
   device::BluetoothSocket::ReceiveCompletionCallback* receive_callback() {
@@ -450,4 +453,33 @@
   error_callback.Run("The most helpful of error messages");
 }
 
+TEST_F(ProximityAuthBluetoothConnectionTest, DeviceChanged_Disconnected) {
+  // Create a connected connection.
+  StrictMock<MockBluetoothConnection> connection;
+  Connect(&connection);
+  EXPECT_TRUE(connection.IsConnected());
+
+  // If the remote device disconnects, |connection| should also disconnect.
+  ON_CALL(device_, IsConnected()).WillByDefault(Return(false));
+  EXPECT_CALL(connection, SetStatusProxy(Connection::DISCONNECTED));
+  EXPECT_CALL(*socket_, Disconnect(_));
+  EXPECT_CALL(*adapter_, RemoveObserver(&connection));
+  connection.DeviceChanged(adapter_.get(), &device_);
+  EXPECT_FALSE(connection.IsConnected());
+}
+
+TEST_F(ProximityAuthBluetoothConnectionTest, DeviceChanged_NotDisconnected) {
+  // Nothing should happen if DeviceChanged is called, but the remote device is
+  // not disconnected.
+  StrictMock<MockBluetoothConnection> connection;
+  Connect(&connection);
+  EXPECT_TRUE(connection.IsConnected());
+  connection.DeviceChanged(adapter_.get(), &device_);
+  EXPECT_TRUE(connection.IsConnected());
+
+  // The connection disconnects and unregisters as an observer upon destruction.
+  EXPECT_CALL(*socket_, Disconnect(_));
+  EXPECT_CALL(*adapter_, RemoveObserver(&connection));
+}
+
 }  // namespace proximity_auth
diff --git a/components/proximity_auth/connection.cc b/components/proximity_auth/connection.cc
index 437be60..85249bb8 100644
--- a/components/proximity_auth/connection.cc
+++ b/components/proximity_auth/connection.cc
@@ -46,6 +46,10 @@
   observers_.RemoveObserver(observer);
 }
 
+std::string Connection::GetDeviceAddress() {
+  return remote_device_.bluetooth_address;
+}
+
 void Connection::SetStatus(Status status) {
   if (status_ == status)
     return;
diff --git a/components/proximity_auth/connection.h b/components/proximity_auth/connection.h
index a79ce188..532e03d9 100644
--- a/components/proximity_auth/connection.h
+++ b/components/proximity_auth/connection.h
@@ -54,6 +54,9 @@
   // Disconnects from the remote device.
   virtual void Disconnect() = 0;
 
+  // The bluetooth address of the connected device.
+  virtual std::string GetDeviceAddress();
+
   Status status() const { return status_; }
 
  protected:
diff --git a/components/proximity_auth/proximity_auth_pref_manager.cc b/components/proximity_auth/proximity_auth_pref_manager.cc
new file mode 100644
index 0000000..f28e110
--- /dev/null
+++ b/components/proximity_auth/proximity_auth_pref_manager.cc
@@ -0,0 +1,112 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/scoped_user_pref_update.h"
+#include "base/values.h"
+#include "components/proximity_auth/logging/logging.h"
+#include "components/proximity_auth/proximity_auth_pref_names.h"
+
+namespace proximity_auth {
+
+ProximityAuthPrefManager::ProximityAuthPrefManager(PrefService* pref_service)
+    : pref_service_(pref_service) {}
+
+ProximityAuthPrefManager::~ProximityAuthPrefManager() {}
+
+// static
+void ProximityAuthPrefManager::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterDictionaryPref(prefs::kProximityAuthRemoteBleDevices);
+}
+
+bool ProximityAuthPrefManager::HasDeviceWithAddress(
+    const std::string& bluetooth_address) const {
+  return pref_service_->GetDictionary(prefs::kProximityAuthRemoteBleDevices)
+      ->HasKey(bluetooth_address);
+}
+
+bool ProximityAuthPrefManager::HasDeviceWithPublicKey(
+    const std::string& public_key) const {
+  return !GetDeviceAddress(public_key).empty();
+}
+
+std::string ProximityAuthPrefManager::GetDevicePublicKey(
+    const std::string& bluetooth_address) const {
+  std::string public_key;
+  GetRemoteBleDevices()->GetStringWithoutPathExpansion(bluetooth_address,
+                                                       &public_key);
+  return public_key;
+}
+
+std::string ProximityAuthPrefManager::GetDeviceAddress(
+    const std::string& public_key) const {
+  const base::DictionaryValue* remote_ble_devices = GetRemoteBleDevices();
+  for (base::DictionaryValue::Iterator it(*remote_ble_devices); !it.IsAtEnd();
+       it.Advance()) {
+    std::string value_string;
+    DCHECK(it.value().IsType(base::Value::TYPE_STRING));
+    if (it.value().GetAsString(&value_string) && value_string == public_key)
+      return it.key();
+  }
+  return std::string();
+}
+
+std::vector<std::string> ProximityAuthPrefManager::GetPublicKeys() const {
+  std::vector<std::string> public_keys;
+  const base::DictionaryValue* remote_ble_devices = GetRemoteBleDevices();
+  for (base::DictionaryValue::Iterator it(*remote_ble_devices); !it.IsAtEnd();
+       it.Advance()) {
+    std::string value_string;
+    DCHECK(it.value().IsType(base::Value::TYPE_STRING));
+    it.value().GetAsString(&value_string);
+    public_keys.push_back(value_string);
+  }
+  return public_keys;
+}
+
+void ProximityAuthPrefManager::AddOrUpdateDevice(
+    const std::string& bluetooth_address,
+    const std::string& public_key) {
+  PA_LOG(INFO) << "Adding " << public_key << " , " << bluetooth_address
+               << " pair.";
+  if (HasDeviceWithPublicKey(public_key) &&
+      GetDeviceAddress(public_key) != bluetooth_address) {
+    PA_LOG(WARNING) << "Two devices with different bluetooth address, but the "
+                       "same public key were added: "
+                    << public_key;
+    RemoveDeviceWithPublicKey(public_key);
+  }
+
+  DictionaryPrefUpdate remote_ble_devices_update(
+      pref_service_, prefs::kProximityAuthRemoteBleDevices);
+  remote_ble_devices_update->SetStringWithoutPathExpansion(bluetooth_address,
+                                                           public_key);
+}
+
+bool ProximityAuthPrefManager::RemoveDeviceWithAddress(
+    const std::string& bluetooth_address) {
+  DictionaryPrefUpdate remote_ble_devices_update(
+      pref_service_, prefs::kProximityAuthRemoteBleDevices);
+  return remote_ble_devices_update->RemoveWithoutPathExpansion(
+      bluetooth_address, nullptr);
+}
+
+bool ProximityAuthPrefManager::RemoveDeviceWithPublicKey(
+    const std::string& public_key) {
+  return RemoveDeviceWithAddress(GetDeviceAddress(public_key));
+}
+
+const base::DictionaryValue* ProximityAuthPrefManager::GetRemoteBleDevices()
+    const {
+  return pref_service_->GetDictionary(prefs::kProximityAuthRemoteBleDevices);
+}
+
+}  // namespace proximity_auth
diff --git a/components/proximity_auth/proximity_auth_pref_manager.h b/components/proximity_auth/proximity_auth_pref_manager.h
new file mode 100644
index 0000000..561921c
--- /dev/null
+++ b/components/proximity_auth/proximity_auth_pref_manager.h
@@ -0,0 +1,74 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_MANAGER_H
+#define COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_MANAGER_H
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace base {
+class DictionaryValue;
+}  // namespace base
+
+namespace proximity_auth {
+
+// This class manages the local (persistent) settings used by Smart Lock. It
+// provides methods to set and queries the local settings, e.g. the address of
+// BLE devices.
+class ProximityAuthPrefManager {
+ public:
+  // Creates a pref manager backed by preferences registered in
+  // |pref_service| (persistent across browser restarts). |pref_service| should
+  // have been registered using RegisterPrefs(). Not owned, must out live this
+  // instance.
+  explicit ProximityAuthPrefManager(PrefService* pref_service);
+  virtual ~ProximityAuthPrefManager();
+
+  // Registers the prefs used by this class to the given |pref_service|.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  // Methods used to handle remote BLE devices stored in prefs
+  // (kProximityAuthRemoteBleDevices).
+  //
+  // Each device correspond to a (public_key, bluetooth_address) pair. The
+  // bluetooth_address <-> public_key mapping is unique, i.e. if there is
+  // another device with same bluetooth address or public key that device will
+  // be replaced.
+  void AddOrUpdateDevice(const std::string& bluetooth_address,
+                         const std::string& public_key);
+
+  // Removes the unique device with |bluetooth_address| (|public_key|). Returns
+  // false if no device was found.
+  bool RemoveDeviceWithAddress(const std::string& bluetooth_address);
+  bool RemoveDeviceWithPublicKey(const std::string& public_key);
+
+  // Queries the devices stored in |kProximityAuthRemoteBleDevices| pref by
+  // |bluetooth_address| or |public_key|. Virtual for testing.
+  virtual bool HasDeviceWithAddress(const std::string& bluetooth_address) const;
+  virtual bool HasDeviceWithPublicKey(const std::string& public_key) const;
+  virtual std::string GetDevicePublicKey(
+      const std::string& bluetooth_address) const;
+  virtual std::string GetDeviceAddress(const std::string& public_key) const;
+  virtual std::vector<std::string> GetPublicKeys() const;
+
+ private:
+  const base::DictionaryValue* GetRemoteBleDevices() const;
+
+  // Contains perferences that outlive the lifetime of this object and across
+  // process restarts. Not owned and must outlive this instance.
+  PrefService* pref_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProximityAuthPrefManager);
+};
+
+}  // namespace proximity_auth
+
+#endif  // COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_MANAGER_H
diff --git a/components/proximity_auth/proximity_auth_pref_manager_unittest.cc b/components/proximity_auth/proximity_auth_pref_manager_unittest.cc
new file mode 100644
index 0000000..4abf11cb
--- /dev/null
+++ b/components/proximity_auth/proximity_auth_pref_manager_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/testing_pref_service.h"
+#include "components/proximity_auth/proximity_auth_pref_names.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace proximity_auth {
+namespace {
+
+const char kBluetoothAddress1[] = "11:22:33:44:55:66";
+const char kPublicKey1[] = "public key 1";
+
+const char kBluetoothAddress2[] = "22:33:44:55:66:77";
+const char kPublicKey2[] = "public key 2";
+
+}  //  namespace
+
+class ProximityAuthProximityAuthPrefManagerTest : public testing::Test {
+ protected:
+  ProximityAuthProximityAuthPrefManagerTest() {}
+
+  void SetUp() override {
+    ProximityAuthPrefManager::RegisterPrefs(pref_service_.registry());
+  }
+
+  void CheckRemoteBleDevice(const std::string& bluetooth_address,
+                            const std::string& public_key,
+                            ProximityAuthPrefManager& pref_manager) {
+    EXPECT_TRUE(pref_manager.HasDeviceWithAddress(bluetooth_address));
+    EXPECT_EQ(pref_manager.GetDevicePublicKey(bluetooth_address), public_key);
+
+    EXPECT_TRUE(pref_manager.HasDeviceWithPublicKey(public_key));
+    EXPECT_EQ(pref_manager.GetDeviceAddress(public_key), bluetooth_address);
+  }
+
+  TestingPrefServiceSimple pref_service_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProximityAuthProximityAuthPrefManagerTest);
+};
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest, RegisterPrefs) {
+  TestingPrefServiceSimple pref_service;
+  ProximityAuthPrefManager::RegisterPrefs(pref_service.registry());
+  EXPECT_TRUE(
+      pref_service.FindPreference(prefs::kProximityAuthRemoteBleDevices));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest, AddDevice) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest,
+       AddDevice_TwoDevicesWithSameAddress) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey2);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey2, pref_manager);
+
+  EXPECT_FALSE(pref_manager.HasDeviceWithPublicKey(kPublicKey1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest,
+       AddDevice_TwoDevicesWithSamePublicKey) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress2, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress2, kPublicKey1, pref_manager);
+
+  EXPECT_FALSE(pref_manager.HasDeviceWithAddress(kBluetoothAddress1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest, RemoveDeviceWithAddress) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  ASSERT_TRUE(pref_manager.RemoveDeviceWithAddress(kBluetoothAddress1));
+  EXPECT_FALSE(pref_manager.HasDeviceWithAddress(kBluetoothAddress1));
+  EXPECT_FALSE(pref_manager.HasDeviceWithPublicKey(kPublicKey1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest,
+       RemoveDeviceWithAddress_DeviceNotPresent) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  ASSERT_FALSE(pref_manager.RemoveDeviceWithAddress(kBluetoothAddress2));
+  EXPECT_TRUE(pref_manager.HasDeviceWithAddress(kBluetoothAddress1));
+  EXPECT_TRUE(pref_manager.HasDeviceWithPublicKey(kPublicKey1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest, RemoveDeviceWithPublicKey) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  ASSERT_TRUE(pref_manager.RemoveDeviceWithPublicKey(kPublicKey1));
+  EXPECT_FALSE(pref_manager.HasDeviceWithAddress(kBluetoothAddress1));
+  EXPECT_FALSE(pref_manager.HasDeviceWithPublicKey(kPublicKey1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest,
+       RemoveDeviceWithPublicKey_DeviceNotPresent) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  ASSERT_FALSE(pref_manager.RemoveDeviceWithPublicKey(kPublicKey2));
+  EXPECT_TRUE(pref_manager.HasDeviceWithAddress(kBluetoothAddress1));
+  EXPECT_TRUE(pref_manager.HasDeviceWithPublicKey(kPublicKey1));
+}
+
+TEST_F(ProximityAuthProximityAuthPrefManagerTest, GetPublicKeys) {
+  ProximityAuthPrefManager pref_manager(&pref_service_);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress1, kPublicKey1);
+  CheckRemoteBleDevice(kBluetoothAddress1, kPublicKey1, pref_manager);
+
+  pref_manager.AddOrUpdateDevice(kBluetoothAddress2, kPublicKey2);
+  CheckRemoteBleDevice(kBluetoothAddress2, kPublicKey2, pref_manager);
+
+  std::vector<std::string> public_keys = pref_manager.GetPublicKeys();
+
+  // Note: it's not guarantee that the order in |public_key| is the same as
+  // insertion, so directly comparing vectors would not work.
+  EXPECT_TRUE(public_keys.size() == 2);
+  EXPECT_TRUE(std::find(public_keys.begin(), public_keys.end(), kPublicKey1) !=
+              public_keys.end());
+  EXPECT_TRUE(std::find(public_keys.begin(), public_keys.end(), kPublicKey2) !=
+              public_keys.end());
+}
+
+}  // namespace proximity_auth
diff --git a/components/proximity_auth/proximity_auth_pref_names.cc b/components/proximity_auth/proximity_auth_pref_names.cc
new file mode 100644
index 0000000..13d9fa1
--- /dev/null
+++ b/components/proximity_auth/proximity_auth_pref_names.cc
@@ -0,0 +1,15 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/proximity_auth/proximity_auth_pref_names.h"
+
+namespace proximity_auth {
+namespace prefs {
+
+// The dictionary containing remote BLE devices.
+const char kProximityAuthRemoteBleDevices[] =
+    "proximity_auth.remote_ble_devices";
+
+}  // namespace prefs
+}  // namespace proximity_auth
diff --git a/components/proximity_auth/proximity_auth_pref_names.h b/components/proximity_auth/proximity_auth_pref_names.h
new file mode 100644
index 0000000..19c05a22
--- /dev/null
+++ b/components/proximity_auth/proximity_auth_pref_names.h
@@ -0,0 +1,16 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_NAMES_H
+#define COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_NAMES_H
+
+namespace proximity_auth {
+namespace prefs {
+
+extern const char kProximityAuthRemoteBleDevices[];
+
+}  // namespace prefs
+}  // proximity_auth
+
+#endif  // COMPONENTS_PROXIMITY_AUTH_PROXIMITY_AUTH_PREF_NAMES_H
diff --git a/components/proximity_auth/remote_device_loader.cc b/components/proximity_auth/remote_device_loader.cc
index b601703..98594f21 100644
--- a/components/proximity_auth/remote_device_loader.cc
+++ b/components/proximity_auth/remote_device_loader.cc
@@ -5,8 +5,10 @@
 #include "components/proximity_auth/remote_device_loader.h"
 
 #include "base/bind.h"
+#include "components/proximity_auth/cryptauth/base64url.h"
 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
 #include "components/proximity_auth/logging/logging.h"
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
 
 namespace proximity_auth {
 
@@ -14,11 +16,13 @@
     const std::vector<cryptauth::ExternalDeviceInfo>& unlock_keys,
     const std::string& user_id,
     const std::string& user_private_key,
-    scoped_ptr<SecureMessageDelegate> secure_message_delegate)
+    scoped_ptr<SecureMessageDelegate> secure_message_delegate,
+    ProximityAuthPrefManager* pref_manager)
     : remaining_unlock_keys_(unlock_keys),
       user_id_(user_id),
       user_private_key_(user_private_key),
       secure_message_delegate_(secure_message_delegate.Pass()),
+      pref_manager_(pref_manager),
       weak_ptr_factory_(this) {}
 
 RemoteDeviceLoader::~RemoteDeviceLoader() {}
@@ -65,9 +69,19 @@
   RemoteDevice::BluetoothType bluetooth_type =
       unlock_key.bluetooth_address().empty() ? RemoteDevice::BLUETOOTH_LE
                                              : RemoteDevice::BLUETOOTH_CLASSIC;
+
+  std::string bluetooth_address = unlock_key.bluetooth_address();
+  if (bluetooth_address.empty() && pref_manager_) {
+    std::string b64_public_key;
+    Base64UrlEncode(unlock_key.public_key(), &b64_public_key);
+    bluetooth_address = pref_manager_->GetDeviceAddress(b64_public_key);
+    PA_LOG(INFO) << "The BLE address of " << unlock_key.friendly_device_name()
+                 << " is " << bluetooth_address;
+  }
+
   remote_devices_.push_back(RemoteDevice(
       user_id_, unlock_key.friendly_device_name(), unlock_key.public_key(),
-      bluetooth_type, unlock_key.bluetooth_address(), psk, std::string()));
+      bluetooth_type, bluetooth_address, psk, std::string()));
 
   if (!remaining_unlock_keys_.size())
     callback_.Run(remote_devices_);
diff --git a/components/proximity_auth/remote_device_loader.h b/components/proximity_auth/remote_device_loader.h
index bf2e7c7..a492725 100644
--- a/components/proximity_auth/remote_device_loader.h
+++ b/components/proximity_auth/remote_device_loader.h
@@ -17,6 +17,7 @@
 
 namespace proximity_auth {
 
+class ProximityAuthPrefManager;
 class SecureMessageDelegate;
 
 // Loads a collection of RemoteDevice objects from the given ExternalDeviceInfo
@@ -29,11 +30,13 @@
   // |user_private_key|: The private key of the user's local device. Used to
   //                     derive the PSK.
   // |secure_message_delegate|: Used to derive each persistent symmetric key.
+  // |pref_manager|: Used to retrieve the Bluetooth address of BLE devices.
   RemoteDeviceLoader(
       const std::vector<cryptauth::ExternalDeviceInfo>& unlock_keys,
       const std::string& user_id,
       const std::string& user_private_key,
-      scoped_ptr<SecureMessageDelegate> secure_message_delegate);
+      scoped_ptr<SecureMessageDelegate> secure_message_delegate,
+      ProximityAuthPrefManager* pref_manager);
 
   ~RemoteDeviceLoader();
 
@@ -60,6 +63,9 @@
   // Performs the PSK key derivation.
   scoped_ptr<SecureMessageDelegate> secure_message_delegate_;
 
+  // Used to retrieve the address for BLE devices. Not owned.
+  ProximityAuthPrefManager* pref_manager_;
+
   // Invoked when the RemoteDevices are loaded.
   RemoteDeviceCallback callback_;
 
diff --git a/components/proximity_auth/remote_device_loader_unittest.cc b/components/proximity_auth/remote_device_loader_unittest.cc
index c2eb661..1521ccb 100644
--- a/components/proximity_auth/remote_device_loader_unittest.cc
+++ b/components/proximity_auth/remote_device_loader_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
 #include "components/proximity_auth/cryptauth/fake_secure_message_delegate.h"
+#include "components/proximity_auth/proximity_auth_pref_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -35,6 +36,14 @@
   return unlock_key;
 }
 
+class MockProximityAuthPrefManager : public ProximityAuthPrefManager {
+ public:
+  MockProximityAuthPrefManager() : ProximityAuthPrefManager(nullptr) {}
+  ~MockProximityAuthPrefManager() override {}
+
+  MOCK_CONST_METHOD1(GetDeviceAddress, std::string(const std::string&));
+};
+
 }  // namespace
 
 class ProximityAuthRemoteDeviceLoaderTest : public testing::Test {
@@ -42,7 +51,8 @@
   ProximityAuthRemoteDeviceLoaderTest()
       : secure_message_delegate_(new FakeSecureMessageDelegate()),
         user_private_key_(secure_message_delegate_->GetPrivateKeyForPublicKey(
-            kUserPublicKey)) {}
+            kUserPublicKey)),
+        pref_manager_(new MockProximityAuthPrefManager()) {}
 
   ~ProximityAuthRemoteDeviceLoaderTest() {}
 
@@ -64,13 +74,17 @@
   // Stores the result of the RemoteDeviceLoader.
   std::vector<RemoteDevice> remote_devices_;
 
+  // Stores the bluetooth address for BLE devices.
+  scoped_ptr<MockProximityAuthPrefManager> pref_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(ProximityAuthRemoteDeviceLoaderTest);
 };
 
 TEST_F(ProximityAuthRemoteDeviceLoaderTest, LoadZeroDevices) {
   std::vector<cryptauth::ExternalDeviceInfo> unlock_keys;
   RemoteDeviceLoader loader(unlock_keys, user_private_key_, kUserId,
-                            secure_message_delegate_.Pass());
+                            secure_message_delegate_.Pass(),
+                            pref_manager_.get());
 
   std::vector<RemoteDevice> result;
   EXPECT_CALL(*this, LoadCompleted());
@@ -85,7 +99,8 @@
   std::vector<cryptauth::ExternalDeviceInfo> unlock_keys(1,
                                                          CreateUnlockKey("1"));
   RemoteDeviceLoader loader(unlock_keys, user_private_key_, kUserId,
-                            secure_message_delegate_.Pass());
+                            secure_message_delegate_.Pass(),
+                            pref_manager_.get());
 
   std::vector<RemoteDevice> result;
   EXPECT_CALL(*this, LoadCompleted());
@@ -107,7 +122,12 @@
                                                          CreateUnlockKey("1"));
   unlock_keys[0].set_bluetooth_address(std::string());
   RemoteDeviceLoader loader(unlock_keys, user_private_key_, kUserId,
-                            secure_message_delegate_.Pass());
+                            secure_message_delegate_.Pass(),
+                            pref_manager_.get());
+
+  std::string ble_address = "00:00:00:00:00:00";
+  EXPECT_CALL(*pref_manager_, GetDeviceAddress(testing::_))
+      .WillOnce(testing::Return(ble_address));
 
   std::vector<RemoteDevice> result;
   EXPECT_CALL(*this, LoadCompleted());
@@ -119,8 +139,7 @@
   EXPECT_FALSE(remote_devices_[0].persistent_symmetric_key.empty());
   EXPECT_EQ(unlock_keys[0].friendly_device_name(), remote_devices_[0].name);
   EXPECT_EQ(unlock_keys[0].public_key(), remote_devices_[0].public_key);
-  EXPECT_EQ(unlock_keys[0].bluetooth_address(),
-            remote_devices_[0].bluetooth_address);
+  EXPECT_EQ(ble_address, remote_devices_[0].bluetooth_address);
   EXPECT_EQ(RemoteDevice::BLUETOOTH_LE, remote_devices_[0].bluetooth_type);
 }
 
@@ -130,7 +149,8 @@
   unlock_keys.push_back(CreateUnlockKey("2"));
   unlock_keys.push_back(CreateUnlockKey("3"));
   RemoteDeviceLoader loader(unlock_keys, user_private_key_, kUserId,
-                            secure_message_delegate_.Pass());
+                            secure_message_delegate_.Pass(),
+                            pref_manager_.get());
 
   std::vector<RemoteDevice> result;
   EXPECT_CALL(*this, LoadCompleted());
diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc
index 76806b9..60faa7ce 100644
--- a/components/proximity_auth/webui/proximity_auth_webui_handler.cc
+++ b/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -338,11 +338,13 @@
         return;
       }
 
+      // TODO(sacomoto): Pass an instance of ProximityAuthPrefManager. This is
+      // used to get the address of BLE devices.
       remote_device_loader_.reset(new RemoteDeviceLoader(
           std::vector<cryptauth::ExternalDeviceInfo>(1, unlock_key),
           proximity_auth_client_->GetAccountId(),
           enrollment_manager->GetUserPrivateKey(),
-          proximity_auth_client_->CreateSecureMessageDelegate()));
+          proximity_auth_client_->CreateSecureMessageDelegate(), nullptr));
       remote_device_loader_->Load(
           base::Bind(&ProximityAuthWebUIHandler::OnRemoteDevicesLoaded,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/renderer_context_menu/BUILD.gn b/components/renderer_context_menu/BUILD.gn
index b2a3dda..21b4e06 100644
--- a/components/renderer_context_menu/BUILD.gn
+++ b/components/renderer_context_menu/BUILD.gn
@@ -28,5 +28,6 @@
     "//base",
     "//content/public/browser",
     "//components/search_engines",
+    "//third_party/WebKit/public:blink_headers",
   ]
 }
diff --git a/components/scheduler/child/web_task_runner_impl.cc b/components/scheduler/child/web_task_runner_impl.cc
index e108fc2..b4794a4c 100644
--- a/components/scheduler/child/web_task_runner_impl.cc
+++ b/components/scheduler/child/web_task_runner_impl.cc
@@ -28,17 +28,6 @@
 void WebTaskRunnerImpl::postDelayedTask(
     const blink::WebTraceLocation& web_location,
     blink::WebTaskRunner::Task* task,
-    long long delayMs) {
-  tracked_objects::Location location(web_location.functionName(),
-                                     web_location.fileName(), -1, nullptr);
-  task_runner_->PostDelayedTask(
-      location, base::Bind(&blink::WebTaskRunner::Task::run, base::Owned(task)),
-      base::TimeDelta::FromMilliseconds(delayMs));
-}
-
-void WebTaskRunnerImpl::postDelayedTask(
-    const blink::WebTraceLocation& web_location,
-    blink::WebTaskRunner::Task* task,
     double delayMs) {
   tracked_objects::Location location(web_location.functionName(),
                                      web_location.fileName(), -1, nullptr);
diff --git a/components/scheduler/child/web_task_runner_impl.h b/components/scheduler/child/web_task_runner_impl.h
index f1ef079d..73a1e46f 100644
--- a/components/scheduler/child/web_task_runner_impl.h
+++ b/components/scheduler/child/web_task_runner_impl.h
@@ -31,10 +31,6 @@
   // blink::WebTaskRunner implementation:
   void postTask(const blink::WebTraceLocation& web_location,
                 blink::WebTaskRunner::Task* task) override;
-  // TODO(alexclarke): Remove this when possible.
-  void postDelayedTask(const blink::WebTraceLocation& web_location,
-                       blink::WebTaskRunner::Task* task,
-                       long long delayMs) override;
   void postDelayedTask(const blink::WebTraceLocation& web_location,
                        blink::WebTaskRunner::Task* task,
                        double delayMs) override;
diff --git a/components/security_interstitials/core/metrics_helper.cc b/components/security_interstitials/core/metrics_helper.cc
index da7002be..7466562 100644
--- a/components/security_interstitials/core/metrics_helper.cc
+++ b/components/security_interstitials/core/metrics_helper.cc
@@ -134,6 +134,10 @@
   RecordExtraUserInteractionMetrics(interaction);
 }
 
+void MetricsHelper::RecordShutdownMetrics() {
+  RecordExtraShutdownMetrics();
+}
+
 int MetricsHelper::NumVisits() {
   return num_visits_;
 }
diff --git a/components/security_interstitials/core/metrics_helper.h b/components/security_interstitials/core/metrics_helper.h
index 064a1809..e6102017 100644
--- a/components/security_interstitials/core/metrics_helper.h
+++ b/components/security_interstitials/core/metrics_helper.h
@@ -91,14 +91,17 @@
   // histogram and potentially in a RAPPOR metric.
   void RecordUserDecision(Decision decision);
   void RecordUserInteraction(Interaction interaction);
+  void RecordShutdownMetrics();
+
   // Number of times user visited this origin before. -1 means not-yet-set.
   int NumVisits();
 
  protected:
   // Subclasses should implement any embedder-specific recording logic in these
-  // methods. They'll be invoked from RecordUserDecision/Interaction.
+  // methods. They'll be invoked from the matching Record methods.
   virtual void RecordExtraUserDecisionMetrics(Decision decision) = 0;
   virtual void RecordExtraUserInteractionMetrics(Interaction interaction) = 0;
+  virtual void RecordExtraShutdownMetrics() = 0;
 
  private:
   // Used to query the HistoryService to see if the URL is in history.  It will
diff --git a/components/sessions.gypi b/components/sessions.gypi
index e2f8311..8dc4826 100644
--- a/components/sessions.gypi
+++ b/components/sessions.gypi
@@ -15,6 +15,7 @@
       'sessions/core/base_session_service_delegate.h',
       'sessions/core/live_tab.cc',
       'sessions/core/live_tab.h',
+      'sessions/core/live_tab_context.h',
       'sessions/core/persistent_tab_restore_service.cc',
       'sessions/core/persistent_tab_restore_service.h',
       'sessions/core/serialized_navigation_driver.h',
@@ -36,7 +37,6 @@
       'sessions/core/tab_restore_service.h',
       'sessions/core/tab_restore_service_client.cc',
       'sessions/core/tab_restore_service_client.h',
-      'sessions/core/tab_restore_service_delegate.h',
       'sessions/core/tab_restore_service_helper.cc',
       'sessions/core/tab_restore_service_helper.h',
       'sessions/core/tab_restore_service_observer.h',
diff --git a/components/sessions/BUILD.gn b/components/sessions/BUILD.gn
index 940d851..b9f043e 100644
--- a/components/sessions/BUILD.gn
+++ b/components/sessions/BUILD.gn
@@ -72,6 +72,7 @@
     "core/base_session_service_delegate.h",
     "core/live_tab.cc",
     "core/live_tab.h",
+    "core/live_tab_context.h",
     "core/serialized_navigation_driver.h",
     "core/serialized_navigation_entry.cc",
     "core/serialized_navigation_entry.h",
@@ -91,7 +92,6 @@
     "core/tab_restore_service.h",
     "core/tab_restore_service_client.cc",
     "core/tab_restore_service_client.h",
-    "core/tab_restore_service_delegate.h",
     "core/tab_restore_service_helper.cc",
     "core/tab_restore_service_helper.h",
     "core/tab_restore_service_observer.h",
diff --git a/components/sessions/core/in_memory_tab_restore_service.cc b/components/sessions/core/in_memory_tab_restore_service.cc
index c5d7641..27b6892 100644
--- a/components/sessions/core/in_memory_tab_restore_service.cc
+++ b/components/sessions/core/in_memory_tab_restore_service.cc
@@ -33,14 +33,12 @@
   helper_.CreateHistoricalTab(live_tab, index);
 }
 
-void InMemoryTabRestoreService::BrowserClosing(
-    TabRestoreServiceDelegate* delegate) {
-  helper_.BrowserClosing(delegate);
+void InMemoryTabRestoreService::BrowserClosing(LiveTabContext* context) {
+  helper_.BrowserClosing(context);
 }
 
-void InMemoryTabRestoreService::BrowserClosed(
-    TabRestoreServiceDelegate* delegate) {
-  helper_.BrowserClosed(delegate);
+void InMemoryTabRestoreService::BrowserClosed(LiveTabContext* context) {
+  helper_.BrowserClosed(context);
 }
 
 void InMemoryTabRestoreService::ClearEntries() {
@@ -52,9 +50,9 @@
 }
 
 std::vector<LiveTab*> InMemoryTabRestoreService::RestoreMostRecentEntry(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     int host_desktop_type) {
-  return helper_.RestoreMostRecentEntry(delegate, host_desktop_type);
+  return helper_.RestoreMostRecentEntry(context, host_desktop_type);
 }
 
 TabRestoreService::Tab* InMemoryTabRestoreService::RemoveTabEntryById(
@@ -63,11 +61,11 @@
 }
 
 std::vector<LiveTab*> InMemoryTabRestoreService::RestoreEntryById(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     SessionID::id_type id,
     int host_desktop_type,
     WindowOpenDisposition disposition) {
-  return helper_.RestoreEntryById(delegate, id, host_desktop_type, disposition);
+  return helper_.RestoreEntryById(context, id, host_desktop_type, disposition);
 }
 
 void InMemoryTabRestoreService::LoadTabsFromLastSession() {
diff --git a/components/sessions/core/in_memory_tab_restore_service.h b/components/sessions/core/in_memory_tab_restore_service.h
index 5c7e70e9..3e69f1b7 100644
--- a/components/sessions/core/in_memory_tab_restore_service.h
+++ b/components/sessions/core/in_memory_tab_restore_service.h
@@ -35,16 +35,15 @@
   void AddObserver(TabRestoreServiceObserver* observer) override;
   void RemoveObserver(TabRestoreServiceObserver* observer) override;
   void CreateHistoricalTab(LiveTab* live_tab, int index) override;
-  void BrowserClosing(TabRestoreServiceDelegate* delegate) override;
-  void BrowserClosed(TabRestoreServiceDelegate* delegate) override;
+  void BrowserClosing(LiveTabContext* context) override;
+  void BrowserClosed(LiveTabContext* context) override;
   void ClearEntries() override;
   const Entries& entries() const override;
-  std::vector<LiveTab*> RestoreMostRecentEntry(
-      TabRestoreServiceDelegate* delegate,
-      int host_desktop_type) override;
+  std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
+                                               int host_desktop_type) override;
   Tab* RemoveTabEntryById(SessionID::id_type id) override;
   std::vector<LiveTab*> RestoreEntryById(
-      TabRestoreServiceDelegate* delegate,
+      LiveTabContext* context,
       SessionID::id_type id,
       int host_desktop_type,
       WindowOpenDisposition disposition) override;
diff --git a/components/sessions/core/tab_restore_service_delegate.h b/components/sessions/core/live_tab_context.h
similarity index 75%
rename from components/sessions/core/tab_restore_service_delegate.h
rename to components/sessions/core/live_tab_context.h
index f53b67d..03615b0c 100644
--- a/components/sessions/core/tab_restore_service_delegate.h
+++ b/components/sessions/core/live_tab_context.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 COMPONENTS_SESSIONS_CORE_TAB_RESTORE_SERVICE_DELEGATE_H_
-#define COMPONENTS_SESSIONS_CORE_TAB_RESTORE_SERVICE_DELEGATE_H_
+#ifndef COMPONENTS_SESSIONS_CORE_LIVE_TAB_CONTEXT_H_
+#define COMPONENTS_SESSIONS_CORE_LIVE_TAB_CONTEXT_H_
 
 #include <string>
 #include <vector>
@@ -17,26 +17,17 @@
 class SerializedNavigationEntry;
 class PlatformSpecificTabData;
 
-// Objects implement this interface to provide necessary functionality for
-// TabRestoreService to operate. These methods are mostly copies of existing
-// Browser methods.
-class SESSIONS_EXPORT TabRestoreServiceDelegate {
+// An interface representing the context in which LiveTab instances exist in the
+// embedder. As a concrete example, desktop Chrome has an implementation that
+// is backed by an instance of the Browser class.
+class SESSIONS_EXPORT LiveTabContext {
  public:
-  // see BrowserWindow::Show()
+  // TODO(blundell): Rename.
   virtual void ShowBrowserWindow() = 0;
-
-  // see Browser::session_id()
   virtual const SessionID& GetSessionID() const = 0;
-
-  // see Browser::tab_count()
   virtual int GetTabCount() const = 0;
-
-  // see Browser::active_index()
   virtual int GetSelectedIndex() const = 0;
-
-  // see Browser::app_name()
   virtual std::string GetAppName() const = 0;
-
   virtual LiveTab* GetLiveTabAt(int index) const = 0;
   virtual LiveTab* GetActiveLiveTab() const = 0;
   virtual bool IsTabPinned(int index) const = 0;
@@ -68,9 +59,9 @@
   virtual void CloseTab() = 0;
 
  protected:
-  virtual ~TabRestoreServiceDelegate() {}
+  virtual ~LiveTabContext() {}
 };
 
 }  // namespace sessions
 
-#endif  // COMPONENTS_SESSIONS_CORE_TAB_RESTORE_SERVICE_DELEGATE_H_
+#endif  // COMPONENTS_SESSIONS_CORE_LIVE_TAB_CONTEXT_H_
diff --git a/components/sessions/core/persistent_tab_restore_service.cc b/components/sessions/core/persistent_tab_restore_service.cc
index 6e21efc..3231b04 100644
--- a/components/sessions/core/persistent_tab_restore_service.cc
+++ b/components/sessions/core/persistent_tab_restore_service.cc
@@ -938,14 +938,12 @@
   helper_.CreateHistoricalTab(live_tab, index);
 }
 
-void PersistentTabRestoreService::BrowserClosing(
-    TabRestoreServiceDelegate* delegate) {
-  helper_.BrowserClosing(delegate);
+void PersistentTabRestoreService::BrowserClosing(LiveTabContext* context) {
+  helper_.BrowserClosing(context);
 }
 
-void PersistentTabRestoreService::BrowserClosed(
-    TabRestoreServiceDelegate* delegate) {
-  helper_.BrowserClosed(delegate);
+void PersistentTabRestoreService::BrowserClosed(LiveTabContext* context) {
+  helper_.BrowserClosed(context);
 }
 
 void PersistentTabRestoreService::ClearEntries() {
@@ -957,9 +955,9 @@
 }
 
 std::vector<LiveTab*> PersistentTabRestoreService::RestoreMostRecentEntry(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     int host_desktop_type) {
-  return helper_.RestoreMostRecentEntry(delegate, host_desktop_type);
+  return helper_.RestoreMostRecentEntry(context, host_desktop_type);
 }
 
 TabRestoreService::Tab* PersistentTabRestoreService::RemoveTabEntryById(
@@ -968,11 +966,11 @@
 }
 
 std::vector<LiveTab*> PersistentTabRestoreService::RestoreEntryById(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     SessionID::id_type id,
     int host_desktop_type,
     WindowOpenDisposition disposition) {
-  return helper_.RestoreEntryById(delegate, id, host_desktop_type, disposition);
+  return helper_.RestoreEntryById(context, id, host_desktop_type, disposition);
 }
 
 bool PersistentTabRestoreService::IsLoaded() const {
diff --git a/components/sessions/core/persistent_tab_restore_service.h b/components/sessions/core/persistent_tab_restore_service.h
index 39f3b00..587d5af 100644
--- a/components/sessions/core/persistent_tab_restore_service.h
+++ b/components/sessions/core/persistent_tab_restore_service.h
@@ -32,16 +32,15 @@
   void AddObserver(TabRestoreServiceObserver* observer) override;
   void RemoveObserver(TabRestoreServiceObserver* observer) override;
   void CreateHistoricalTab(LiveTab* live_tab, int index) override;
-  void BrowserClosing(TabRestoreServiceDelegate* delegate) override;
-  void BrowserClosed(TabRestoreServiceDelegate* delegate) override;
+  void BrowserClosing(LiveTabContext* context) override;
+  void BrowserClosed(LiveTabContext* context) override;
   void ClearEntries() override;
   const Entries& entries() const override;
-  std::vector<LiveTab*> RestoreMostRecentEntry(
-      TabRestoreServiceDelegate* delegate,
-      int host_desktop_type) override;
+  std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
+                                               int host_desktop_type) override;
   Tab* RemoveTabEntryById(SessionID::id_type id) override;
   std::vector<LiveTab*> RestoreEntryById(
-      TabRestoreServiceDelegate* delegate,
+      LiveTabContext* context,
       SessionID::id_type id,
       int host_desktop_type,
       WindowOpenDisposition disposition) override;
diff --git a/components/sessions/core/tab_restore_service.h b/components/sessions/core/tab_restore_service.h
index 55f25933..c96ece31 100644
--- a/components/sessions/core/tab_restore_service.h
+++ b/components/sessions/core/tab_restore_service.h
@@ -22,7 +22,7 @@
 
 class LiveTab;
 class PlatformSpecificTabData;
-class TabRestoreServiceDelegate;
+class LiveTabContext;
 class TabRestoreServiceObserver;
 
 // TabRestoreService is responsible for maintaining the most recently closed
@@ -136,13 +136,15 @@
   // entries has changed.
   virtual void CreateHistoricalTab(LiveTab* live_tab, int index) = 0;
 
-  // Invoked when a browser is closing. If |delegate| is a tabbed browser with
+  // TODO(blundell): Rename and fix comment.
+  // Invoked when a browser is closing. If |context| is a tabbed browser with
   // at least one tab, a Window is created, added to entries and observers are
   // notified.
-  virtual void BrowserClosing(TabRestoreServiceDelegate* delegate) = 0;
+  virtual void BrowserClosing(LiveTabContext* context) = 0;
 
+  // TODO(blundell): Rename and fix comment.
   // Invoked when the browser is done closing.
-  virtual void BrowserClosed(TabRestoreServiceDelegate* delegate) = 0;
+  virtual void BrowserClosed(LiveTabContext* context) = 0;
 
   // Removes all entries from the list and notifies observers the list
   // of tabs has changed.
@@ -154,12 +156,12 @@
 
   // Restores the most recently closed entry. Does nothing if there are no
   // entries to restore. If the most recently restored entry is a tab, it is
-  // added to |delegate|. |host_desktop_type| is a value that is opaque to this
+  // added to |context|. |host_desktop_type| is a value that is opaque to this
   // class and will be used only to pass back to the embedder via
   // TabRestoreServiceClient if necessary. Returns the LiveTab instances of the
   // restored tab(s).
   virtual std::vector<LiveTab*> RestoreMostRecentEntry(
-      TabRestoreServiceDelegate* delegate,
+      LiveTabContext* context,
       int host_desktop_type) = 0;
 
   // Removes the Tab with id |id| from the list and returns it; ownership is
@@ -167,7 +169,7 @@
   virtual Tab* RemoveTabEntryById(SessionID::id_type id) = 0;
 
   // Restores an entry by id. If there is no entry with an id matching |id|,
-  // this does nothing. If |delegate| is NULL, this creates a new window for the
+  // this does nothing. If |context| is NULL, this creates a new window for the
   // entry. |disposition| is respected, but the attributes (tabstrip index,
   // browser window) of the tab when it was closed will be respected if
   // disposition is UNKNOWN.  |host_desktop_type| is a value that is opaque to
@@ -175,7 +177,7 @@
   // TabRestoreServiceClient if necessary.  Returns the LiveTab instances of the
   // restored tab(s).
   virtual std::vector<LiveTab*> RestoreEntryById(
-      TabRestoreServiceDelegate* delegate,
+      LiveTabContext* context,
       SessionID::id_type id,
       int host_desktop_type,
       WindowOpenDisposition disposition) = 0;
diff --git a/components/sessions/core/tab_restore_service_client.h b/components/sessions/core/tab_restore_service_client.h
index 82e5c63d..c7cb3f7 100644
--- a/components/sessions/core/tab_restore_service_client.h
+++ b/components/sessions/core/tab_restore_service_client.h
@@ -23,7 +23,7 @@
 
 class LiveTab;
 struct SessionWindow;
-class TabRestoreServiceDelegate;
+class LiveTabContext;
 
 // Callback from TabRestoreServiceClient::GetLastSession.
 // The second parameter is the id of the window that was last active.
@@ -36,27 +36,25 @@
  public:
   virtual ~TabRestoreServiceClient();
 
-  // Creates a TabRestoreServiceDelegate instance that is associated with
+  // Creates a LiveTabContext instance that is associated with
   // |host_desktop_type| and |app_name|. May return nullptr (e.g., if the
-  // embedder does not support TabRestoreServiceDelegate functionality).
+  // embedder does not support LiveTabContext functionality).
   // Note that |host_desktop_type| is opaque to the component; the only values
   // that will be passed here are those that have been passed *in* to the
   // component from the embedder via TabRestoreService.
-  virtual TabRestoreServiceDelegate* CreateTabRestoreServiceDelegate(
-      int host_desktop_type,
-      const std::string& app_name) = 0;
+  virtual LiveTabContext* CreateLiveTabContext(int host_desktop_type,
+                                               const std::string& app_name) = 0;
 
-  // Returns the TabRestoreServiceDelegate instance that is associated with
+  // Returns the LiveTabContext instance that is associated with
   // |tab|, or null if there is no such instance.
-  virtual TabRestoreServiceDelegate* FindTabRestoreServiceDelegateForTab(
-      const LiveTab* tab) = 0;
+  virtual LiveTabContext* FindLiveTabContextForTab(const LiveTab* tab) = 0;
 
-  // Returns the TabRestoreServiceDelegate instance that is associated with
+  // Returns the LiveTabContext instance that is associated with
   // |desired_id| and |host_desktop_type|, or null if there is no such instance.
   // Note that |host_desktop_type| is opaque to the component; the only values
   // that will be passed here are those that have been passed *in* to the
   // component from the embedder via TabRestoreService.
-  virtual TabRestoreServiceDelegate* FindTabRestoreServiceDelegateWithID(
+  virtual LiveTabContext* FindLiveTabContextWithID(
       SessionID::id_type desired_id,
       int host_desktop_type) = 0;
 
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index 5fdd7ffe..2ce992f4 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -11,10 +11,10 @@
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "components/sessions/core/live_tab.h"
+#include "components/sessions/core/live_tab_context.h"
 #include "components/sessions/core/serialized_navigation_entry.h"
 #include "components/sessions/core/session_types.h"
 #include "components/sessions/core/tab_restore_service_client.h"
-#include "components/sessions/core/tab_restore_service_delegate.h"
 #include "components/sessions/core/tab_restore_service_observer.h"
 
 namespace sessions {
@@ -68,41 +68,39 @@
   if (restoring_)
     return;
 
-  TabRestoreServiceDelegate* delegate =
-      client_->FindTabRestoreServiceDelegateForTab(live_tab);
-  if (closing_delegates_.find(delegate) != closing_delegates_.end())
+  LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab);
+  if (closing_contexts_.find(context) != closing_contexts_.end())
     return;
 
   scoped_ptr<Tab> local_tab(new Tab());
-  PopulateTab(local_tab.get(), index, delegate, live_tab);
+  PopulateTab(local_tab.get(), index, context, live_tab);
   if (local_tab->navigations.empty())
     return;
 
   AddEntry(local_tab.release(), true, true);
 }
 
-void TabRestoreServiceHelper::BrowserClosing(
-    TabRestoreServiceDelegate* delegate) {
-  closing_delegates_.insert(delegate);
+void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) {
+  closing_contexts_.insert(context);
 
   scoped_ptr<Window> window(new Window());
-  window->selected_tab_index = delegate->GetSelectedIndex();
+  window->selected_tab_index = context->GetSelectedIndex();
   window->timestamp = TimeNow();
-  window->app_name = delegate->GetAppName();
+  window->app_name = context->GetAppName();
 
   // Don't use std::vector::resize() because it will push copies of an empty tab
   // into the vector, which will give all tabs in a window the same ID.
-  for (int i = 0; i < delegate->GetTabCount(); ++i) {
+  for (int i = 0; i < context->GetTabCount(); ++i) {
     window->tabs.push_back(Tab());
   }
   size_t entry_index = 0;
-  for (int tab_index = 0; tab_index < delegate->GetTabCount(); ++tab_index) {
-    PopulateTab(&(window->tabs[entry_index]), tab_index, delegate,
-                delegate->GetLiveTabAt(tab_index));
+  for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) {
+    PopulateTab(&(window->tabs[entry_index]), tab_index, context,
+                context->GetLiveTabAt(tab_index));
     if (window->tabs[entry_index].navigations.empty()) {
       window->tabs.erase(window->tabs.begin() + entry_index);
     } else {
-      window->tabs[entry_index].browser_id = delegate->GetSessionID().id();
+      window->tabs[entry_index].browser_id = context->GetSessionID().id();
       entry_index++;
     }
   }
@@ -119,9 +117,8 @@
   }
 }
 
-void TabRestoreServiceHelper::BrowserClosed(
-    TabRestoreServiceDelegate* delegate) {
-  closing_delegates_.erase(delegate);
+void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) {
+  closing_contexts_.erase(context);
 }
 
 void TabRestoreServiceHelper::ClearEntries() {
@@ -136,13 +133,13 @@
 }
 
 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     int host_desktop_type) {
   if (entries_.empty())
     return std::vector<LiveTab*>();
 
-  return RestoreEntryById(delegate, entries_.front()->id, host_desktop_type,
-      UNKNOWN);
+  return RestoreEntryById(context, entries_.front()->id, host_desktop_type,
+                          UNKNOWN);
 }
 
 TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById(
@@ -161,7 +158,7 @@
 }
 
 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     SessionID::id_type id,
     int host_desktop_type,
     WindowOpenDisposition disposition) {
@@ -184,31 +181,31 @@
     entry_iterator = entries_.end();
   }
 
-  // |delegate| will be NULL in cases where one isn't already available (eg,
+  // |context| will be NULL in cases where one isn't already available (eg,
   // when invoked on Mac OS X with no windows open). In this case, create a
   // new browser into which we restore the tabs.
   std::vector<LiveTab*> live_tabs;
   if (entry->type == TabRestoreService::TAB) {
     Tab* tab = static_cast<Tab*>(entry);
     LiveTab* restored_tab = NULL;
-    delegate = RestoreTab(*tab, delegate, host_desktop_type, disposition,
-        &restored_tab);
+    context = RestoreTab(*tab, context, host_desktop_type, disposition,
+                         &restored_tab);
     live_tabs.push_back(restored_tab);
-    delegate->ShowBrowserWindow();
+    context->ShowBrowserWindow();
   } else if (entry->type == TabRestoreService::WINDOW) {
-    TabRestoreServiceDelegate* current_delegate = delegate;
+    LiveTabContext* current_context = context;
     Window* window = static_cast<Window*>(entry);
 
     // When restoring a window, either the entire window can be restored, or a
     // single tab within it. If the entry's ID matches the one to restore, then
     // the entire window will be restored.
     if (!restoring_tab_in_window) {
-      delegate = client_->CreateTabRestoreServiceDelegate(host_desktop_type,
-                                                          window->app_name);
+      context =
+          client_->CreateLiveTabContext(host_desktop_type, window->app_name);
       for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) {
         const Tab& tab = window->tabs[tab_i];
-        LiveTab* restored_tab = delegate->AddRestoredTab(
-            tab.navigations, delegate->GetTabCount(),
+        LiveTab* restored_tab = context->AddRestoredTab(
+            tab.navigations, context->GetTabCount(),
             tab.current_navigation_index, tab.extension_app_id,
             static_cast<int>(tab_i) == window->selected_tab_index, tab.pinned,
             tab.from_last_session, tab.platform_data.get(),
@@ -223,7 +220,7 @@
       // All the window's tabs had the same former browser_id.
       if (window->tabs[0].has_browser()) {
         UpdateTabBrowserIDs(window->tabs[0].browser_id,
-                            delegate->GetSessionID().id());
+                            context->GetSessionID().id());
       }
     } else {
       // Restore a single tab from the window. Find the tab that matches the ID
@@ -233,8 +230,8 @@
         const Tab& tab = *tab_i;
         if (tab.id == id) {
           LiveTab* restored_tab = NULL;
-          delegate = RestoreTab(tab, delegate, host_desktop_type, disposition,
-              &restored_tab);
+          context = RestoreTab(tab, context, host_desktop_type, disposition,
+                               &restored_tab);
           live_tabs.push_back(restored_tab);
           window->tabs.erase(tab_i);
           // If restoring the tab leaves the window with nothing else, delete it
@@ -246,22 +243,21 @@
             // Update the browser ID of the rest of the tabs in the window so if
             // any one is restored, it goes into the same window as the tab
             // being restored now.
-            UpdateTabBrowserIDs(tab.browser_id,
-                                delegate->GetSessionID().id());
+            UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id());
             for (std::vector<Tab>::iterator tab_j = window->tabs.begin();
                  tab_j != window->tabs.end(); ++tab_j) {
-              (*tab_j).browser_id = delegate->GetSessionID().id();
+              (*tab_j).browser_id = context->GetSessionID().id();
             }
           }
           break;
         }
       }
     }
-    delegate->ShowBrowserWindow();
+    context->ShowBrowserWindow();
 
-    if (disposition == CURRENT_TAB && current_delegate &&
-        current_delegate->GetActiveLiveTab()) {
-      current_delegate->CloseTab();
+    if (disposition == CURRENT_TAB && current_context &&
+        current_context->GetActiveLiveTab()) {
+      current_context->CloseTab();
     }
   } else {
     NOTREACHED();
@@ -361,7 +357,7 @@
 
 void TabRestoreServiceHelper::PopulateTab(Tab* tab,
                                           int index,
-                                          TabRestoreServiceDelegate* delegate,
+                                          LiveTabContext* context,
                                           LiveTab* live_tab) {
   const int pending_index = live_tab->GetPendingEntryIndex();
   int entry_count = live_tab->GetEntryCount();
@@ -387,52 +383,51 @@
   tab->platform_data = live_tab->GetPlatformSpecificTabData();
 
   // Delegate may be NULL during unit tests.
-  if (delegate) {
-    tab->browser_id = delegate->GetSessionID().id();
-    tab->pinned = delegate->IsTabPinned(tab->tabstrip_index);
+  if (context) {
+    tab->browser_id = context->GetSessionID().id();
+    tab->pinned = context->IsTabPinned(tab->tabstrip_index);
   }
 }
 
-TabRestoreServiceDelegate* TabRestoreServiceHelper::RestoreTab(
+LiveTabContext* TabRestoreServiceHelper::RestoreTab(
     const Tab& tab,
-    TabRestoreServiceDelegate* delegate,
+    LiveTabContext* context,
     int host_desktop_type,
     WindowOpenDisposition disposition,
     LiveTab** live_tab) {
   LiveTab* restored_tab;
-  if (disposition == CURRENT_TAB && delegate) {
-    restored_tab = delegate->ReplaceRestoredTab(
+  if (disposition == CURRENT_TAB && context) {
+    restored_tab = context->ReplaceRestoredTab(
         tab.navigations, tab.current_navigation_index, tab.from_last_session,
         tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override);
   } else {
     // We only respsect the tab's original browser if there's no disposition.
     if (disposition == UNKNOWN && tab.has_browser()) {
-      delegate = client_->FindTabRestoreServiceDelegateWithID(
-          tab.browser_id, host_desktop_type);
+      context =
+          client_->FindLiveTabContextWithID(tab.browser_id, host_desktop_type);
     }
 
     int tab_index = -1;
 
-    // |delegate| will be NULL in cases where one isn't already available (eg,
+    // |context| will be NULL in cases where one isn't already available (eg,
     // when invoked on Mac OS X with no windows open). In this case, create a
     // new browser into which we restore the tabs.
-    if (delegate && disposition != NEW_WINDOW) {
+    if (context && disposition != NEW_WINDOW) {
       tab_index = tab.tabstrip_index;
     } else {
-      delegate = client_->CreateTabRestoreServiceDelegate(host_desktop_type,
-                                                          std::string());
+      context = client_->CreateLiveTabContext(host_desktop_type, std::string());
       if (tab.has_browser())
-        UpdateTabBrowserIDs(tab.browser_id, delegate->GetSessionID().id());
+        UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id());
     }
 
     // Place the tab at the end if the tab index is no longer valid or
     // we were passed a specific disposition.
-    if (tab_index < 0 || tab_index > delegate->GetTabCount() ||
+    if (tab_index < 0 || tab_index > context->GetTabCount() ||
         disposition != UNKNOWN) {
-      tab_index = delegate->GetTabCount();
+      tab_index = context->GetTabCount();
     }
 
-    restored_tab = delegate->AddRestoredTab(
+    restored_tab = context->AddRestoredTab(
         tab.navigations, tab_index, tab.current_navigation_index,
         tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned,
         tab.from_last_session, tab.platform_data.get(),
@@ -444,7 +439,7 @@
   if (live_tab)
     *live_tab = restored_tab;
 
-  return delegate;
+  return context;
 }
 
 
diff --git a/components/sessions/core/tab_restore_service_helper.h b/components/sessions/core/tab_restore_service_helper.h
index 983d9aa..8fa5c827 100644
--- a/components/sessions/core/tab_restore_service_helper.h
+++ b/components/sessions/core/tab_restore_service_helper.h
@@ -20,7 +20,7 @@
 
 class TabRestoreService;
 class TabRestoreServiceClient;
-class TabRestoreServiceDelegate;
+class LiveTabContext;
 class TabRestoreServiceObserver;
 class TimeFactory;
 
@@ -73,15 +73,14 @@
   void AddObserver(TabRestoreServiceObserver* observer);
   void RemoveObserver(TabRestoreServiceObserver* observer);
   void CreateHistoricalTab(LiveTab* live_tab, int index);
-  void BrowserClosing(TabRestoreServiceDelegate* delegate);
-  void BrowserClosed(TabRestoreServiceDelegate* delegate);
+  void BrowserClosing(LiveTabContext* context);
+  void BrowserClosed(LiveTabContext* context);
   void ClearEntries();
   const Entries& entries() const;
-  std::vector<LiveTab*> RestoreMostRecentEntry(
-      TabRestoreServiceDelegate* delegate,
-      int host_desktop_type);
+  std::vector<LiveTab*> RestoreMostRecentEntry(LiveTabContext* context,
+                                               int host_desktop_type);
   Tab* RemoveTabEntryById(SessionID::id_type id);
-  std::vector<LiveTab*> RestoreEntryById(TabRestoreServiceDelegate* delegate,
+  std::vector<LiveTab*> RestoreEntryById(LiveTabContext* context,
                                          SessionID::id_type id,
                                          int host_desktop_type,
                                          WindowOpenDisposition disposition);
@@ -115,26 +114,26 @@
   friend class PersistentTabRestoreService;
 
   // Populates the tab's navigations from the LiveTab, and its browser_id and
-  // pinned state from the delegate.
+  // pinned state from the context.
   void PopulateTab(Tab* tab,
                    int index,
-                   TabRestoreServiceDelegate* delegate,
+                   LiveTabContext* context,
                    LiveTab* live_tab);
 
   // This is a helper function for RestoreEntryById() for restoring a single
-  // tab. If |delegate| is NULL, this creates a new window for the entry. This
-  // returns the TabRestoreServiceDelegate into which the tab was restored.
+  // tab. If |context| is NULL, this creates a new window for the entry. This
+  // returns the LiveTabContext into which the tab was restored.
   // |disposition| will be respected, but if it is UNKNOWN then the tab's
   // original attributes will be respected instead. If a new
-  // TabRestoreServiceDelegate needs to be created for this tab,
+  // LiveTabContext needs to be created for this tab,
   // |host_desktop_type| will be passed to
-  // TabRestoreServiceClient::CreateTabRestoreServiceDelegate(). If present,
+  // TabRestoreServiceClient::CreateLiveTabContext(). If present,
   // |live_tab| will be populated with the LiveTab of the restored tab.
-  TabRestoreServiceDelegate* RestoreTab(const Tab& tab,
-                                        TabRestoreServiceDelegate* delegate,
-                                        int host_desktop_type,
-                                        WindowOpenDisposition disposition,
-                                        LiveTab** live_tab);
+  LiveTabContext* RestoreTab(const Tab& tab,
+                             LiveTabContext* context,
+                             int host_desktop_type,
+                             WindowOpenDisposition disposition,
+                             LiveTab** live_tab);
 
   // Returns true if |tab| has more than one navigation. If |tab| has more
   // than one navigation |tab->current_navigation_index| is constrained based
@@ -176,10 +175,10 @@
 
   base::ObserverList<TabRestoreServiceObserver> observer_list_;
 
-  // Set of delegates that we've received a BrowserClosing method for but no
-  // corresponding BrowserClosed. We cache the set of delegates closing to
+  // Set of contexts that we've received a BrowserClosing method for but no
+  // corresponding BrowserClosed. We cache the set of contexts closing to
   // avoid creating historical tabs for them.
-  std::set<TabRestoreServiceDelegate*> closing_delegates_;
+  std::set<LiveTabContext*> closing_contexts_;
 
   TimeFactory* const time_factory_;
 
diff --git a/components/storage_monitor/storage_monitor_win.cc b/components/storage_monitor/storage_monitor_win.cc
index dae08e86..95a6911 100644
--- a/components/storage_monitor/storage_monitor_win.cc
+++ b/components/storage_monitor/storage_monitor_win.cc
@@ -9,7 +9,6 @@
 #include <fileapi.h>
 #include <shlobj.h>
 
-#include "base/profiler/scoped_tracker.h"
 #include "base/win/wrapped_window_proc.h"
 #include "components/storage_monitor/portable_device_watcher_win.h"
 #include "components/storage_monitor/removable_device_constants.h"
diff --git a/components/sync_driver/fake_sync_client.cc b/components/sync_driver/fake_sync_client.cc
index 048c7e6..0470871 100644
--- a/components/sync_driver/fake_sync_client.cc
+++ b/components/sync_driver/fake_sync_client.cc
@@ -20,6 +20,8 @@
 
 FakeSyncClient::~FakeSyncClient() {}
 
+void FakeSyncClient::Initialize(SyncService* sync_service) {}
+
 SyncService* FakeSyncClient::GetSyncService() {
   return sync_service_.get();
 }
diff --git a/components/sync_driver/fake_sync_client.h b/components/sync_driver/fake_sync_client.h
index eadeef2..2007191 100644
--- a/components/sync_driver/fake_sync_client.h
+++ b/components/sync_driver/fake_sync_client.h
@@ -17,6 +17,8 @@
   explicit FakeSyncClient(SyncApiComponentFactory* factory);
   ~FakeSyncClient() override;
 
+  void Initialize(SyncService* sync_service) override;
+
   SyncService* GetSyncService() override;
   PrefService* GetPrefService() override;
   bookmarks::BookmarkModel* GetBookmarkModel() override;
diff --git a/components/sync_driver/generic_change_processor_unittest.cc b/components/sync_driver/generic_change_processor_unittest.cc
index 7ab8929..541342d 100644
--- a/components/sync_driver/generic_change_processor_unittest.cc
+++ b/components/sync_driver/generic_change_processor_unittest.cc
@@ -83,8 +83,7 @@
   MockSyncApiComponentFactory() {}
 
   // SyncApiComponentFactory implementation.
-  void Initialize(SyncService* sync_service) override {}
-  void RegisterDataTypes() override {}
+  void RegisterDataTypes(sync_driver::SyncClient* sync_client) override {}
   sync_driver::DataTypeManager* CreateDataTypeManager(
       const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
           debug_info_listener,
diff --git a/components/sync_driver/shared_change_processor_unittest.cc b/components/sync_driver/shared_change_processor_unittest.cc
index b97ea36..a28d305 100644
--- a/components/sync_driver/shared_change_processor_unittest.cc
+++ b/components/sync_driver/shared_change_processor_unittest.cc
@@ -41,8 +41,7 @@
   ~TestSyncApiComponentFactory() override {}
 
   // SyncApiComponentFactory implementation.
-  void Initialize(sync_driver::SyncService* pss) override {}
-  void RegisterDataTypes() override {}
+  void RegisterDataTypes(sync_driver::SyncClient* sync_client) override {}
   sync_driver::DataTypeManager* CreateDataTypeManager(
       const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
           debug_info_listener,
diff --git a/components/sync_driver/sync_api_component_factory.h b/components/sync_driver/sync_api_component_factory.h
index c402cace4..44029c4 100644
--- a/components/sync_driver/sync_api_component_factory.h
+++ b/components/sync_driver/sync_api_component_factory.h
@@ -47,6 +47,7 @@
 class GenericChangeProcessor;
 class LocalDeviceInfoProvider;
 class SyncPrefs;
+class SyncClient;
 class SyncService;
 
 // This factory provides sync driver code with the model type specific sync/api
@@ -76,10 +77,8 @@
         : model_associator(ma), change_processor(cp) {}
   };
 
-  virtual void Initialize(sync_driver::SyncService* sync_service) = 0;
-
-  // Creates and registers enabled datatypes with internal SyncService.
-  virtual void RegisterDataTypes() = 0;
+  // Creates and registers enabled datatypes with the provided SyncClient.
+  virtual void RegisterDataTypes(sync_driver::SyncClient* sync_client) = 0;
 
   // Instantiates a new DataTypeManager with a SyncBackendHost, a list of data
   // type controllers and a DataTypeManagerObserver.  The return pointer is
diff --git a/components/sync_driver/sync_client.h b/components/sync_driver/sync_client.h
index e8e668d..a4788f7 100644
--- a/components/sync_driver/sync_client.h
+++ b/components/sync_driver/sync_client.h
@@ -48,6 +48,12 @@
 class SyncClient {
  public:
   SyncClient();
+  virtual ~SyncClient();
+
+  // Initializes the sync client with the specified sync service. This will also
+  // register data type controllers with |service| (via
+  // SyncApiComponentFactory::RegisterDataTypes).
+  virtual void Initialize(SyncService* service) = 0;
 
   // Returns the current SyncService instance.
   virtual SyncService* GetSyncService() = 0;
@@ -72,9 +78,6 @@
   // Returns the current SyncApiComponentFactory instance.
   virtual SyncApiComponentFactory* GetSyncApiComponentFactory() = 0;
 
- protected:
-  virtual ~SyncClient();
-
  private:
   DISALLOW_COPY_AND_ASSIGN(SyncClient);
 };
diff --git a/components/sync_driver/sync_service.h b/components/sync_driver/sync_service.h
index c90dcfc..4b2de8d6 100644
--- a/components/sync_driver/sync_service.h
+++ b/components/sync_driver/sync_service.h
@@ -149,11 +149,11 @@
   // superset of the active types (see GetActiveDataTypes()).
   virtual syncer::ModelTypeSet GetPreferredDataTypes() const = 0;
 
-  // Called when a user chooses which data types to sync as part of the sync
-  // setup wizard.  |sync_everything| represents whether they chose the
-  // "keep everything synced" option; if true, |chosen_types| will be ignored
-  // and all data types will be synced.  |sync_everything| means "sync all
-  // current and future data types."
+  // Called when a user chooses which data types to sync. |sync_everything|
+  // represents whether they chose the "keep everything synced" option; if
+  // true, |chosen_types| will be ignored and all data types will be synced.
+  // |sync_everything| means "sync all current and future data types."
+  // |chosen_types| must be a subset of syncer::UserSelectableTypes().
   virtual void OnUserChoseDatatypes(bool sync_everything,
                                     syncer::ModelTypeSet chosen_types) = 0;
 
diff --git a/components/test/DEPS b/components/test/DEPS
index 7bd6a586..640fa0a 100644
--- a/components/test/DEPS
+++ b/components/test/DEPS
@@ -5,7 +5,6 @@
   "+components/policy/core/browser/android/component_jni_registrar.h",
   "+components/safe_json/android/component_jni_registrar.h",
   "+components/signin/core/browser/android/component_jni_registrar.h",
-  "+content/browser/android/browser_jni_registrar.h",
   "+content/public/android/java/src/org/chromium/content/browser",
   "+content/public/app/content_jni_onload.h",
   "+content/public/app/content_main.h",
@@ -17,7 +16,6 @@
   "+content/shell/app/shell_main_delegate.h",
   "+jni",
   "+media/base/media_switches.h",
-  "+net/android/net_jni_registrar.h",
   "+ui/android/java/src/org/chromium/ui/base",
   "+ui/base/android/ui_base_jni_registrar.h",
   "+ui/base/resource/resource_bundle.h",
diff --git a/components/test/run_all_unittests.cc b/components/test/run_all_unittests.cc
index ef7d826..d04085e 100644
--- a/components/test/run_all_unittests.cc
+++ b/components/test/run_all_unittests.cc
@@ -26,8 +26,6 @@
 #include "components/policy/core/browser/android/component_jni_registrar.h"
 #include "components/safe_json/android/component_jni_registrar.h"
 #include "components/signin/core/browser/android/component_jni_registrar.h"
-#include "content/browser/android/browser_jni_registrar.h"
-#include "net/android/net_jni_registrar.h"
 #include "ui/base/android/ui_base_jni_registrar.h"
 #include "ui/gfx/android/gfx_jni_registrar.h"
 #endif
@@ -59,8 +57,6 @@
     ASSERT_TRUE(policy::android::RegisterPolicy(env));
     ASSERT_TRUE(safe_json::android::RegisterSafeJsonJni(env));
     ASSERT_TRUE(signin::android::RegisterSigninJni(env));
-    ASSERT_TRUE(net::android::RegisterJni(env));
-    ASSERT_TRUE(content::android::RegisterBrowserJni(env));
 #endif
 
     ui::RegisterPathProvider();
diff --git a/components/test_runner/web_test_proxy.cc b/components/test_runner/web_test_proxy.cc
index aa72173..1dc3bf2 100644
--- a/components/test_runner/web_test_proxy.cc
+++ b/components/test_runner/web_test_proxy.cc
@@ -819,6 +819,9 @@
     case blink::WebAXEventHide:
       event_name = "Hide";
       break;
+    case blink::WebAXEventHover:
+      event_name = "Hover";
+      break;
     case blink::WebAXEventInvalidStatusChanged:
       event_name = "InvalidStatusChanged";
       break;
diff --git a/components/translate/content/renderer/translate_helper.cc b/components/translate/content/renderer/translate_helper.cc
index 44082b3..568ecf0 100644
--- a/components/translate/content/renderer/translate_helper.cc
+++ b/components/translate/content/renderer/translate_helper.cc
@@ -33,8 +33,6 @@
 #include "third_party/WebKit/public/web/WebNode.h"
 #include "third_party/WebKit/public/web/WebNodeList.h"
 #include "third_party/WebKit/public/web/WebScriptSource.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/WebKit/public/web/WebWidget.h"
 #include "url/gurl.h"
 #include "v8/include/v8.h"
 
@@ -48,7 +46,6 @@
 using blink::WebSecurityOrigin;
 using blink::WebString;
 using blink::WebVector;
-using blink::WebView;
 
 namespace {
 
diff --git a/components/translate/core/common/translate_util.cc b/components/translate/core/common/translate_util.cc
index 37d6a3e..6cb6d14 100644
--- a/components/translate/core/common/translate_util.cc
+++ b/components/translate/core/common/translate_util.cc
@@ -46,7 +46,8 @@
 // are different to be exact.
 //
 // If this table is updated, please sync this with the synonym table in
-// chrome/browser/resources/options/language_options.js
+// chrome/browser/resources/options/language_options.js and
+// chrome/browser/resources/settings/languages_page/languages.js.
 const LanguageCodePair kLanguageCodeSimilitudes[] = {
   {"no", "nb"},
   {"tl", "fil"},
@@ -56,7 +57,8 @@
 // codes are used, so we must see them as synonyms.
 //
 // If this table is updated, please sync this with the synonym table in
-// chrome/browser/resources/options/language_options.js
+// chrome/browser/resources/options/language_options.js and
+// chrome/browser/resources/settings/languages_page/languages.js.
 const LanguageCodePair kLanguageCodeSynonyms[] = {
   {"iw", "he"},
   {"jw", "jv"},
@@ -66,7 +68,8 @@
 // Translate.
 //
 // If this table is updated, please sync this with the synonym table in
-// chrome/browser/resources/options/language_options.js
+// chrome/browser/resources/options/language_options.js and
+// chrome/browser/resources/settings/languages_page/languages.js.
 const LanguageCodePair kLanguageCodeChineseCompatiblePairs[] = {
   {"zh-TW", "zh-HK"},
   {"zh-TW", "zh-MO"},
diff --git a/components/user_manager/user_manager.h b/components/user_manager/user_manager.h
index 105125b..24b8c9a 100644
--- a/components/user_manager/user_manager.h
+++ b/components/user_manager/user_manager.h
@@ -359,6 +359,11 @@
                                        const std::string& path,
                                        const int in_value) = 0;
 
+  // Returns true if user's canonical email was found.
+  // Returns it in |out_email|.
+  virtual bool GetKnownUserCanonicalEmail(const UserID& user_id,
+                                          std::string* out_email) = 0;
+
   // Updates |gaia_id| for user with |user_id|.
   // TODO(antrim): Update this once UserID contains GAIA ID.
   virtual void UpdateGaiaID(const UserID& user_id,
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc
index 3eee72a..3bcb61c2 100644
--- a/components/user_manager/user_manager_base.cc
+++ b/components/user_manager/user_manager_base.cc
@@ -1145,6 +1145,11 @@
   UpdateKnownUserPrefs(user_id, dict, false);
 }
 
+bool UserManagerBase::GetKnownUserCanonicalEmail(const UserID& user_id,
+                                                 std::string* out_email) {
+  return GetKnownUserStringPref(user_id, kCanonicalEmail, out_email);
+}
+
 void UserManagerBase::UpdateGaiaID(const UserID& user_id,
                                    const std::string& gaia_id) {
   SetKnownUserStringPref(user_id, kGAIAIdKey, gaia_id);
diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h
index a89dcc1c..a5f5f8f 100644
--- a/components/user_manager/user_manager_base.h
+++ b/components/user_manager/user_manager_base.h
@@ -129,6 +129,8 @@
   void SetKnownUserIntegerPref(const UserID& user_id,
                                const std::string& path,
                                const int in_value) override;
+  bool GetKnownUserCanonicalEmail(const UserID& user_id,
+                                  std::string* out_email) override;
   void UpdateGaiaID(const UserID& user_id, const std::string& gaia_id) override;
   bool FindGaiaID(const UserID& user_id, std::string* out_value) override;
   void UpdateUsingSAML(const std::string& user_id,
diff --git a/components/variations/proto/study.proto b/components/variations/proto/study.proto
index d86a362..25ff116 100644
--- a/components/variations/proto/study.proto
+++ b/components/variations/proto/study.proto
@@ -44,7 +44,7 @@
 
   // An experiment within the study.
   //
-  // Next tag: 11
+  // Next tag: 12
   message Experiment {
     // A named parameter value for this experiment.
     //
@@ -79,10 +79,44 @@
     // Optional id used to uniquely identify this experiment for Chrome Sync.
     optional uint64 chrome_sync_experiment_id = 10;
 
+    // Specifies the feature association parameters for this experiment group.
+    //
+    // Next tag: 5
+    message FeatureAssociation {
+      // Optional list of features to enable when this experiment is selected.
+      // Command-line overrides take precedence over this setting. No feature
+      // listed here should exist in the |disable_feature| list.
+      repeated string enable_feature = 1;
+
+      // Optional list of features to disable when this experiment is selected.
+      // Command-line overrides take precedence over this setting. No feature
+      // listed here should exist in the |enable_feature| list.
+      repeated string disable_feature = 2;
+
+      // Similar to |forcing_flag|, this is an optional name of a feature which
+      // will cause this experiment to be activated, if that feature is enabled
+      // from the command-line. Experiment with this set are not eligible for
+      // selection via a random dice roll.
+      // Mutually exclusive with |forcing_flag|, |forcing_feature_off| or
+      // having a non-zero |probability_weight|.
+      optional string forcing_feature_on = 3;
+
+      // Similar to |forcing_flag|, this is an optional name of a feature which
+      // will cause this experiment to be activated, if that feature is disabled
+      // from the command-line. Experiment with this set are not eligible for
+      // selection via a random dice roll.
+      // Mutually exclusive with |forcing_flag|, |forcing_feature_on| or having
+      // a non-zero |probability_weight|.
+      optional string forcing_feature_off = 4;
+    }
+    optional FeatureAssociation feature_association = 11;
+
     // Optional name of a Chrome flag that, when present, causes this experiment
     // to be forced. If the forcing_flag field is set, users will not be
     // assigned to this experiment unless that flag is present in Chrome's
     // command line.
+    // Mutually exclusive with |forcing_feature_on|, |forcing_feature_off| or
+    // having a non-zero |probability_weight|.
     optional string forcing_flag = 5;
 
     // Parameter values for this experiment.
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc
index e0f9a010..20ba860 100644
--- a/components/variations/service/variations_service.cc
+++ b/components/variations/service/variations_service.cc
@@ -223,7 +223,7 @@
 VariationsService::~VariationsService() {
 }
 
-bool VariationsService::CreateTrialsFromSeed() {
+bool VariationsService::CreateTrialsFromSeed(base::FeatureList* feature_list) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   create_trials_from_seed_called_ = true;
@@ -252,7 +252,8 @@
       GetCurrentFormFactor(), GetHardwareClass(), latest_country,
       LoadPermanentConsistencyCountry(current_version, latest_country),
       base::Bind(&UIStringOverrider::OverrideUIString,
-                 base::Unretained(&ui_string_overrider_)));
+                 base::Unretained(&ui_string_overrider_)),
+      feature_list);
 
   const base::Time now = base::Time::Now();
 
@@ -706,8 +707,8 @@
   std::string stored_country;
 
   // Determine if the saved pref value is present and valid.
-  const bool is_pref_present = list_value && !list_value->empty();
-  const bool is_pref_valid = is_pref_present && list_value->GetSize() == 2 &&
+  const bool is_pref_empty = list_value->empty();
+  const bool is_pref_valid = list_value->GetSize() == 2 &&
                              list_value->GetString(0, &stored_version_string) &&
                              list_value->GetString(1, &stored_country) &&
                              base::Version(stored_version_string).IsValid();
@@ -716,14 +717,15 @@
   const bool does_version_match =
       is_pref_valid && version.Equals(base::Version(stored_version_string));
 
-  // Determine if the country in the saved pref matches the country in |seed|.
+  // Determine if the country in the saved pref matches the country in
+  // |latest_country|.
   const bool does_country_match = is_pref_valid && !latest_country.empty() &&
                                   stored_country == latest_country;
 
   // Record a histogram for how the saved pref value compares to the current
   // version and the country code in the variations seed.
   LoadPermanentConsistencyCountryResult result;
-  if (!is_pref_present) {
+  if (is_pref_empty) {
     result = !latest_country.empty() ? LOAD_COUNTRY_NO_PREF_HAS_SEED
                                      : LOAD_COUNTRY_NO_PREF_NO_SEED;
   } else if (!is_pref_valid) {
@@ -744,7 +746,7 @@
 
   // Use the stored country if one is available and was fetched since the last
   // time Chrome was updated.
-  if (is_pref_present && does_version_match)
+  if (does_version_match)
     return stored_country;
 
   if (latest_country.empty()) {
@@ -766,4 +768,16 @@
   return latest_country;
 }
 
+std::string VariationsService::GetStoredPermanentCountry() {
+  const base::ListValue* list_value =
+      local_state_->GetList(prefs::kVariationsPermanentConsistencyCountry);
+  std::string stored_country;
+
+  if (list_value->GetSize() == 2) {
+    list_value->GetString(1, &stored_country);
+  }
+
+  return stored_country;
+}
+
 }  // namespace variations
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h
index def6124..90f7c97 100644
--- a/components/variations/service/variations_service.h
+++ b/components/variations/service/variations_service.h
@@ -28,6 +28,7 @@
 class PrefRegistrySimple;
 
 namespace base {
+class FeatureList;
 class Version;
 }
 
@@ -72,10 +73,12 @@
 
   ~VariationsService() override;
 
-  // Creates field trials based on Variations Seed loaded from local prefs. If
-  // there is a problem loading the seed data, all trials specified by the seed
-  // may not be created.
-  bool CreateTrialsFromSeed();
+  // Creates field trials based on the variations seed loaded from local state.
+  // If there is a problem loading the seed data, all trials specified by the
+  // seed may not be created. Some field trials are configured to override or
+  // associate with (for reporting) specific features. These associations are
+  // registered with |feature_list|.
+  bool CreateTrialsFromSeed(base::FeatureList* feature_list);
 
   // Should be called before startup of the main message loop.
   void PerformPreMainMessageLoopStartup();
@@ -113,6 +116,10 @@
   GURL GetVariationsServerURL(PrefService* local_prefs,
                               const std::string& restrict_mode_override);
 
+  // Returns the permanent country code stored for this client. Country code is
+  // in the format of lowercase ISO 3166-1 alpha-2. Example: us, br, in
+  std::string GetStoredPermanentCountry();
+
   // Exposed for testing.
   static std::string GetDefaultVariationsServerURLForTesting();
 
diff --git a/components/variations/variations_seed_processor.cc b/components/variations/variations_seed_processor.cc
index 169ac63..8acfa88 100644
--- a/components/variations/variations_seed_processor.cc
+++ b/components/variations/variations_seed_processor.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/variations/processed_study.h"
@@ -79,6 +80,72 @@
   }
 }
 
+// Forces the specified |experiment| to be enabled in |study|.
+void ForceExperimentState(
+    const Study& study,
+    const Study_Experiment& experiment,
+    const VariationsSeedProcessor::UIStringOverrideCallback& override_callback,
+    base::FieldTrial* trial) {
+  RegisterExperimentParams(study, experiment);
+  RegisterVariationIds(experiment, study.name());
+  if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) {
+    trial->group();
+    // UI Strings can only be overridden from ACTIVATION_AUTO experiments.
+    ApplyUIStringOverrides(experiment, override_callback);
+  }
+}
+
+// Registers feature overrides for the chosen experiment in the specified study.
+void RegisterFeatureOverrides(const ProcessedStudy& processed_study,
+                              base::FieldTrial* trial,
+                              base::FeatureList* feature_list) {
+  const std::string& group_name = trial->GetGroupNameWithoutActivation();
+  int experiment_index = processed_study.GetExperimentIndexByName(group_name);
+  // The field trial was defined from |study|, so the active experiment's name
+  // must be in the |study|.
+  DCHECK_NE(-1, experiment_index);
+
+  const Study_Experiment& experiment =
+      processed_study.study()->experiment(experiment_index);
+
+  // Process all the features to enable.
+  int feature_count = experiment.feature_association().enable_feature_size();
+  for (int i = 0; i < feature_count; ++i) {
+    feature_list->RegisterFieldTrialOverride(
+        experiment.feature_association().enable_feature(i),
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
+  }
+
+  // Process all the features to disable.
+  feature_count = experiment.feature_association().disable_feature_size();
+  for (int i = 0; i < feature_count; ++i) {
+    feature_list->RegisterFieldTrialOverride(
+        experiment.feature_association().disable_feature(i),
+        base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
+  }
+}
+
+// Checks if |experiment| is associated with a forcing flag or feature and if it
+// is, returns whether it should be forced enabled based on the |command_line|
+// or |feature_list| state.
+bool ShouldForceExperiment(const Study_Experiment& experiment,
+                           const base::CommandLine& command_line,
+                           const base::FeatureList& feature_list) {
+  if (experiment.feature_association().has_forcing_feature_on()) {
+    return feature_list.IsFeatureOverriddenFromCommandLine(
+        experiment.feature_association().forcing_feature_on(),
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE);
+  }
+  if (experiment.feature_association().has_forcing_feature_off()) {
+    return feature_list.IsFeatureOverriddenFromCommandLine(
+        experiment.feature_association().forcing_feature_off(),
+        base::FeatureList::OVERRIDE_DISABLE_FEATURE);
+  }
+  if (experiment.has_forcing_flag())
+    return command_line.HasSwitch(experiment.forcing_flag());
+  return false;
+}
+
 }  // namespace
 
 VariationsSeedProcessor::VariationsSeedProcessor() {
@@ -97,7 +164,8 @@
     const std::string& hardware_class,
     const std::string& session_consistency_country,
     const std::string& permanent_consistency_country,
-    const UIStringOverrideCallback& override_callback) {
+    const UIStringOverrideCallback& override_callback,
+    base::FeatureList* feature_list) {
   std::vector<ProcessedStudy> filtered_studies;
   FilterAndValidateStudies(seed, locale, reference_date, version, channel,
                            form_factor, hardware_class,
@@ -105,12 +173,13 @@
                            permanent_consistency_country, &filtered_studies);
 
   for (size_t i = 0; i < filtered_studies.size(); ++i)
-    CreateTrialFromStudy(filtered_studies[i], override_callback);
+    CreateTrialFromStudy(filtered_studies[i], override_callback, feature_list);
 }
 
 void VariationsSeedProcessor::CreateTrialFromStudy(
     const ProcessedStudy& processed_study,
-    const UIStringOverrideCallback& override_callback) {
+    const UIStringOverrideCallback& override_callback,
+    base::FeatureList* feature_list) {
   const Study& study = *processed_study.study();
 
   // Check if any experiments need to be forced due to a command line
@@ -118,28 +187,26 @@
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   for (int i = 0; i < study.experiment_size(); ++i) {
     const Study_Experiment& experiment = study.experiment(i);
-    if (experiment.has_forcing_flag() &&
-        command_line->HasSwitch(experiment.forcing_flag())) {
-      scoped_refptr<base::FieldTrial> trial(
-          base::FieldTrialList::CreateFieldTrial(study.name(),
-                                                 experiment.name()));
-      // If |trial| is NULL, then there might already be a trial forced to a
+    if (ShouldForceExperiment(experiment, *command_line, *feature_list)) {
+      base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
+          study.name(), experiment.name());
+      // If |trial| is null, then there might already be a trial forced to a
       // different group (e.g. via --force-fieldtrials). Break out of the loop,
       // but don't return, so that variation ids and params for the selected
       // group will still be picked up.
-      if (!trial.get())
+      if (!trial)
         break;
 
-      RegisterExperimentParams(study, experiment);
-      RegisterVariationIds(experiment, study.name());
-      if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) {
-        trial->group();
-        // UI Strings can only be overridden from ACTIVATION_AUTO experiments.
-        ApplyUIStringOverrides(experiment, override_callback);
+      if (experiment.feature_association().has_forcing_feature_on()) {
+        feature_list->AssociateReportingFieldTrial(
+            experiment.feature_association().forcing_feature_on(),
+            base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
+      } else if (experiment.feature_association().has_forcing_feature_off()) {
+        feature_list->AssociateReportingFieldTrial(
+            experiment.feature_association().forcing_feature_off(),
+            base::FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
       }
-
-      DVLOG(1) << "Trial " << study.name() << " forced by flag: "
-               << experiment.forcing_flag();
+      ForceExperimentState(study, experiment, override_callback, trial);
       return;
     }
   }
@@ -169,14 +236,18 @@
           randomization_seed, NULL));
 
   bool has_overrides = false;
+  bool enables_or_disables_features = false;
   for (int i = 0; i < study.experiment_size(); ++i) {
     const Study_Experiment& experiment = study.experiment(i);
     RegisterExperimentParams(study, experiment);
 
     // Groups with forcing flags have probability 0 and will never be selected.
     // Therefore, there's no need to add them to the field trial.
-    if (experiment.has_forcing_flag())
+    if (experiment.has_forcing_flag() ||
+        experiment.feature_association().has_forcing_feature_on() ||
+        experiment.feature_association().has_forcing_feature_off()) {
       continue;
+    }
 
     if (experiment.name() != study.default_experiment_name())
       trial->AppendGroup(experiment.name(), experiment.probability_weight());
@@ -184,9 +255,17 @@
     RegisterVariationIds(experiment, study.name());
 
     has_overrides = has_overrides || experiment.override_ui_string_size() > 0;
+    if (experiment.feature_association().enable_feature_size() != 0 ||
+        experiment.feature_association().disable_feature_size() != 0) {
+      enables_or_disables_features = true;
+    }
   }
 
   trial->SetForced();
+
+  if (enables_or_disables_features)
+    RegisterFeatureOverrides(processed_study, trial.get(), feature_list);
+
   if (processed_study.is_expired()) {
     trial->Disable();
   } else if (study.activation_type() == Study_ActivationType_ACTIVATION_AUTO) {
diff --git a/components/variations/variations_seed_processor.h b/components/variations/variations_seed_processor.h
index edbe059..f7199be 100644
--- a/components/variations/variations_seed_processor.h
+++ b/components/variations/variations_seed_processor.h
@@ -18,6 +18,10 @@
 #include "components/variations/proto/study.pb.h"
 #include "components/variations/proto/variations_seed.pb.h"
 
+namespace base {
+class FeatureList;
+}
+
 namespace variations {
 
 class ProcessedStudy;
@@ -42,7 +46,8 @@
                             const std::string& hardware_class,
                             const std::string& session_consistency_country,
                             const std::string& permanent_consistency_country,
-                            const UIStringOverrideCallback& override_callback);
+                            const UIStringOverrideCallback& override_callback,
+                            base::FeatureList* feature_list);
 
  private:
   friend class VariationsSeedProcessorTest;
@@ -71,7 +76,8 @@
   // Creates and registers a field trial from the |processed_study| data.
   // Disables the trial if |processed_study.is_expired| is true.
   void CreateTrialFromStudy(const ProcessedStudy& processed_study,
-                            const UIStringOverrideCallback& override_callback);
+                            const UIStringOverrideCallback& override_callback,
+                            base::FeatureList* feature_list);
 
   DISALLOW_COPY_AND_ASSIGN(VariationsSeedProcessor);
 };
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc
index f246df5..89cab1b 100644
--- a/components/variations/variations_seed_processor_unittest.cc
+++ b/components/variations/variations_seed_processor_unittest.cc
@@ -9,7 +9,10 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/format_macros.h"
 #include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/variations/processed_study.h"
 #include "components/variations/variations_associated_data.h"
@@ -105,19 +108,27 @@
     // process singletons.
     testing::ClearAllVariationIDs();
     testing::ClearAllVariationParams();
+
+    base::FeatureList::ClearInstanceForTesting();
   }
 
   bool CreateTrialFromStudy(const Study* study) {
+    return CreateTrialFromStudyWithFeatureList(study, &feature_list_);
+  }
+
+  bool CreateTrialFromStudyWithFeatureList(const Study* study,
+                                           base::FeatureList* feature_list) {
     ProcessedStudy processed_study;
     if (processed_study.Init(study, false)) {
       VariationsSeedProcessor().CreateTrialFromStudy(
-          processed_study, override_callback_.callback());
+          processed_study, override_callback_.callback(), feature_list);
       return true;
     }
     return false;
   }
 
  protected:
+  base::FeatureList feature_list_;
   TestOverrideStringCallback override_callback_;
 
  private:
@@ -215,23 +226,27 @@
   // Check that adding [expired, non-expired] activates the non-expired one.
   ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
   {
+    base::FeatureList feature_list;
     base::FieldTrialList field_trial_list(NULL);
     study1->set_expiry_date(TimeToProtoTime(year_ago));
     seed_processor.CreateTrialsFromSeed(
         seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE,
-        Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback());
+        Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(),
+        &feature_list);
     EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
   }
 
   // Check that adding [non-expired, expired] activates the non-expired one.
   ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
   {
+    base::FeatureList feature_list;
     base::FieldTrialList field_trial_list(NULL);
     study1->clear_expiry_date();
     study2->set_expiry_date(TimeToProtoTime(year_ago));
     seed_processor.CreateTrialsFromSeed(
         seed, "en-CA", base::Time::Now(), version, Study_Channel_STABLE,
-        Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback());
+        Study_FormFactor_DESKTOP, "", "", "", override_callback_.callback(),
+        &feature_list);
     EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
   }
 }
@@ -436,7 +451,7 @@
   seed_processor.CreateTrialsFromSeed(
       seed, "en-CA", base::Time::Now(), base::Version("20.0.0.0"),
       Study_Channel_STABLE, Study_FormFactor_DESKTOP, "", "", "",
-      override_callback_.callback());
+      override_callback_.callback(), &feature_list_);
 
   // Non-specified and ACTIVATION_EXPLICIT should not start active, but
   // ACTIVATION_AUTO should.
@@ -493,4 +508,200 @@
   EXPECT_EQ(kExperimentId, id);
 }
 
+TEST_F(VariationsSeedProcessorTest, FeatureEnabledOrDisableByTrial) {
+  struct base::Feature kFeatureOffByDefault {
+    "kOff", base::FEATURE_DISABLED_BY_DEFAULT
+  };
+  struct base::Feature kFeatureOnByDefault {
+    "kOn", base::FEATURE_ENABLED_BY_DEFAULT
+  };
+  struct base::Feature kUnrelatedFeature {
+    "kUnrelated", base::FEATURE_DISABLED_BY_DEFAULT
+  };
+
+  struct {
+    const char* enable_feature;
+    const char* disable_feature;
+    bool expected_feature_off_state;
+    bool expected_feature_on_state;
+  } test_cases[] = {
+      {nullptr, nullptr, false, true},
+      {kFeatureOnByDefault.name, nullptr, false, true},
+      {kFeatureOffByDefault.name, nullptr, true, true},
+      {nullptr, kFeatureOnByDefault.name, false, false},
+      {nullptr, kFeatureOffByDefault.name, false, true},
+  };
+
+  for (size_t i = 0; i < arraysize(test_cases); i++) {
+    const auto& test_case = test_cases[i];
+    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
+
+    base::FieldTrialList field_trial_list(NULL);
+    base::FeatureList::ClearInstanceForTesting();
+    scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+
+    Study study;
+    study.set_name("Study1");
+    study.set_default_experiment_name("B");
+    AddExperiment("B", 0, &study);
+
+    Study_Experiment* experiment = AddExperiment("A", 1, &study);
+    Study_Experiment_FeatureAssociation* association =
+        experiment->mutable_feature_association();
+    if (test_case.enable_feature)
+      association->add_enable_feature(test_case.enable_feature);
+    else if (test_case.disable_feature)
+      association->add_disable_feature(test_case.disable_feature);
+
+    EXPECT_TRUE(
+        CreateTrialFromStudyWithFeatureList(&study, feature_list.get()));
+    base::FeatureList::SetInstance(feature_list.Pass());
+
+    // |kUnrelatedFeature| should not be affected.
+    EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature));
+
+    // Before the associated feature is queried, the trial shouldn't be active.
+    EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name()));
+
+    EXPECT_EQ(test_case.expected_feature_off_state,
+              base::FeatureList::IsEnabled(kFeatureOffByDefault));
+    EXPECT_EQ(test_case.expected_feature_on_state,
+              base::FeatureList::IsEnabled(kFeatureOnByDefault));
+
+    // The field trial should get activated if it had a feature association.
+    const bool expected_field_trial_active =
+        test_case.enable_feature || test_case.disable_feature;
+    EXPECT_EQ(expected_field_trial_active,
+              base::FieldTrialList::IsTrialActive(study.name()));
+  }
+}
+
+TEST_F(VariationsSeedProcessorTest, FeatureAssociationAndForcing) {
+  struct base::Feature kFeatureOffByDefault {
+    "kFeatureOffByDefault", base::FEATURE_DISABLED_BY_DEFAULT
+  };
+  struct base::Feature kFeatureOnByDefault {
+    "kFeatureOnByDefault", base::FEATURE_ENABLED_BY_DEFAULT
+  };
+
+  enum OneHundredPercentGroup {
+    DEFAULT_GROUP,
+    ENABLE_GROUP,
+    DISABLE_GROUP,
+  };
+
+  const char kDefaultGroup[] = "Default";
+  const char kEnabledGroup[] = "Enabled";
+  const char kDisabledGroup[] = "Disabled";
+  const char kForcedOnGroup[] = "ForcedOn";
+  const char kForcedOffGroup[] = "ForcedOff";
+
+  struct {
+    const base::Feature& feature;
+    const char* enable_features_command_line;
+    const char* disable_features_command_line;
+    OneHundredPercentGroup one_hundred_percent_group;
+
+    const char* expected_group;
+    bool expected_feature_state;
+    bool expected_trial_activated;
+  } test_cases[] = {
+      // Check what happens without and command-line forcing flags - that the
+      // |one_hundred_percent_group| gets correctly selected and does the right
+      // thing w.r.t. to affecting the feature / activating the trial.
+      {kFeatureOffByDefault, "", "", DEFAULT_GROUP, kDefaultGroup, false,
+       false},
+      {kFeatureOffByDefault, "", "", ENABLE_GROUP, kEnabledGroup, true, true},
+      {kFeatureOffByDefault, "", "", DISABLE_GROUP, kDisabledGroup, false,
+       true},
+
+      // Do the same as above, but for kFeatureOnByDefault feature.
+      {kFeatureOnByDefault, "", "", DEFAULT_GROUP, kDefaultGroup, true, false},
+      {kFeatureOnByDefault, "", "", ENABLE_GROUP, kEnabledGroup, true, true},
+      {kFeatureOnByDefault, "", "", DISABLE_GROUP, kDisabledGroup, false, true},
+
+      // Test forcing each feature on and off through the command-line and that
+      // the correct associated experiment gets chosen.
+      {kFeatureOffByDefault, kFeatureOffByDefault.name, "", DEFAULT_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOffByDefault, "", kFeatureOffByDefault.name, DEFAULT_GROUP,
+       kForcedOffGroup, false, true},
+      {kFeatureOnByDefault, kFeatureOnByDefault.name, "", DEFAULT_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOnByDefault, "", kFeatureOnByDefault.name, DEFAULT_GROUP,
+       kForcedOffGroup, false, true},
+
+      // Check that even if a feature should be enabled or disabled based on the
+      // the experiment probability weights, the forcing flag association still
+      // takes precedence. This is 4 cases as above, but with different values
+      // for |one_hundred_percent_group|.
+      {kFeatureOffByDefault, kFeatureOffByDefault.name, "", ENABLE_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOffByDefault, "", kFeatureOffByDefault.name, ENABLE_GROUP,
+       kForcedOffGroup, false, true},
+      {kFeatureOnByDefault, kFeatureOnByDefault.name, "", ENABLE_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOnByDefault, "", kFeatureOnByDefault.name, ENABLE_GROUP,
+       kForcedOffGroup, false, true},
+      {kFeatureOffByDefault, kFeatureOffByDefault.name, "", DISABLE_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOffByDefault, "", kFeatureOffByDefault.name, DISABLE_GROUP,
+       kForcedOffGroup, false, true},
+      {kFeatureOnByDefault, kFeatureOnByDefault.name, "", DISABLE_GROUP,
+       kForcedOnGroup, true, true},
+      {kFeatureOnByDefault, "", kFeatureOnByDefault.name, DISABLE_GROUP,
+       kForcedOffGroup, false, true},
+  };
+
+  for (size_t i = 0; i < arraysize(test_cases); i++) {
+    const auto& test_case = test_cases[i];
+    const int group = test_case.one_hundred_percent_group;
+    SCOPED_TRACE(base::StringPrintf(
+        "Test[%" PRIuS "]: %s [%s] [%s] %d", i, test_case.feature.name,
+        test_case.enable_features_command_line,
+        test_case.disable_features_command_line, static_cast<int>(group)));
+
+    base::FieldTrialList field_trial_list(NULL);
+    base::FeatureList::ClearInstanceForTesting();
+    scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    feature_list->InitializeFromCommandLine(
+        test_case.enable_features_command_line,
+        test_case.disable_features_command_line);
+
+    Study study;
+    study.set_name("Study1");
+    study.set_default_experiment_name("Default");
+    AddExperiment(kDefaultGroup, group == DEFAULT_GROUP ? 1 : 0, &study);
+
+    Study_Experiment* feature_enable =
+        AddExperiment(kEnabledGroup, group == ENABLE_GROUP ? 1 : 0, &study);
+    feature_enable->mutable_feature_association()->add_enable_feature(
+        test_case.feature.name);
+
+    Study_Experiment* feature_disable =
+        AddExperiment(kDisabledGroup, group == DISABLE_GROUP ? 1 : 0, &study);
+    feature_disable->mutable_feature_association()->add_disable_feature(
+        test_case.feature.name);
+
+    AddExperiment(kForcedOnGroup, 0, &study)
+        ->mutable_feature_association()
+        ->set_forcing_feature_on(test_case.feature.name);
+    AddExperiment(kForcedOffGroup, 0, &study)
+        ->mutable_feature_association()
+        ->set_forcing_feature_off(test_case.feature.name);
+
+    EXPECT_TRUE(
+        CreateTrialFromStudyWithFeatureList(&study, feature_list.get()));
+    base::FeatureList::SetInstance(feature_list.Pass());
+
+    // Trial should not be activated initially, but later might get activated
+    // depending on the expected values.
+    EXPECT_FALSE(base::FieldTrialList::IsTrialActive(study.name()));
+    EXPECT_EQ(test_case.expected_feature_state,
+              base::FeatureList::IsEnabled(test_case.feature));
+    EXPECT_EQ(test_case.expected_trial_activated,
+              base::FieldTrialList::IsTrialActive(study.name()));
+  }
+}
+
 }  // namespace variations
diff --git a/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java b/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java
index d2c0f31..33592802 100644
--- a/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java
+++ b/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java
@@ -117,8 +117,8 @@
     }
 
     private void measure(RenderCoordinates coordinates) {
-        mPopup.setWindowLayoutMode(
-                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+        mPopup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
         mPopup.getContentView().setLayoutParams(
                 new RelativeLayout.LayoutParams(
                         RelativeLayout.LayoutParams.WRAP_CONTENT,
diff --git a/components/web_view/BUILD.gn b/components/web_view/BUILD.gn
index ec65cfe..1f5c100a 100644
--- a/components/web_view/BUILD.gn
+++ b/components/web_view/BUILD.gn
@@ -112,9 +112,9 @@
     ":test_support",
     "//base",
     "//base/test:test_config",
-    "//components/mus/public/cpp",
     "//components/mus/public/cpp/tests:test_support",
     "//components/mus/public/interfaces",
+    "//components/mus/public/cpp",
     "//components/web_view/public/cpp",
     "//components/web_view/public/interfaces",
     "//mojo/application/public/cpp:sources",
@@ -127,6 +127,6 @@
 
   data_deps = [
     ":web_view",
-    "//components/mus",
+    "//components/mus/vm:lib",
   ]
 }
diff --git a/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
new file mode 100644
index 0000000..fe92e3b
--- /dev/null
+++ b/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -0,0 +1,107 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
+#include "ui/events/event_processor.h"
+#include "ui/events/event_utils.h"
+
+namespace content {
+
+class TouchAccessibilityBrowserTest : public ContentBrowserTest {
+ public:
+  TouchAccessibilityBrowserTest() {}
+
+  DISALLOW_COPY_AND_ASSIGN(TouchAccessibilityBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(TouchAccessibilityBrowserTest,
+                       TouchExplorationSendsHoverEvents) {
+  // Create HTML with a 7 x 5 table, each exactly 50 x 50 pixels.
+  std::string html_url =
+      "data:text/html,"
+      "<style>"
+      "  body { margin: 0; }"
+      "  table { border-spacing: 0; border-collapse: collapse; }"
+      "  td { width: 50px; height: 50px; padding: 0; }"
+      "</style>"
+      "<body>"
+      "<table>";
+  int cell = 0;
+  for (int row = 0; row < 5; ++row) {
+    html_url += "<tr>";
+    for (int col = 0; col < 7; ++col) {
+      html_url += "<td>" + base::IntToString(cell) + "</td>";
+      ++cell;
+    }
+    html_url += "</tr>";
+  }
+  html_url += "</table></body>";
+
+  // Navigate to the url and load the accessibility tree.
+  AccessibilityNotificationWaiter waiter(
+      shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE);
+  GURL url(html_url);
+  NavigateToURL(shell(), url);
+  waiter.WaitForNotification();
+
+  // Get the BrowserAccessibilityManager.
+  WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+      shell()->web_contents());
+  BrowserAccessibilityManager* manager =
+      web_contents->GetRootBrowserAccessibilityManager();
+  ASSERT_NE(nullptr, manager);
+
+  // Loop over all of the cells in the table. For each one, send a simulated
+  // touch exploration event in the center of that cell, and assert that we
+  // get an accessibility hover event fired in the correct cell.
+  AccessibilityNotificationWaiter waiter2(
+      shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
+  aura::Window* window = web_contents->GetContentNativeView();
+  ui::EventProcessor* dispatcher = window->GetHost()->event_processor();
+  for (int row = 0; row < 5; ++row) {
+    for (int col = 0; col < 7; ++col) {
+      std::string expected_cell_text = base::IntToString(row * 7 + col);
+      VLOG(1) << "Sending event in row " << row << " col " << col
+              << " with text " << expected_cell_text;
+
+      // Send a touch exploration event to the center of the particular grid
+      // cell. A touch exploration event is just a mouse move event with
+      // the ui::EF_TOUCH_ACCESSIBILITY flag set.
+      gfx::Rect bounds = window->GetBoundsInRootWindow();
+      gfx::PointF location(bounds.x() + 50 * col + 25,
+                           bounds.y() + 50 * row + 25);
+      int flags = ui::EF_TOUCH_ACCESSIBILITY;
+      scoped_ptr<ui::Event> mouse_move_event(new ui::MouseEvent(
+          ui::ET_MOUSE_MOVED, location, location, ui::EventTimeForNow(),
+          flags, 0));
+      ignore_result(dispatcher->OnEventFromSource(mouse_move_event.get()));
+
+      // Wait until we get a hover event in the expected grid cell.
+      // Tolerate additional events, keep looping until we get the expected one.
+      std::string cell_text;
+      do {
+        waiter2.WaitForNotification();
+        int target_id = waiter2.event_target_id();
+        BrowserAccessibility* hit = manager->GetFromID(target_id);
+        BrowserAccessibility* child = hit->PlatformGetChild(0);
+        ASSERT_NE(nullptr, child);
+        cell_text = child->GetData().GetStringAttribute(ui::AX_ATTR_VALUE);
+        VLOG(1) << "Got hover event in cell with text: " << cell_text;
+      } while (cell_text != expected_cell_text);
+    }
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/android/background_sync_network_observer_android.cc b/content/browser/android/background_sync_network_observer_android.cc
deleted file mode 100644
index 533fc36..0000000
--- a/content/browser/android/background_sync_network_observer_android.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/android/background_sync_network_observer_android.h"
-
-#include "jni/BackgroundSyncNetworkObserver_jni.h"
-
-namespace content {
-
-// static
-bool BackgroundSyncNetworkObserverAndroid::Observer::RegisterNetworkObserver(
-    JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-// static
-scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer>
-BackgroundSyncNetworkObserverAndroid::Observer::Create(
-    base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer> observer(
-      new BackgroundSyncNetworkObserverAndroid::Observer(callback));
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&BackgroundSyncNetworkObserverAndroid::Observer::Init,
-                 observer));
-  return observer;
-}
-
-void BackgroundSyncNetworkObserverAndroid::Observer::Init() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  // Attach a Java BackgroundSyncNetworkObserver object. Its lifetime will be
-  // scoped to the lifetime of this object.
-  JNIEnv* env = base::android::AttachCurrentThread();
-  base::android::ScopedJavaGlobalRef<jobject> obj(
-      Java_BackgroundSyncNetworkObserver_createObserver(
-          env, base::android::GetApplicationContext(),
-          reinterpret_cast<jlong>(this)));
-  j_observer_.Reset(obj);
-}
-
-BackgroundSyncNetworkObserverAndroid::Observer::~Observer() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  Java_BackgroundSyncNetworkObserver_removeObserver(
-      env, j_observer_.obj(), reinterpret_cast<jlong>(this));
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  j_observer_.Release();
-}
-
-void BackgroundSyncNetworkObserverAndroid::Observer::
-    NotifyConnectionTypeChanged(JNIEnv* env,
-                                jobject jcaller,
-                                jint new_connection_type) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(callback_,
-                 static_cast<net::NetworkChangeNotifier::ConnectionType>(
-                     new_connection_type)));
-}
-
-BackgroundSyncNetworkObserverAndroid::Observer::Observer(
-    base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback)
-    : callback_(callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-BackgroundSyncNetworkObserverAndroid::BackgroundSyncNetworkObserverAndroid(
-    const base::Closure& network_changed_callback)
-    : BackgroundSyncNetworkObserver(network_changed_callback),
-      weak_ptr_factory_(this) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  // Remove the observer attached by the NetworkObserver constructor
-  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-
-  observer_ = Observer::Create(
-      base::Bind(&BackgroundSyncNetworkObserverAndroid::OnNetworkChanged,
-                 weak_ptr_factory_.GetWeakPtr()));
-}
-
-BackgroundSyncNetworkObserverAndroid::~BackgroundSyncNetworkObserverAndroid() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-}  // namespace content
diff --git a/content/browser/android/background_sync_network_observer_android.h b/content/browser/android/background_sync_network_observer_android.h
deleted file mode 100644
index 49e8b0a..0000000
--- a/content/browser/android/background_sync_network_observer_android.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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_ANDROID_BACKGROUND_SYNC_NETWORK_OBSERVER_ANDROID_H_
-#define CONTENT_BROWSER_ANDROID_BACKGROUND_SYNC_NETWORK_OBSERVER_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/background_sync/background_sync_network_observer.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-// BackgroundSyncNetworkObserverAndroid is a specialized
-// BackgroundSyncNetworkObserver which is backed by a NetworkChangeNotifier
-// that listens for network events even when the browser is paused, unlike the
-// standard NetworkChangeNotifier. This ensures that sync events can be fired
-// even when the browser is backgrounded, and other network observers are
-// disabled.
-class BackgroundSyncNetworkObserverAndroid
-    : public BackgroundSyncNetworkObserver {
- public:
-  // Creates a BackgroundSyncNetworkObserver. |network_changed_callback| is
-  // called via PostMessage when the network connection changes.
-  BackgroundSyncNetworkObserverAndroid(
-      const base::Closure& network_changed_callback);
-
-  ~BackgroundSyncNetworkObserverAndroid() override;
-
-  // This class lives on the UI thread and mediates all access to the Java
-  // BackgroundSyncNetworkObserver, which it creates and owns. It is in turn
-  // owned by the BackgroundSyncNetworkObserverAndroid.
-  class Observer : public base::RefCountedThreadSafe<
-                       BackgroundSyncNetworkObserverAndroid::Observer,
-                       content::BrowserThread::DeleteOnUIThread> {
-   public:
-    static scoped_refptr<BackgroundSyncNetworkObserverAndroid::Observer> Create(
-        base::Callback<void(net::NetworkChangeNotifier::ConnectionType)>
-            callback);
-
-    static bool RegisterNetworkObserver(JNIEnv* env);
-
-    // Called from BackgroundSyncNetworkObserver.java over JNI whenever the
-    // connection type changes. This updates the current connection type seen by
-    // this class and calls the |network_changed_callback| provided to the
-    // constructor, on the IO thread, with the new connection type.
-    void NotifyConnectionTypeChanged(JNIEnv* env,
-                                     jobject jcaller,
-                                     jint new_connection_type);
-
-   private:
-    friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
-    friend class base::DeleteHelper<
-        BackgroundSyncNetworkObserverAndroid::Observer>;
-
-    Observer(base::Callback<void(net::NetworkChangeNotifier::ConnectionType)>
-                 callback);
-    void Init();
-    ~Observer();
-
-    // This callback is to be run on the IO thread whenever the connection type
-    // changes.
-    base::Callback<void(net::NetworkChangeNotifier::ConnectionType)> callback_;
-    base::android::ScopedJavaGlobalRef<jobject> j_observer_;
-
-    DISALLOW_COPY_AND_ASSIGN(Observer);
-  };
-
- private:
-  // Accessed on UI Thread
-  scoped_refptr<Observer> observer_;
-
-  base::WeakPtrFactory<BackgroundSyncNetworkObserverAndroid> weak_ptr_factory_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_ANDROID_BACKGROUND_SYNC_NETWORK_OBSERVER_ANDROID_H_
diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc
index bea2065..43adba8 100644
--- a/content/browser/android/browser_jni_registrar.cc
+++ b/content/browser/android/browser_jni_registrar.cc
@@ -9,7 +9,6 @@
 #include "content/browser/accessibility/browser_accessibility_android.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
 #include "content/browser/android/background_sync_launcher_android.h"
-#include "content/browser/android/background_sync_network_observer_android.h"
 #include "content/browser/android/browser_startup_controller.h"
 #include "content/browser/android/child_process_launcher_android.h"
 #include "content/browser/android/composited_touch_handle_drawable.h"
@@ -51,9 +50,6 @@
      content::AndroidLocationApiAdapter::RegisterGeolocationService},
     {"BackgroundSyncLauncherAndroid",
      content::BackgroundSyncLauncherAndroid::RegisterLauncher},
-    {"BackgroundSyncNetworkObserverAndroid",
-     content::BackgroundSyncNetworkObserverAndroid::Observer::
-         RegisterNetworkObserver},
     {"BrowserAccessibilityManager",
      content::RegisterBrowserAccessibilityManager},
     {"BrowserStartupController", content::RegisterBrowserStartupController},
diff --git a/content/browser/appcache/appcache_dispatcher_host.h b/content/browser/appcache/appcache_dispatcher_host.h
index c9c1cdd..30d2f86 100644
--- a/content/browser/appcache/appcache_dispatcher_host.h
+++ b/content/browser/appcache/appcache_dispatcher_host.h
@@ -19,8 +19,8 @@
 
 // Handles appcache related messages sent to the main browser process from
 // its child processes. There is a distinct host for each child process.
-// Messages are handled on the IO thread. The BrowserRenderProcessHost and
-// WorkerProcessHost create an instance and delegates calls to it.
+// Messages are handled on the IO thread. The RenderProcessHostImpl creates
+// an instance and delegates calls to it.
 class AppCacheDispatcherHost : public BrowserMessageFilter {
  public:
   AppCacheDispatcherHost(ChromeAppCacheService* appcache_service,
diff --git a/content/browser/appcache/appcache_response.h b/content/browser/appcache/appcache_response.h
index a4c87db..8d6c790 100644
--- a/content/browser/appcache/appcache_response.h
+++ b/content/browser/appcache/appcache_response.h
@@ -209,9 +209,8 @@
   // negative error code or the number of bytes written. The 'callback' is a
   // required parameter. The contents of 'info_buf' are not modified.
   // Should only be called where there is no Write operation in progress.
-  // (virtual for testing)
-  virtual void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
-                         const net::CompletionCallback& callback);
+  void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
+                 const net::CompletionCallback& callback);
 
   // Writes data to storage. Always returns the result of the write
   // asynchronously through the 'callback'. Returns the number of bytes written
@@ -221,10 +220,8 @@
   // the number of bytes written. The 'callback' is a required parameter.
   // The contents of 'buf' are not modified.
   // Should only be called where there is no Write operation in progress.
-  // (virtual for testing)
-  virtual void WriteData(net::IOBuffer* buf,
-                         int buf_len,
-                         const net::CompletionCallback& callback);
+  void WriteData(net::IOBuffer* buf, int buf_len,
+                 const net::CompletionCallback& callback);
 
   // Returns true if there is a write pending.
   bool IsWritePending() { return IsIOPending(); }
diff --git a/content/browser/background_sync/background_sync_browsertest.cc b/content/browser/background_sync/background_sync_browsertest.cc
index ae1ccc94..eb79df9 100644
--- a/content/browser/background_sync/background_sync_browsertest.cc
+++ b/content/browser/background_sync/background_sync_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
 #include "content/browser/background_sync/background_sync_manager.h"
-#include "content/browser/background_sync/background_sync_network_observer.h"
 #include "content/browser/background_sync/background_sync_registration_handle.h"
 #include "content/browser/background_sync/background_sync_status.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -93,15 +92,20 @@
                       callback));
 }
 
-}  // namespace
-
 class BackgroundSyncBrowserTest : public ContentBrowserTest {
  public:
   BackgroundSyncBrowserTest() {}
   ~BackgroundSyncBrowserTest() override {}
 
   void SetUp() override {
-    BackgroundSyncNetworkObserver::SetIgnoreNetworkChangeNotifierForTests(true);
+    NetworkChangeNotifier::SetTestNotificationsOnly(true);
+
+#if defined(OS_CHROMEOS)
+    // ChromeOS's NetworkChangeNotifier doesn't get created in
+    // content_browsertests, so make one now.
+    net::NetworkChangeNotifier::CreateMock();
+#endif
+
     ContentBrowserTest::SetUp();
   }
 
@@ -109,12 +113,6 @@
     shell_ = incognito ? CreateOffTheRecordBrowser() : shell();
   }
 
-  BackgroundSyncContext* GetSyncContextFromShell(Shell* shell) {
-    StoragePartition* storage = BrowserContext::GetDefaultStoragePartition(
-        shell_->web_contents()->GetBrowserContext());
-    return storage->GetBackgroundSyncContext();
-  }
-
   void SetUpCommandLine(base::CommandLine* command_line) override {
     // TODO(jkarlin): Remove this once background sync is no longer
     // experimental.
@@ -130,10 +128,10 @@
         base::FilePath(FILE_PATH_LITERAL("content/test/data/"))));
     ASSERT_TRUE(https_server_->Start());
 
-    SetIncognitoMode(false);
-
     SetOnline(true);
 
+    SetIncognitoMode(false);
+
     ASSERT_TRUE(LoadTestPage(kDefaultTestURL));
 
     ContentBrowserTest::SetUpOnMainThread();
@@ -150,13 +148,7 @@
                                                   script, result);
   }
 
-  // This runs asynchronously on the IO thread, but we don't need to wait for it
-  // to complete before running a background sync operation, since those also
-  // run on the IO thread.
   void SetOnline(bool online);
-  void SetOnlineOnIOThread(
-      const scoped_refptr<BackgroundSyncContext>& sync_context,
-      bool online);
 
   // Returns true if the one-shot sync with tag is currently pending. Fails
   // (assertion failure) if the tag isn't registered.
@@ -183,28 +175,14 @@
 };
 
 void BackgroundSyncBrowserTest::SetOnline(bool online) {
-  ASSERT_TRUE(shell_);
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(&BackgroundSyncBrowserTest::SetOnlineOnIOThread,
-                 base::Unretained(this),
-                 base::Unretained(GetSyncContextFromShell(shell_)), online));
-  base::RunLoop().RunUntilIdle();
-}
-
-void BackgroundSyncBrowserTest::SetOnlineOnIOThread(
-    const scoped_refptr<BackgroundSyncContext>& sync_context,
-    bool online) {
-  BackgroundSyncManager* sync_manager = sync_context->background_sync_manager();
-  BackgroundSyncNetworkObserver* network_observer =
-      sync_manager->GetNetworkObserverForTesting();
   if (online) {
-    network_observer->NotifyManagerIfNetworkChanged(
+    NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
         NetworkChangeNotifier::CONNECTION_WIFI);
   } else {
-    network_observer->NotifyManagerIfNetworkChanged(
+    NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
         NetworkChangeNotifier::CONNECTION_NONE);
   }
+  base::RunLoop().RunUntilIdle();
 }
 
 bool BackgroundSyncBrowserTest::OneShotPending(const std::string& tag) {
@@ -535,4 +513,6 @@
   EXPECT_TRUE(NotifyWhenDoneImmediateOneShot("ok - delay result: false"));
 }
 
+}  // namespace
+
 }  // namespace content
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index 080cd52..07ac7d8 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -7,6 +7,7 @@
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/metrics/field_trial.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "content/browser/background_sync/background_sync_metrics.h"
@@ -20,7 +21,6 @@
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/background_sync_launcher_android.h"
-#include "content/browser/android/background_sync_network_observer_android.h"
 #endif
 
 namespace content {
@@ -52,6 +52,12 @@
           base::Passed(scoped_ptr<BackgroundSyncRegistrationHandle>().Pass())));
 }
 
+bool ShouldDisableForFieldTrial() {
+  std::string experiment = base::FieldTrialList::FindFullName("BackgroundSync");
+  return base::StartsWith(experiment, "ExperimentDisable",
+                          base::CompareCase::INSENSITIVE_ASCII);
+}
+
 }  // namespace
 
 BackgroundSyncManager::BackgroundSyncRegistrations::
@@ -182,16 +188,17 @@
   return CreateRegistrationHandle(ref_registration->get());
 }
 
-void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id,
+void BackgroundSyncManager::OnRegistrationDeleted(int64 sw_registration_id,
                                                   const GURL& pattern) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Operations already in the queue will either fail when they write to storage
   // or return stale results based on registrations loaded in memory. This is
   // inconsequential since the service worker is gone.
-  op_scheduler_.ScheduleOperation(base::Bind(
-      &BackgroundSyncManager::OnRegistrationDeletedImpl,
-      weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion()));
+  op_scheduler_.ScheduleOperation(
+      base::Bind(&BackgroundSyncManager::OnRegistrationDeletedImpl,
+                 weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
+                 MakeEmptyCompletion()));
 }
 
 void BackgroundSyncManager::OnStorageWiped() {
@@ -214,15 +221,9 @@
 
   service_worker_context_->AddObserver(this);
 
-#if defined(OS_ANDROID)
-  network_observer_.reset(new BackgroundSyncNetworkObserverAndroid(
-      base::Bind(&BackgroundSyncManager::OnNetworkChanged,
-                 weak_ptr_factory_.GetWeakPtr())));
-#else
   network_observer_.reset(new BackgroundSyncNetworkObserver(
       base::Bind(&BackgroundSyncManager::OnNetworkChanged,
                  weak_ptr_factory_.GetWeakPtr())));
-#endif
   power_observer_.reset(new BackgroundSyncPowerObserver(base::Bind(
       &BackgroundSyncManager::OnPowerChanged, weak_ptr_factory_.GetWeakPtr())));
 }
@@ -246,6 +247,11 @@
     return;
   }
 
+  if (ShouldDisableForFieldTrial()) {
+    DisableAndClearManager(callback);
+    return;
+  }
+
   GetDataFromBackend(
       kBackgroundSyncUserDataKey,
       base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend,
@@ -340,6 +346,13 @@
     return;
   }
 
+  if (ShouldDisableForFieldTrial()) {
+    DisableAndClearManager(base::Bind(
+        callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+        base::Passed(scoped_ptr<BackgroundSyncRegistrationHandle>().Pass())));
+    return;
+  }
+
   if (options.tag.length() > kMaxTagLength) {
     BackgroundSyncMetrics::CountRegister(
         options.periodicity, registration_could_fire,
@@ -689,27 +702,27 @@
 
 void BackgroundSyncManager::Unregister(
     int64 sw_registration_id,
-    SyncPeriodicity periodicity,
     BackgroundSyncRegistrationHandle::HandleId handle_id,
     const StatusCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (disabled_) {
-    BackgroundSyncMetrics::CountUnregister(
-        periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
-    return;
-  }
-
   BackgroundSyncRegistration* registration =
       GetRegistrationForHandle(handle_id);
   DCHECK(registration);
 
+  if (disabled_) {
+    BackgroundSyncMetrics::CountUnregister(
+        registration->options()->periodicity,
+        BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
+    return;
+  }
+
   op_scheduler_.ScheduleOperation(base::Bind(
       &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
       sw_registration_id, RegistrationKey(*registration), registration->id(),
-      periodicity, MakeStatusCompletion(callback)));
+      registration->options()->periodicity, MakeStatusCompletion(callback)));
 }
 
 void BackgroundSyncManager::UnregisterImpl(
@@ -1196,13 +1209,13 @@
 }
 
 void BackgroundSyncManager::OnRegistrationDeletedImpl(
-    int64 registration_id,
+    int64 sw_registration_id,
     const base::Closure& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // The backend (ServiceWorkerStorage) will delete the data, so just delete the
   // memory representation here.
-  active_registrations_.erase(registration_id);
+  active_registrations_.erase(sw_registration_id);
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                 base::Bind(callback));
 }
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h
index 5080ba81..999b310 100644
--- a/content/browser/background_sync/background_sync_manager.h
+++ b/content/browser/background_sync/background_sync_manager.h
@@ -95,14 +95,10 @@
       BackgroundSyncRegistrationHandle::HandleId handle_id);
 
   // ServiceWorkerContextObserver overrides.
-  void OnRegistrationDeleted(int64 registration_id,
+  void OnRegistrationDeleted(int64 sw_registration_id,
                              const GURL& pattern) override;
   void OnStorageWiped() override;
 
-  BackgroundSyncNetworkObserver* GetNetworkObserverForTesting() {
-    return network_observer_.get();
-  }
-
  protected:
   // A registration might be referenced by the client longer than
   // the BackgroundSyncManager needs to keep track of it (e.g., the event has
@@ -238,7 +234,6 @@
   // BACKGROUND_SYNC_STATUS_NOT_FOUND if no match is found. Calls |callback|
   // with BACKGROUND_SYNC_STATUS_OK on success.
   void Unregister(int64 sw_registration_id,
-                  SyncPeriodicity periodicity,
                   BackgroundSyncRegistrationHandle::HandleId handle_id,
                   const StatusCallback& callback);
   void UnregisterImpl(
@@ -317,7 +312,7 @@
                                        int number_of_batched_sync_events);
 
   // OnRegistrationDeleted callbacks
-  void OnRegistrationDeletedImpl(int64 registration_id,
+  void OnRegistrationDeletedImpl(int64 sw_registration_id,
                                  const base::Closure& callback);
 
   // OnStorageWiped callbacks
@@ -356,8 +351,9 @@
   scoped_ptr<BackgroundSyncPowerObserver> power_observer_;
 
   // The registrations that clients have handles to.
-  IDMap<scoped_refptr<RefCountedRegistration>, IDMapOwnPointer>
-      registration_handle_ids_;
+  IDMap<scoped_refptr<RefCountedRegistration>,
+        IDMapOwnPointer,
+        BackgroundSyncRegistrationHandle::HandleId> registration_handle_ids_;
 
   base::WeakPtrFactory<BackgroundSyncManager> weak_ptr_factory_;
 
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index 3056594..4817b0c0 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -7,12 +7,13 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/metrics/field_trial.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_source.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/mock_entropy_provider.h"
 #include "base/thread_task_runner_handle.h"
-#include "content/browser/background_sync/background_sync_network_observer.h"
 #include "content/browser/background_sync/background_sync_registration_handle.h"
 #include "content/browser/background_sync/background_sync_status.h"
 #include "content/browser/browser_thread_impl.h"
@@ -232,9 +233,6 @@
   }
 
   void SetUp() override {
-    // Don't let the tests be confused by the real-world device connectivity
-    BackgroundSyncNetworkObserver::SetIgnoreNetworkChangeNotifierForTests(true);
-
     helper_.reset(
         new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId));
 
@@ -253,12 +251,6 @@
     RegisterServiceWorkers();
   }
 
-  void TearDown() override {
-    // Restore the network observer functionality for subsequent tests
-    BackgroundSyncNetworkObserver::SetIgnoreNetworkChangeNotifierForTests(
-        false);
-  }
-
   void RegisterServiceWorkers() {
     bool called_1 = false;
     bool called_2 = false;
@@ -312,12 +304,7 @@
   void SetNetwork(net::NetworkChangeNotifier::ConnectionType connection_type) {
     net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
         connection_type);
-    if (test_background_sync_manager_) {
-      BackgroundSyncNetworkObserver* network_observer =
-          test_background_sync_manager_->GetNetworkObserverForTesting();
-      network_observer->NotifyManagerIfNetworkChanged(connection_type);
-      base::RunLoop().RunUntilIdle();
-    }
+    base::RunLoop().RunUntilIdle();
   }
 
   void SetOnBatteryPower(bool on_battery_power) {
@@ -1628,4 +1615,26 @@
   EXPECT_FALSE(GetRegistration(sync_options_1_));
 }
 
+TEST_F(BackgroundSyncManagerTest, FieldTrialDisablesManager) {
+  EXPECT_TRUE(Register(sync_options_1_));
+
+  base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
+  base::FieldTrialList::CreateFieldTrial("BackgroundSync",
+                                         "ExperimentDisabled");
+
+  EXPECT_FALSE(Register(sync_options_2_));
+  EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+
+  // If the service worker is wiped and the manager is restarted, the manager
+  // should disable itself on init.
+  test_background_sync_manager_->set_corrupt_backend(false);
+  helper_->context()->ScheduleDeleteAndStartOver();
+  base::RunLoop().RunUntilIdle();
+
+  RegisterServiceWorkers();
+
+  EXPECT_FALSE(GetRegistrations(SYNC_ONE_SHOT));
+  EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
+}
+
 }  // namespace content
diff --git a/content/browser/background_sync/background_sync_network_observer.cc b/content/browser/background_sync/background_sync_network_observer.cc
index a08e7d8..1c6f2bd9 100644
--- a/content/browser/background_sync/background_sync_network_observer.cc
+++ b/content/browser/background_sync/background_sync_network_observer.cc
@@ -11,15 +11,6 @@
 
 namespace content {
 
-// static
-bool BackgroundSyncNetworkObserver::ignore_network_change_notifier_ = false;
-
-// static
-void BackgroundSyncNetworkObserver::SetIgnoreNetworkChangeNotifierForTests(
-    bool ignore) {
-  ignore_network_change_notifier_ = ignore;
-}
-
 BackgroundSyncNetworkObserver::BackgroundSyncNetworkObserver(
     const base::Closure& network_changed_callback)
     : connection_type_(net::NetworkChangeNotifier::GetConnectionType()),
@@ -56,25 +47,6 @@
   return false;
 }
 
-void BackgroundSyncNetworkObserver::OnNetworkChanged(
-    net::NetworkChangeNotifier::ConnectionType connection_type) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  if (ignore_network_change_notifier_)
-    return;
-  NotifyManagerIfNetworkChanged(connection_type);
-}
-
-void BackgroundSyncNetworkObserver::NotifyManagerIfNetworkChanged(
-    net::NetworkChangeNotifier::ConnectionType connection_type) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (connection_type == connection_type_)
-    return;
-
-  connection_type_ = connection_type;
-  NotifyNetworkChanged();
-}
-
 void BackgroundSyncNetworkObserver::NotifyNetworkChanged() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -82,4 +54,15 @@
                                                 network_changed_callback_);
 }
 
+void BackgroundSyncNetworkObserver::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType connection_type) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (connection_type == connection_type_)
+    return;
+
+  connection_type_ = connection_type;
+  NotifyNetworkChanged();
+}
+
 }  // namespace content
diff --git a/content/browser/background_sync/background_sync_network_observer.h b/content/browser/background_sync/background_sync_network_observer.h
index 4d47cc6..7c81f738 100644
--- a/content/browser/background_sync/background_sync_network_observer.h
+++ b/content/browser/background_sync/background_sync_network_observer.h
@@ -13,7 +13,7 @@
 namespace content {
 
 class CONTENT_EXPORT BackgroundSyncNetworkObserver
-    : public net::NetworkChangeNotifier::NetworkChangeObserver {
+    : net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   // Creates a BackgroundSyncNetworkObserver. |network_changed_callback| is
   // called when the network connection changes asynchronously via PostMessage.
@@ -21,37 +21,22 @@
 
   ~BackgroundSyncNetworkObserver() override;
 
-  // Enable or disable notifications coming from the NetworkChangeNotifier. (For
-  // preventing flakes in tests)
-  static void SetIgnoreNetworkChangeNotifierForTests(bool ignore);
-
   // Returns true if the state of the network meets the needs of
   // |network_state|.
   bool NetworkSufficient(SyncNetworkState network_state);
 
+ private:
+  void NotifyNetworkChanged();
+
   // NetworkChangeObserver overrides
   void OnNetworkChanged(
       net::NetworkChangeNotifier::ConnectionType connection_type) override;
 
- private:
-  friend class BackgroundSyncBrowserTest;
-  friend class BackgroundSyncManagerTest;
-
-  // Calls NotifyNetworkChanged if the connection type has changed.
-  void NotifyManagerIfNetworkChanged(
-      net::NetworkChangeNotifier::ConnectionType connection_type);
-
-  void NotifyNetworkChanged();
-
   net::NetworkChangeNotifier::ConnectionType connection_type_;
 
   // The callback to run when the network changes.
   base::Closure network_changed_callback_;
 
-  // Set true to ignore notifications coming from the NetworkChangeNotifier
-  // (to prevent flakes in tests).
-  static bool ignore_network_change_notifier_;
-
   DISALLOW_COPY_AND_ASSIGN(BackgroundSyncNetworkObserver);
 };
 
diff --git a/content/browser/background_sync/background_sync_registration_handle.cc b/content/browser/background_sync/background_sync_registration_handle.cc
index 4e5e8e8..7cb2672 100644
--- a/content/browser/background_sync/background_sync_registration_handle.cc
+++ b/content/browser/background_sync/background_sync_registration_handle.cc
@@ -22,8 +22,8 @@
   DCHECK(IsValid());
   DCHECK(background_sync_manager_);
 
-  background_sync_manager_->Unregister(
-      sw_registration_id, options()->periodicity, handle_id_, callback);
+  background_sync_manager_->Unregister(sw_registration_id, handle_id_,
+                                       callback);
 }
 
 void BackgroundSyncRegistrationHandle::NotifyWhenDone(
diff --git a/content/browser/background_sync/background_sync_registration_handle.h b/content/browser/background_sync/background_sync_registration_handle.h
index f2915d1..85f21dff 100644
--- a/content/browser/background_sync/background_sync_registration_handle.h
+++ b/content/browser/background_sync/background_sync_registration_handle.h
@@ -24,7 +24,7 @@
 // destroyed) after the BackgroundSyncManager has been deleted.
 class CONTENT_EXPORT BackgroundSyncRegistrationHandle {
  public:
-  using HandleId = int;
+  using HandleId = int64_t;
   using StatusCallback = base::Callback<void(BackgroundSyncStatus)>;
   using StatusAndStateCallback =
       base::Callback<void(BackgroundSyncStatus, BackgroundSyncState)>;
diff --git a/content/browser/background_sync/background_sync_service_impl.cc b/content/browser/background_sync/background_sync_service_impl.cc
index b8c03df..aef8b45 100644
--- a/content/browser/background_sync/background_sync_service_impl.cc
+++ b/content/browser/background_sync/background_sync_service_impl.cc
@@ -131,7 +131,6 @@
 }
 
 void BackgroundSyncServiceImpl::Unregister(
-    BackgroundSyncPeriodicity periodicity,
     BackgroundSyncRegistrationHandle::HandleId handle_id,
     int64_t sw_registration_id,
     const UnregisterCallback& callback) {
diff --git a/content/browser/background_sync/background_sync_service_impl.h b/content/browser/background_sync/background_sync_service_impl.h
index f00c668..828b53bd 100644
--- a/content/browser/background_sync/background_sync_service_impl.h
+++ b/content/browser/background_sync/background_sync_service_impl.h
@@ -33,8 +33,7 @@
                 int64_t sw_registration_id,
                 bool requested_from_service_worker,
                 const RegisterCallback& callback) override;
-  void Unregister(BackgroundSyncPeriodicity periodicity,
-                  BackgroundSyncRegistrationHandle::HandleId handle_id,
+  void Unregister(BackgroundSyncRegistrationHandle::HandleId handle_id,
                   int64_t sw_registration_id,
                   const UnregisterCallback& callback) override;
   void GetRegistration(BackgroundSyncPeriodicity periodicity,
@@ -78,7 +77,9 @@
   mojo::Binding<BackgroundSyncService> binding_;
 
   // The registrations that the client might reference.
-  IDMap<BackgroundSyncRegistrationHandle, IDMapOwnPointer> active_handles_;
+  IDMap<BackgroundSyncRegistrationHandle,
+        IDMapOwnPointer,
+        BackgroundSyncRegistrationHandle::HandleId> active_handles_;
 
   base::WeakPtrFactory<BackgroundSyncServiceImpl> weak_ptr_factory_;
 
diff --git a/content/browser/background_sync/background_sync_service_impl_unittest.cc b/content/browser/background_sync/background_sync_service_impl_unittest.cc
index ca2e45ce..7d9d65b 100644
--- a/content/browser/background_sync/background_sync_service_impl_unittest.cc
+++ b/content/browser/background_sync/background_sync_service_impl_unittest.cc
@@ -210,7 +210,6 @@
       int32 handle_id,
       const BackgroundSyncService::UnregisterCallback& callback) {
     service_impl_->Unregister(
-        BackgroundSyncPeriodicity::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT,
         handle_id, sw_registration_id_, callback);
     base::RunLoop().RunUntilIdle();
   }
diff --git a/content/browser/bootstrap_sandbox_manager_mac.cc b/content/browser/bootstrap_sandbox_manager_mac.cc
index 48d2549..ae6df85dd 100644
--- a/content/browser/bootstrap_sandbox_manager_mac.cc
+++ b/content/browser/bootstrap_sandbox_manager_mac.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/bootstrap_sandbox_manager_mac.h"
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "content/browser/browser_io_surface_manager_mac.h"
@@ -12,13 +13,15 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_switches.h"
 #include "sandbox/mac/bootstrap_sandbox.h"
 
 namespace content {
 
 // static
 bool BootstrapSandboxManager::ShouldEnable() {
-  return false;
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableBootstrapSandbox);
 }
 
 // static
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index d88d5de..f15b4fc1 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -378,7 +378,7 @@
   // connected and the exit of the child process is detecter by an error on the
   // IPC channel thereafter.
   DCHECK(!early_exit_watcher_.GetWatchedObject());
-  early_exit_watcher_.StartWatching(process.Handle(), this);
+  early_exit_watcher_.StartWatchingOnce(process.Handle(), this);
 #endif
 
   // TODO(rvargas) crbug.com/417532: Don't store a handle.
diff --git a/content/browser/compositor/buffer_queue.cc b/content/browser/compositor/buffer_queue.cc
index 6f4a19d..e22ec38 100644
--- a/content/browser/compositor/buffer_queue.cc
+++ b/content/browser/compositor/buffer_queue.cc
@@ -62,18 +62,10 @@
                                    int source_texture,
                                    const gfx::Rect& new_damage,
                                    const gfx::Rect& old_damage) {
-  gfx::Rect new_damage_mutable = new_damage;
-  gfx::Rect old_damage_mutable = old_damage;
-#if defined(ARCH_CPU_ARM_FAMILY)
-  // TODO(dnicoara): Remove ARM workaround once partial swap is enabled.
-  new_damage_mutable = gfx::Rect(size_);
-  old_damage_mutable = gfx::Rect();
-#endif
-
   gl_helper_->CopySubBufferDamage(
       texture_target_, texture, source_texture,
-      SkRegion(gfx::RectToSkIRect(new_damage_mutable)),
-      SkRegion(gfx::RectToSkIRect(old_damage_mutable)));
+      SkRegion(gfx::RectToSkIRect(new_damage)),
+      SkRegion(gfx::RectToSkIRect(old_damage)));
 }
 
 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
index e9aa71c..14abb51 100644
--- a/content/browser/download/save_file_manager.cc
+++ b/content/browser/download/save_file_manager.cc
@@ -272,9 +272,8 @@
   SaveFileMap::iterator it = save_file_map_.find(save_id);
   if (it != save_file_map_.end()) {
     SaveFile* save_file = it->second;
-    // This routine may be called twice for the same from from
-    // SaveePackage::OnReceivedSerializedHtmlData, once for the file
-    // itself, and once when all frames have been serialized.
+    // This routine may be called twice from the same SavePackage - once for the
+    // file itself, and once when all frames have been serialized.
     // So we can't assert that the file is InProgress() here.
     // TODO(rdsmith): Fix this logic and put the DCHECK below back in.
     // DCHECK(save_file->InProgress());
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
index 98092f4..9687195 100644
--- a/content/browser/download/save_package.cc
+++ b/content/browser/download/save_package.cc
@@ -205,6 +205,7 @@
                          const base::FilePath& file_full_path,
                          const base::FilePath& directory_full_path)
     : WebContentsObserver(web_contents),
+      number_of_frames_pending_response_(0),
       file_manager_(NULL),
       download_manager_(NULL),
       download_(NULL),
@@ -222,8 +223,7 @@
       contents_id_(0),
       unique_id_(g_save_package_id++),
       wrote_to_completed_file_(false),
-      wrote_to_failed_file_(false) {
-}
+      wrote_to_failed_file_(false) {}
 
 SavePackage::~SavePackage() {
   // Stop receiving saving job's updates
@@ -339,7 +339,7 @@
   if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML) {
     // Get directory
     DCHECK(!saved_main_directory_path_.empty());
-    GetSavableResourceLinksForCurrentPage();
+    GetSavableResourceLinks();
   } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) {
     web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind(
         &SavePackage::OnMHTMLGenerated, this));
@@ -626,7 +626,7 @@
       wait_state_ == HTML_DATA) {
     // Inform backend to serialize the all frames' DOM and send serialized
     // HTML data back.
-    GetSerializedHtmlDataForCurrentPageWithLocalLinks();
+    GetSerializedHtmlWithLocalLinks();
   }
 }
 
@@ -1003,16 +1003,6 @@
   }
 }
 
-bool SavePackage::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(SavePackage, message)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData,
-                        OnReceivedSerializedHtmlData)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
 bool SavePackage::OnMessageReceived(const IPC::Message& message,
                                     RenderFrameHost* render_frame_host) {
   bool handled = true;
@@ -1021,6 +1011,8 @@
                         OnSavableResourceLinksResponse)
     IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksError,
                         OnSavableResourceLinksError)
+    IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedHtmlWithLocalLinksResponse,
+                        OnSerializedHtmlWithLocalLinksResponse)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -1030,7 +1022,7 @@
 // We collect all URLs which have local storage and send the
 // map:(originalURL:currentLocalPath) to render process (backend).
 // Then render process will serialize DOM and send data to us.
-void SavePackage::GetSerializedHtmlDataForCurrentPageWithLocalLinks() {
+void SavePackage::GetSerializedHtmlWithLocalLinks() {
   if (wait_state_ != HTML_DATA)
     return;
   std::vector<GURL> saved_links;
@@ -1067,41 +1059,48 @@
   // Get the relative directory name.
   base::FilePath relative_dir_name = saved_main_directory_path_.BaseName();
 
-  Send(new ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks(
-      routing_id(), saved_links, saved_file_paths, relative_dir_name));
+  // Ask all frames for their serialized data.
+  DCHECK_EQ(0, number_of_frames_pending_response_);
+  web_contents()->ForEachFrame(base::Bind(
+      &SavePackage::GetSerializedHtmlWithLocalLinksForFrame,
+      base::Unretained(this),  // Safe, because ForEachFrame is synchronous.
+      saved_links, saved_file_paths, relative_dir_name));
+  DCHECK_LT(0, number_of_frames_pending_response_);
 }
 
-// Process the serialized HTML content data of a specified web page
-// retrieved from render process.
-void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                               const std::string& data,
-                                               int32 status) {
+void SavePackage::GetSerializedHtmlWithLocalLinksForFrame(
+    const std::vector<GURL>& saved_links,
+    const std::vector<base::FilePath>& saved_file_paths,
+    const base::FilePath& relative_dir_name,
+    RenderFrameHost* target) {
+  number_of_frames_pending_response_++;
+  target->Send(new FrameMsg_GetSerializedHtmlWithLocalLinks(
+      target->GetRoutingID(), saved_links, saved_file_paths,
+      relative_dir_name));
+}
+
+// Process the serialized HTML content data of a specified frame
+// retrieved from the renderer process.
+void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
+    RenderFrameHost* sender,
+    const GURL& frame_url,
+    const std::string& data,
+    int32 status) {
   WebPageSerializerClient::PageSerializationStatus flag =
       static_cast<WebPageSerializerClient::PageSerializationStatus>(status);
+
+  // When calling WebPageSerializer::serialize in non-recursive mode, the
+  // AllFramesAreFinished is redundant - it is sent by each frame right after
+  // CurrentFrameIsFinished.  Therefore we ignore AllFramesAreFinished and
+  // instead track pending frames in |number_of_frames_pending_response_|.
+  if (flag == WebPageSerializerClient::AllFramesAreFinished)
+    return;
+
   // Check current state.
   if (wait_state_ != HTML_DATA)
     return;
 
   int id = contents_id();
-  // If the all frames are finished saving, we need to close the
-  // remaining SaveItems.
-  if (flag == WebPageSerializerClient::AllFramesAreFinished) {
-    for (SaveUrlItemMap::iterator it = in_progress_items_.begin();
-         it != in_progress_items_.end(); ++it) {
-      DVLOG(20) << " " << __FUNCTION__ << "()"
-                << " save_id = " << it->second->save_id()
-                << " url = \"" << it->second->url().spec() << "\"";
-      BrowserThread::PostTask(
-          BrowserThread::FILE, FROM_HERE,
-          base::Bind(&SaveFileManager::SaveFinished,
-                     file_manager_,
-                     it->second->save_id(),
-                     it->second->url(),
-                     id,
-                     true));
-    }
-    return;
-  }
 
   SaveUrlItemMap::iterator it = in_progress_items_.find(frame_url.spec());
   if (it == in_progress_items_.end()) {
@@ -1151,12 +1150,29 @@
                    save_item->url(),
                    id,
                    true));
+    number_of_frames_pending_response_--;
+    DCHECK_LE(0, number_of_frames_pending_response_);
+  }
+
+  // If all frames are finished saving, we need to close the remaining
+  // SaveItems.
+  if (number_of_frames_pending_response_ == 0) {
+    for (SaveUrlItemMap::iterator it = in_progress_items_.begin();
+         it != in_progress_items_.end(); ++it) {
+      DVLOG(20) << " " << __FUNCTION__ << "()"
+                << " save_id = " << it->second->save_id() << " url = \""
+                << it->second->url().spec() << "\"";
+      BrowserThread::PostTask(
+          BrowserThread::FILE, FROM_HERE,
+          base::Bind(&SaveFileManager::SaveFinished, file_manager_,
+                     it->second->save_id(), it->second->url(), id, true));
+    }
   }
 }
 
 // Ask for all savable resource links from backend, include main frame and
 // sub-frame.
-void SavePackage::GetSavableResourceLinksForCurrentPage() {
+void SavePackage::GetSavableResourceLinks() {
   if (wait_state_ != START_PROCESS)
     return;
 
@@ -1205,14 +1221,14 @@
   if (frame_url.is_valid())
     frame_urls_to_save_.push_back(frame_url);
 
-  CompleteSavableResourceLinksResponseFromFrame();
+  CompleteSavableResourceLinksResponse();
 }
 
 void SavePackage::OnSavableResourceLinksError(RenderFrameHost* sender) {
-  CompleteSavableResourceLinksResponseFromFrame();
+  CompleteSavableResourceLinksResponse();
 }
 
-void SavePackage::CompleteSavableResourceLinksResponseFromFrame() {
+void SavePackage::CompleteSavableResourceLinksResponse() {
   --number_of_frames_pending_response_;
   DCHECK_LE(0, number_of_frames_pending_response_);
   if (number_of_frames_pending_response_ != 0)
diff --git a/content/browser/download/save_package.h b/content/browser/download/save_package.h
index b96d2ee5..818ad5bf 100644
--- a/content/browser/download/save_package.h
+++ b/content/browser/download/save_package.h
@@ -146,7 +146,6 @@
   void DoSavingProcess();
 
   // WebContentsObserver implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
   bool OnMessageReceived(const IPC::Message& message,
                          RenderFrameHost* render_frame_host) override;
 
@@ -179,7 +178,7 @@
 
   // Set of methods to get all savable resource links from current web page,
   // including main frame and sub-frames.
-  void GetSavableResourceLinksForCurrentPage();
+  void GetSavableResourceLinks();
   void GetSavableResourceLinksForFrame(RenderFrameHost* target);
   void OnSavableResourceLinksResponse(
       RenderFrameHost* sender,
@@ -187,11 +186,35 @@
       const std::vector<GURL>& resources_list,
       const std::vector<Referrer>& referrers_list);
   void OnSavableResourceLinksError(RenderFrameHost* sender);
-  void CompleteSavableResourceLinksResponseFromFrame();
+  void CompleteSavableResourceLinksResponse();
 
-  // Get html data by serializing all frames of current page with lists
-  // which contain all resource links that have local copy.
-  void GetSerializedHtmlDataForCurrentPageWithLocalLinks();
+  // For each frame in the current page, ask the renderer process associated
+  // with that frame to serialize that frame into html.
+  void GetSerializedHtmlWithLocalLinks();
+
+  // Ask renderer process to serialize |target| frame into html data
+  // with lists which contain all resource links that have a local copy.
+  // - The parameter |saved_links| contains original URLs of all saved links
+  //   (which may include URLs referred to from the whole page (not just from
+  //   the |target| frame).
+  // - The parameter |saved_file_paths| contains corresponding local file paths
+  //   of all saved links, which is matched with |saved_links| vector one by
+  //   one.
+  // - The parameter |relative_dir_name| is relative path of directory which
+  //   contain all saved auxiliary files included all sub frames and resouces.
+  void GetSerializedHtmlWithLocalLinksForFrame(
+      const std::vector<GURL>& saved_links,
+      const std::vector<base::FilePath>& saved_file_paths,
+      const base::FilePath& relative_dir_name,
+      RenderFrameHost* target);
+
+  // Routes html data (sent by renderer process in response to
+  // GetSerializedHtmlWithLocalLinksForFrame above) to the associated local file
+  // (and also keeps track of when all frames have been completed).
+  void OnSerializedHtmlWithLocalLinksResponse(RenderFrameHost* sender,
+                                              const GURL& frame_url,
+                                              const std::string& data,
+                                              int32 status);
 
   // Look up SaveItem by save id from in progress map.
   SaveItem* LookupItemInProcessBySaveId(int32 save_id);
@@ -214,10 +237,6 @@
       SavePageType type,
       const SavePackageDownloadCreatedCallback& cb);
 
-  void OnReceivedSerializedHtmlData(const GURL& frame_url,
-                                    const std::string& data,
-                                    int32 status);
-
   typedef base::hash_map<std::string, SaveItem*> SaveUrlItemMap;
   // in_progress_items_ is map of all saving job in in-progress state.
   SaveUrlItemMap in_progress_items_;
diff --git a/content/browser/fileapi/blob_reader_unittest.cc b/content/browser/fileapi/blob_reader_unittest.cc
new file mode 100644
index 0000000..a7e095c
--- /dev/null
+++ b/content/browser/fileapi/blob_reader_unittest.cc
@@ -0,0 +1,1111 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/blob/blob_reader.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_runner.h"
+#include "base/time/time.h"
+#include "content/public/test/async_file_test_helper.h"
+#include "content/public/test/test_file_system_context.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/fileapi/file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using base::FilePath;
+using content::AsyncFileTestHelper;
+using net::DrainableIOBuffer;
+using net::IOBuffer;
+
+namespace storage {
+namespace {
+
+const int kTestDiskCacheStreamIndex = 0;
+
+// Our disk cache tests don't need a real data handle since the tests themselves
+// scope the disk cache and entries.
+class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
+ private:
+  ~EmptyDataHandle() override {}
+};
+
+// A disk_cache::Entry that arbitrarily delays the completion of a read
+// operation to allow testing some races without flake. This is particularly
+// relevant in this unit test, which uses the always-synchronous MEMORY_CACHE.
+class DelayedReadEntry : public disk_cache::Entry {
+ public:
+  explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry)
+      : entry_(entry.Pass()) {}
+  ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); }
+
+  bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); }
+
+  void RunPendingReadCallbacks() {
+    std::vector<base::Callback<void(void)>> callbacks;
+    pending_read_callbacks_.swap(callbacks);
+    for (const auto& callback : callbacks)
+      callback.Run();
+  }
+
+  // From disk_cache::Entry:
+  void Doom() override { entry_->Doom(); }
+
+  void Close() override { delete this; }  // Note this is required by the API.
+
+  std::string GetKey() const override { return entry_->GetKey(); }
+
+  base::Time GetLastUsed() const override { return entry_->GetLastUsed(); }
+
+  base::Time GetLastModified() const override {
+    return entry_->GetLastModified();
+  }
+
+  int32 GetDataSize(int index) const override {
+    return entry_->GetDataSize(index);
+  }
+
+  int ReadData(int index,
+               int offset,
+               IOBuffer* buf,
+               int buf_len,
+               const CompletionCallback& original_callback) override {
+    net::TestCompletionCallback callback;
+    int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback());
+    DCHECK_NE(rv, net::ERR_IO_PENDING)
+        << "Test expects to use a MEMORY_CACHE instance, which is synchronous.";
+    pending_read_callbacks_.push_back(base::Bind(original_callback, rv));
+    return net::ERR_IO_PENDING;
+  }
+
+  int WriteData(int index,
+                int offset,
+                IOBuffer* buf,
+                int buf_len,
+                const CompletionCallback& callback,
+                bool truncate) override {
+    return entry_->WriteData(index, offset, buf, buf_len, callback, truncate);
+  }
+
+  int ReadSparseData(int64 offset,
+                     IOBuffer* buf,
+                     int buf_len,
+                     const CompletionCallback& callback) override {
+    return entry_->ReadSparseData(offset, buf, buf_len, callback);
+  }
+
+  int WriteSparseData(int64 offset,
+                      IOBuffer* buf,
+                      int buf_len,
+                      const CompletionCallback& callback) override {
+    return entry_->WriteSparseData(offset, buf, buf_len, callback);
+  }
+
+  int GetAvailableRange(int64 offset,
+                        int len,
+                        int64* start,
+                        const CompletionCallback& callback) override {
+    return entry_->GetAvailableRange(offset, len, start, callback);
+  }
+
+  bool CouldBeSparse() const override { return entry_->CouldBeSparse(); }
+
+  void CancelSparseIO() override { entry_->CancelSparseIO(); }
+
+  int ReadyForSparseIO(const CompletionCallback& callback) override {
+    return entry_->ReadyForSparseIO(callback);
+  }
+
+ private:
+  disk_cache::ScopedEntryPtr entry_;
+  std::vector<base::Callback<void(void)>> pending_read_callbacks_;
+};
+
+scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache(
+    const scoped_refptr<base::SingleThreadTaskRunner>& thread) {
+  scoped_ptr<disk_cache::Backend> cache;
+  net::TestCompletionCallback callback;
+  int rv = disk_cache::CreateCacheBackend(
+      net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, FilePath(), 0, false,
+      thread, nullptr, &cache, callback.callback());
+  EXPECT_EQ(net::OK, callback.GetResult(rv));
+
+  return cache.Pass();
+}
+
+disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
+                                                const char* key,
+                                                const std::string& data) {
+  disk_cache::Entry* temp_entry = nullptr;
+  net::TestCompletionCallback callback;
+  int rv = cache->CreateEntry(key, &temp_entry, callback.callback());
+  if (callback.GetResult(rv) != net::OK)
+    return nullptr;
+  disk_cache::ScopedEntryPtr entry(temp_entry);
+
+  scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data);
+  rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
+                        iobuffer->size(), callback.callback(), false);
+  EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
+  return entry.Pass();
+}
+
+template <typename T>
+void SetValue(T* address, T value) {
+  *address = value;
+}
+
+class FakeFileStreamReader : public FileStreamReader {
+ public:
+  explicit FakeFileStreamReader(const std::string& contents)
+      : buffer_(new DrainableIOBuffer(
+            new net::StringIOBuffer(
+                scoped_ptr<std::string>(new std::string(contents))),
+            contents.size())),
+        net_error_(net::OK),
+        size_(contents.size()) {}
+  FakeFileStreamReader(const std::string& contents, uint64_t size)
+      : buffer_(new DrainableIOBuffer(
+            new net::StringIOBuffer(
+                scoped_ptr<std::string>(new std::string(contents))),
+            contents.size())),
+        net_error_(net::OK),
+        size_(size) {}
+
+  ~FakeFileStreamReader() override {}
+
+  void SetReturnError(int net_error) { net_error_ = net_error; }
+
+  void SetAsyncRunner(base::SingleThreadTaskRunner* runner) {
+    async_task_runner_ = runner;
+  }
+
+  int Read(net::IOBuffer* buf,
+           int buf_length,
+           const net::CompletionCallback& done) override {
+    DCHECK(buf);
+    // When async_task_runner_ is not set, return synchronously.
+    if (!async_task_runner_.get()) {
+      if (net_error_ == net::OK) {
+        return ReadImpl(buf, buf_length, net::CompletionCallback());
+      } else {
+        return net_error_;
+      }
+    }
+
+    // Otherwise always return asynchronously.
+    if (net_error_ == net::OK) {
+      async_task_runner_->PostTask(
+          FROM_HERE,
+          base::Bind(base::IgnoreResult(&FakeFileStreamReader::ReadImpl),
+                     base::Unretained(this), make_scoped_refptr(buf),
+                     buf_length, done));
+    } else {
+      async_task_runner_->PostTask(FROM_HERE, base::Bind(done, net_error_));
+    }
+    return net::ERR_IO_PENDING;
+  }
+
+  int64 GetLength(const net::Int64CompletionCallback& size_callback) override {
+    // When async_task_runner_ is not set, return synchronously.
+    if (!async_task_runner_.get()) {
+      if (net_error_ == net::OK) {
+        return size_;
+      } else {
+        return net_error_;
+      }
+    }
+    if (net_error_ == net::OK) {
+      async_task_runner_->PostTask(FROM_HERE, base::Bind(size_callback, size_));
+    } else {
+      async_task_runner_->PostTask(
+          FROM_HERE,
+          base::Bind(size_callback, static_cast<int64_t>(net_error_)));
+    }
+    return net::ERR_IO_PENDING;
+  }
+
+ private:
+  int ReadImpl(scoped_refptr<net::IOBuffer> buf,
+               int buf_length,
+               const net::CompletionCallback& done) {
+    CHECK_GE(buf_length, 0);
+    int length = std::min(buf_length, buffer_->BytesRemaining());
+    memcpy(buf->data(), buffer_->data(), length);
+    buffer_->DidConsume(length);
+    if (done.is_null()) {
+      return length;
+    }
+    done.Run(length);
+    return net::ERR_IO_PENDING;
+  }
+
+  scoped_refptr<net::DrainableIOBuffer> buffer_;
+  scoped_refptr<base::SingleThreadTaskRunner> async_task_runner_;
+  int net_error_;
+  uint64_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeFileStreamReader);
+};
+
+class MockFileStreamReaderProvider
+    : public BlobReader::FileStreamReaderProvider {
+ public:
+  ~MockFileStreamReaderProvider() override {}
+
+  MOCK_METHOD4(CreateForLocalFileMock,
+               FileStreamReader*(base::TaskRunner* task_runner,
+                                 const FilePath& file_path,
+                                 int64_t initial_offset,
+                                 const base::Time& expected_modification_time));
+  MOCK_METHOD4(CreateFileStreamReaderMock,
+               FileStreamReader*(const GURL& filesystem_url,
+                                 int64_t offset,
+                                 int64_t max_bytes_to_read,
+                                 const base::Time& expected_modification_time));
+  // Since we're returning a move-only type, we have to do some delegation for
+  // gmock.
+  scoped_ptr<FileStreamReader> CreateForLocalFile(
+      base::TaskRunner* task_runner,
+      const base::FilePath& file_path,
+      int64_t initial_offset,
+      const base::Time& expected_modification_time) override {
+    return make_scoped_ptr(CreateForLocalFileMock(
+        task_runner, file_path, initial_offset, expected_modification_time));
+  }
+
+  scoped_ptr<FileStreamReader> CreateFileStreamReader(
+      const GURL& filesystem_url,
+      int64_t offset,
+      int64_t max_bytes_to_read,
+      const base::Time& expected_modification_time) override {
+    return make_scoped_ptr(CreateFileStreamReaderMock(
+        filesystem_url, offset, max_bytes_to_read, expected_modification_time));
+  }
+};
+
+}  // namespace
+
+class BlobReaderTest : public ::testing::Test {
+ public:
+  BlobReaderTest() {}
+  ~BlobReaderTest() override {}
+
+  void TearDown() override {
+    reader_.reset();
+    blob_handle_.reset();
+    message_loop_.RunUntilIdle();
+    base::RunLoop().RunUntilIdle();
+  }
+
+ protected:
+  void InitializeReader(BlobDataBuilder* builder) {
+    blob_handle_ = builder ? context_.AddFinishedBlob(builder).Pass() : nullptr;
+    provider_ = new MockFileStreamReaderProvider();
+    scoped_ptr<BlobReader::FileStreamReaderProvider> temp_ptr(provider_);
+    reader_.reset(new BlobReader(blob_handle_.get(), temp_ptr.Pass(),
+                                 message_loop_.task_runner().get()));
+  }
+
+  // Takes ownership of the file reader (the blob reader takes ownership).
+  void ExpectLocalFileCall(const FilePath& file_path,
+                           base::Time modification_time,
+                           uint64_t initial_offset,
+                           FakeFileStreamReader* reader) {
+    EXPECT_CALL(*provider_, CreateForLocalFileMock(
+                                message_loop_.task_runner().get(), file_path,
+                                initial_offset, modification_time))
+        .WillOnce(testing::Return(reader));
+  }
+
+  // Takes ownership of the file reader (the blob reader takes ownership).
+  void ExpectFileSystemCall(const GURL& filesystem_url,
+                            int64_t offset,
+                            int64_t max_bytes_to_read,
+                            base::Time expected_modification_time,
+                            FakeFileStreamReader* reader) {
+    EXPECT_CALL(*provider_, CreateFileStreamReaderMock(
+                                filesystem_url, offset, max_bytes_to_read,
+                                expected_modification_time))
+        .WillOnce(testing::Return(reader));
+  }
+
+  void CheckSizeCalculatedSynchronously(size_t expected_size, int async_size) {
+    EXPECT_EQ(-1, async_size);
+    EXPECT_EQ(net::OK, reader_->net_error());
+    EXPECT_EQ(expected_size, reader_->total_size());
+    EXPECT_TRUE(reader_->total_size_calculated());
+  }
+
+  void CheckSizeNotCalculatedYet(int async_size) {
+    EXPECT_EQ(-1, async_size);
+    EXPECT_EQ(net::OK, reader_->net_error());
+    EXPECT_FALSE(reader_->total_size_calculated());
+  }
+
+  void CheckSizeCalculatedAsynchronously(size_t expected_size,
+                                         int async_result) {
+    EXPECT_EQ(net::OK, async_result);
+    EXPECT_EQ(net::OK, reader_->net_error());
+    EXPECT_EQ(expected_size, reader_->total_size());
+    EXPECT_TRUE(reader_->total_size_calculated());
+  }
+
+  scoped_refptr<net::IOBuffer> CreateBuffer(uint64_t size) {
+    return scoped_refptr<net::IOBuffer>(
+        new net::IOBuffer(static_cast<size_t>(size)));
+  }
+
+  bool IsReaderTotalSizeCalculated() {
+    return reader_->total_size_calculated();
+  }
+
+  BlobStorageContext context_;
+  scoped_ptr<BlobDataHandle> blob_handle_;
+  MockFileStreamReaderProvider* provider_ = nullptr;
+  base::MessageLoop message_loop_;
+  scoped_ptr<BlobReader> reader_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
+};
+
+namespace {
+
+TEST_F(BlobReaderTest, BasicMemory) {
+  BlobDataBuilder b("uuid");
+  const std::string kData("Hello!!!");
+  const size_t kDataSize = 8ul;
+  b.AppendData(kData);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kDataSize, size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kDataSize, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
+}
+
+TEST_F(BlobReaderTest, BasicFile) {
+  BlobDataBuilder b("uuid");
+  const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+  b.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&b);
+
+  // Non-async reader.
+  ExpectLocalFileCall(kPath, kTime, 0, new FakeFileStreamReader(kData));
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
+}
+
+TEST_F(BlobReaderTest, BasicFileSystem) {
+  BlobDataBuilder b("uuid");
+  const GURL kURL("file://test_file/here.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+  b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
+  this->InitializeReader(&b);
+
+  // Non-async reader.
+  ExpectFileSystemCall(kURL, 0, kData.size(), kTime,
+                       new FakeFileStreamReader(kData));
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
+}
+
+TEST_F(BlobReaderTest, BasicDiskCache) {
+  scoped_ptr<disk_cache::Backend> cache =
+      CreateInMemoryDiskCache(message_loop_.task_runner());
+  ASSERT_TRUE(cache);
+
+  BlobDataBuilder b("uuid");
+  const std::string kData = "Test Blob Data";
+  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
+      new EmptyDataHandle();
+  disk_cache::ScopedEntryPtr entry =
+      CreateDiskCacheEntry(cache.get(), "test entry", kData);
+  b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kData.size(), static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
+}
+
+TEST_F(BlobReaderTest, BufferLargerThanMemory) {
+  BlobDataBuilder b("uuid");
+  const std::string kData("Hello!!!");
+  const size_t kDataSize = 8ul;
+  const size_t kBufferSize = 10ul;
+  b.AppendData(kData);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kBufferSize, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "Hello!!!", kDataSize));
+}
+
+TEST_F(BlobReaderTest, MemoryRange) {
+  BlobDataBuilder b("uuid");
+  const std::string kData("Hello!!!");
+  const size_t kDataSize = 8ul;
+  const size_t kSeekOffset = 2ul;
+  const uint64_t kReadLength = 4ull;
+  b.AppendData(kData);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
+
+  reader_->SetReadRange(kSeekOffset, kReadLength);
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kDataSize - kSeekOffset, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "llo!", kReadLength));
+}
+
+TEST_F(BlobReaderTest, BufferSmallerThanMemory) {
+  BlobDataBuilder b("uuid");
+  const std::string kData("Hello!!!");
+  const size_t kBufferSize = 4ul;
+  b.AppendData(kData);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kBufferSize, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "Hell", kBufferSize));
+
+  bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kBufferSize, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "o!!!", kBufferSize));
+}
+
+TEST_F(BlobReaderTest, SegmentedBufferAndMemory) {
+  BlobDataBuilder b("uuid");
+  const size_t kNumItems = 10;
+  const size_t kItemSize = 6;
+  const size_t kBufferSize = 10;
+  const size_t kTotalSize = kNumItems * kItemSize;
+  char current_value = 0;
+  for (size_t i = 0; i < kNumItems; i++) {
+    char buf[kItemSize];
+    for (size_t j = 0; j < kItemSize; j++) {
+      buf[j] = current_value++;
+    }
+    b.AppendData(buf, kItemSize);
+  }
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kTotalSize, size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
+
+  current_value = 0;
+  for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
+    int bytes_read = 0;
+    int async_bytes_read = 0;
+    EXPECT_EQ(BlobReader::Status::DONE,
+              reader_->Read(buffer.get(), kBufferSize, &bytes_read,
+                            base::Bind(&SetValue<int>, &async_bytes_read)));
+    EXPECT_EQ(net::OK, reader_->net_error());
+    EXPECT_EQ(kBufferSize, static_cast<size_t>(bytes_read));
+    EXPECT_EQ(0, async_bytes_read);
+    for (size_t j = 0; j < kBufferSize; j++) {
+      EXPECT_EQ(current_value, buffer->data()[j]);
+      current_value++;
+    }
+  }
+}
+
+TEST_F(BlobReaderTest, FileAsync) {
+  BlobDataBuilder b("uuid");
+  const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+  b.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&b);
+
+  scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+
+  ExpectLocalFileCall(kPath, kTime, 0, reader.release());
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeNotCalculatedYet(size_result);
+  message_loop_.RunUntilIdle();
+  CheckSizeCalculatedAsynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
+  EXPECT_EQ(0, bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
+}
+
+TEST_F(BlobReaderTest, FileSystemAsync) {
+  BlobDataBuilder b("uuid");
+  const GURL kURL("file://test_file/here.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+  b.AppendFileSystemFile(kURL, 0, kData.size(), kTime);
+  this->InitializeReader(&b);
+
+  scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+
+  ExpectFileSystemCall(kURL, 0, kData.size(), kTime, reader.release());
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeNotCalculatedYet(size_result);
+  message_loop_.RunUntilIdle();
+  CheckSizeCalculatedAsynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
+  EXPECT_EQ(0, bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
+}
+
+TEST_F(BlobReaderTest, DiskCacheAsync) {
+  scoped_ptr<disk_cache::Backend> cache =
+      CreateInMemoryDiskCache(message_loop_.task_runner());
+  ASSERT_TRUE(cache);
+
+  BlobDataBuilder b("uuid");
+  const std::string kData = "Test Blob Data";
+  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
+      new EmptyDataHandle();
+  scoped_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry(
+      CreateDiskCacheEntry(cache.get(), "test entry", kData).Pass()));
+  b.AppendDiskCacheEntry(data_handle, delayed_read_entry.get(),
+                         kTestDiskCacheStreamIndex);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeCalculatedSynchronously(kData.size(), size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
+  delayed_read_entry->RunPendingReadCallbacks();
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(0, bytes_read);
+  EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
+  EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
+}
+
+TEST_F(BlobReaderTest, FileRange) {
+  BlobDataBuilder b("uuid");
+  const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  // We check the offset in the ExpectLocalFileCall mock.
+  const std::string kRangeData = "leD";
+  const std::string kData = "FileData!!!";
+  const uint64_t kOffset = 2;
+  const uint64_t kReadLength = 3;
+  const base::Time kTime = base::Time::Now();
+  b.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&b);
+
+  scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData));
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+  ExpectLocalFileCall(kPath, kTime, 0, reader.release());
+
+  // We create the reader again with the offset after the seek.
+  reader.reset(new FakeFileStreamReader(kRangeData));
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+  ExpectLocalFileCall(kPath, kTime, kOffset, reader.release());
+
+  int size_result = -1;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  message_loop_.RunUntilIdle();
+
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->SetReadRange(kOffset, kReadLength));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kReadLength, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kReadLength, static_cast<size_t>(async_bytes_read));
+  EXPECT_EQ(0, bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength));
+}
+
+TEST_F(BlobReaderTest, DiskCacheRange) {
+  scoped_ptr<disk_cache::Backend> cache =
+      CreateInMemoryDiskCache(message_loop_.task_runner());
+  ASSERT_TRUE(cache);
+
+  BlobDataBuilder b("uuid");
+  const std::string kData = "Test Blob Data";
+  const uint64_t kOffset = 2;
+  const uint64_t kReadLength = 3;
+  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
+      new EmptyDataHandle();
+  disk_cache::ScopedEntryPtr entry =
+      CreateDiskCacheEntry(cache.get(), "test entry", kData);
+  b.AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
+  this->InitializeReader(&b);
+
+  int size_result = -1;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kReadLength);
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->SetReadRange(kOffset, kReadLength));
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->Read(buffer.get(), kReadLength, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(kReadLength, static_cast<size_t>(bytes_read));
+  EXPECT_EQ(0, async_bytes_read);
+  EXPECT_EQ(0, memcmp(buffer->data(), "st ", kReadLength));
+}
+
+TEST_F(BlobReaderTest, FileSomeAsyncSegmentedOffsetsUnknownSizes) {
+  // This tests includes:
+  // * Unknown file sizes (item length of uint64::max) for every other item.
+  // * Offsets for every 3rd file item.
+  // * Non-async reader for every 4th file item.
+  BlobDataBuilder b("uuid");
+  const FilePath kPathBase = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  const base::Time kTime = base::Time::Now();
+  const size_t kNumItems = 10;
+  const size_t kItemSize = 6;
+  const size_t kBufferSize = 10;
+  const size_t kTotalSize = kNumItems * kItemSize;
+  char current_value = 0;
+  // Create blob and reader.
+  for (size_t i = 0; i < kNumItems; i++) {
+    current_value += kItemSize;
+    FilePath path = kPathBase.Append(
+        FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
+    uint64_t offset = i % 3 == 0 ? 1 : 0;
+    uint64_t size =
+        i % 2 == 0 ? kItemSize : std::numeric_limits<uint64_t>::max();
+    b.AppendFile(path, offset, size, kTime);
+  }
+  this->InitializeReader(&b);
+
+  // Set expectations.
+  current_value = 0;
+  for (size_t i = 0; i < kNumItems; i++) {
+    uint64_t offset = i % 3 == 0 ? 1 : 0;
+    scoped_ptr<char[]> buf(new char[kItemSize + offset]);
+    if (offset > 0) {
+      memset(buf.get(), 7, offset);
+    }
+    for (size_t j = 0; j < kItemSize; j++) {
+      buf.get()[j + offset] = current_value++;
+    }
+    scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(
+        std::string(buf.get() + offset, kItemSize), kItemSize + offset));
+    if (i % 4 != 0) {
+      reader->SetAsyncRunner(message_loop_.task_runner().get());
+    }
+    FilePath path = kPathBase.Append(
+        FilePath::FromUTF8Unsafe(base::StringPrintf("%d", current_value)));
+    ExpectLocalFileCall(path, kTime, offset, reader.release());
+  }
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeNotCalculatedYet(size_result);
+  message_loop_.RunUntilIdle();
+  CheckSizeCalculatedAsynchronously(kTotalSize, size_result);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize));
+
+  current_value = 0;
+  for (size_t i = 0; i < kTotalSize / kBufferSize; i++) {
+    int bytes_read = 0;
+    int async_bytes_read = 0;
+    EXPECT_EQ(BlobReader::Status::IO_PENDING,
+              reader_->Read(buffer.get(), kBufferSize, &bytes_read,
+                            base::Bind(&SetValue<int>, &async_bytes_read)));
+    message_loop_.RunUntilIdle();
+    EXPECT_EQ(net::OK, reader_->net_error());
+    EXPECT_EQ(0, bytes_read);
+    EXPECT_EQ(kBufferSize, static_cast<size_t>(async_bytes_read));
+    for (size_t j = 0; j < kBufferSize; j++) {
+      EXPECT_EQ(current_value, buffer->data()[j]);
+      current_value++;
+    }
+  }
+}
+
+TEST_F(BlobReaderTest, MixedContent) {
+  // Includes data, a file, and a disk cache entry.
+  scoped_ptr<disk_cache::Backend> cache =
+      CreateInMemoryDiskCache(message_loop_.task_runner());
+  ASSERT_TRUE(cache);
+
+  BlobDataBuilder b("uuid");
+  const std::string kData1("Hello ");
+  const std::string kData2("there. ");
+  const std::string kData3("This ");
+  const std::string kData4("is multi-content.");
+  const uint64_t kDataSize = 35;
+
+  const base::Time kTime = base::Time::Now();
+  const FilePath kData1Path = FilePath::FromUTF8Unsafe("/fake/file.txt");
+
+  disk_cache::ScopedEntryPtr entry3 =
+      CreateDiskCacheEntry(cache.get(), "test entry", kData3);
+
+  b.AppendFile(kData1Path, 0, kData1.size(), kTime);
+  b.AppendData(kData2);
+  b.AppendDiskCacheEntry(
+      scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()),
+      entry3.get(), kTestDiskCacheStreamIndex);
+  b.AppendData(kData4);
+
+  this->InitializeReader(&b);
+
+  scoped_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader(kData1));
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+  ExpectLocalFileCall(kData1Path, kTime, 0, reader.release());
+
+  int size_result = -1;
+  EXPECT_FALSE(IsReaderTotalSizeCalculated());
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  CheckSizeNotCalculatedYet(size_result);
+  message_loop_.RunUntilIdle();
+  CheckSizeCalculatedAsynchronously(kDataSize, size_result);
+
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
+
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kDataSize, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(0, async_bytes_read);
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::OK, reader_->net_error());
+  EXPECT_EQ(0, bytes_read);
+  EXPECT_EQ(kDataSize, static_cast<size_t>(async_bytes_read));
+  EXPECT_EQ(0, memcmp(buffer->data(), "Hello there. This is multi-content.",
+                      kDataSize));
+}
+
+TEST_F(BlobReaderTest, StateErrors) {
+  // Test common variables
+  int bytes_read = -1;
+  int async_bytes_read = -1;
+  int size_result = -1;
+  const std::string kData("Hello!!!");
+
+  // Case: Blob handle is a nullptr.
+  InitializeReader(nullptr);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+  EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(10);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->Read(buffer.get(), 10, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+
+  // Case: Not calling CalculateSize before SetReadRange.
+  BlobDataBuilder builder1("uuid1");
+  builder1.AppendData(kData);
+  InitializeReader(&builder1);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR, reader_->SetReadRange(0, 10));
+  EXPECT_EQ(net::ERR_FAILED, reader_->net_error());
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->Read(buffer.get(), 10, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+
+  // Case: Not calling CalculateSize before Read.
+  BlobDataBuilder builder2("uuid2");
+  builder2.AppendData(kData);
+  InitializeReader(&builder2);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->Read(buffer.get(), 10, &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+}
+
+TEST_F(BlobReaderTest, FileErrorsSync) {
+  int size_result = -1;
+  const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+
+  // Case: Error on length query.
+  BlobDataBuilder builder1("uuid1");
+  builder1.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&builder1);
+  FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
+  reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
+  ExpectLocalFileCall(kPath, kTime, 0, reader);
+
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+
+  // Case: Error on read.
+  BlobDataBuilder builder2("uuid2");
+  builder2.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&builder2);
+  reader = new FakeFileStreamReader(kData);
+  ExpectLocalFileCall(kPath, kTime, 0, reader);
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+}
+
+TEST_F(BlobReaderTest, FileErrorsAsync) {
+  int size_result = -1;
+  const FilePath kPath = FilePath::FromUTF8Unsafe("/fake/file.txt");
+  const std::string kData = "FileData!!!";
+  const base::Time kTime = base::Time::Now();
+
+  // Case: Error on length query.
+  BlobDataBuilder builder1("uuid1");
+  builder1.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&builder1);
+  FakeFileStreamReader* reader = new FakeFileStreamReader(kData);
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+  reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
+  ExpectLocalFileCall(kPath, kTime, 0, reader);
+
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, size_result);
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+
+  // Case: Error on read.
+  BlobDataBuilder builder2("uuid2");
+  builder2.AppendFile(kPath, 0, kData.size(), kTime);
+  this->InitializeReader(&builder2);
+  reader = new FakeFileStreamReader(kData);
+  ExpectLocalFileCall(kPath, kTime, 0, reader);
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  reader->SetReturnError(net::ERR_FILE_NOT_FOUND);
+  reader->SetAsyncRunner(message_loop_.task_runner().get());
+
+  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kData.size()));
+  int bytes_read = 0;
+  int async_bytes_read = 0;
+  EXPECT_EQ(BlobReader::Status::IO_PENDING,
+            reader_->Read(buffer.get(), kData.size(), &bytes_read,
+                          base::Bind(&SetValue<int>, &async_bytes_read)));
+  EXPECT_EQ(net::OK, reader_->net_error());
+  message_loop_.RunUntilIdle();
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, async_bytes_read);
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+}
+
+TEST_F(BlobReaderTest, RangeError) {
+  const std::string kData("Hello!!!");
+  const size_t kDataSize = 8ul;
+  const uint64_t kReadLength = 4ull;
+
+  // Case: offset too high.
+  BlobDataBuilder b("uuid1");
+  b.AppendData(kData);
+  this->InitializeReader(&b);
+  int size_result = -1;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  scoped_refptr<net::IOBuffer> buffer = CreateBuffer(kDataSize);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->SetReadRange(kDataSize + 1, kReadLength));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+
+  // Case: length too long.
+  BlobDataBuilder b2("uuid2");
+  b2.AppendData(kData);
+  this->InitializeReader(&b2);
+  size_result = -1;
+  EXPECT_EQ(BlobReader::Status::DONE,
+            reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+  buffer = CreateBuffer(kDataSize + 1);
+  EXPECT_EQ(BlobReader::Status::NET_ERROR,
+            reader_->SetReadRange(0, kDataSize + 1));
+  EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
+}
+
+}  // namespace
+}  // namespace storage
diff --git a/content/browser/fileapi/blob_url_request_job_unittest.cc b/content/browser/fileapi/blob_url_request_job_unittest.cc
index 9debd4d..96becf0 100644
--- a/content/browser/fileapi/blob_url_request_job_unittest.cc
+++ b/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -115,7 +115,7 @@
         net::URLRequest* request,
         net::NetworkDelegate* network_delegate) const override {
       return new BlobURLRequestJob(request, network_delegate,
-                                   test_->GetSnapshotFromBuilder(),
+                                   test_->GetHandleFromBuilder(),
                                    test_->file_system_context_.get(),
                                    base::ThreadTaskRunnerHandle::Get().get());
     }
@@ -157,6 +157,7 @@
 
   void TearDown() override {
     blob_handle_.reset();
+    request_.reset();
     // Clean up for ASAN
     base::RunLoop run_loop;
     run_loop.RunUntilIdle();
@@ -282,18 +283,19 @@
     *expected_result += std::string(kTestFileSystemFileData2 + 6, 7);
   }
 
-  scoped_ptr<BlobDataSnapshot> GetSnapshotFromBuilder() {
+  storage::BlobDataHandle* GetHandleFromBuilder() {
     if (!blob_handle_) {
       blob_handle_ = blob_context_.AddFinishedBlob(blob_data_.get()).Pass();
     }
-    return blob_handle_->CreateSnapshot().Pass();
+    return blob_handle_.get();
   }
 
   // This only works if all the Blob items have a definite pre-computed length.
   // Otherwise, this will fail a CHECK.
   int64 GetTotalBlobLength() {
     int64 total = 0;
-    scoped_ptr<BlobDataSnapshot> data = GetSnapshotFromBuilder();
+    scoped_ptr<BlobDataSnapshot> data =
+        GetHandleFromBuilder()->CreateSnapshot();
     const auto& items = data->items();
     for (const auto& item : items) {
       int64 length = base::checked_cast<int64>(item->length());
@@ -491,6 +493,27 @@
   EXPECT_EQ(total, length);
 }
 
+TEST_F(BlobURLRequestJobTest, TestGetRangeRequest3) {
+  SetUpFileSystem();
+  std::string result;
+  BuildComplicatedData(&result);
+  net::HttpRequestHeaders extra_headers;
+  extra_headers.SetHeader(net::HttpRequestHeaders::kRange,
+                          net::HttpByteRange::Bounded(0, 2).GetHeaderValue());
+  expected_status_code_ = 206;
+  expected_response_ = result.substr(0, 3);
+  TestRequest("GET", extra_headers);
+
+  EXPECT_EQ(3, request_->response_headers()->GetContentLength());
+
+  int64 first = 0, last = 0, length = 0;
+  EXPECT_TRUE(
+      request_->response_headers()->GetContentRange(&first, &last, &length));
+  EXPECT_EQ(0, first);
+  EXPECT_EQ(2, last);
+  EXPECT_EQ(GetTotalBlobLength(), length);
+}
+
 TEST_F(BlobURLRequestJobTest, TestExtraHeaders) {
   blob_data_->set_content_type(kTestContentType);
   blob_data_->set_content_disposition(kTestContentDisposition);
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index 402e794..18a2fcd 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -5,6 +5,8 @@
 #include "content/browser/frame_host/navigation_handle_impl.h"
 
 #include "content/browser/frame_host/navigator_delegate.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
 #include "net/url_request/redirect_info.h"
 
 namespace content {
@@ -12,7 +14,7 @@
 // static
 scoped_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
     const GURL& url,
-    const bool is_main_frame,
+    bool is_main_frame,
     NavigatorDelegate* delegate) {
   return scoped_ptr<NavigationHandleImpl>(
       new NavigationHandleImpl(url, is_main_frame, delegate));
@@ -22,11 +24,15 @@
                                            const bool is_main_frame,
                                            NavigatorDelegate* delegate)
     : url_(url),
-      net_error_code_(net::OK),
-      state_(DID_START),
       is_main_frame_(is_main_frame),
+      is_post_(false),
+      has_user_gesture_(false),
+      transition_(ui::PAGE_TRANSITION_LINK),
+      is_external_protocol_(false),
+      net_error_code_(net::OK),
       render_frame_host_(nullptr),
       is_same_page_(false),
+      state_(INITIAL),
       is_transferring_(false),
       delegate_(delegate) {
   delegate_->DidStartNavigation(this);
@@ -36,16 +42,46 @@
   delegate_->DidFinishNavigation(this);
 }
 
-const GURL& NavigationHandleImpl::GetURL() const {
+const GURL& NavigationHandleImpl::GetURL() {
   return url_;
 }
 
-net::Error NavigationHandleImpl::GetNetErrorCode() const {
-  return net_error_code_;
+bool NavigationHandleImpl::IsInMainFrame() {
+  return is_main_frame_;
 }
 
-bool NavigationHandleImpl::IsInMainFrame() const {
-  return is_main_frame_;
+bool NavigationHandleImpl::IsPost() {
+  CHECK_NE(INITIAL, state_)
+      << "This accessor should not be called before the request is started.";
+  return is_post_;
+}
+
+const Referrer& NavigationHandleImpl::GetReferrer() {
+  CHECK_NE(INITIAL, state_)
+      << "This accessor should not be called before the request is started.";
+  return sanitized_referrer_;
+}
+
+bool NavigationHandleImpl::HasUserGesture() {
+  CHECK_NE(INITIAL, state_)
+      << "This accessor should not be called before the request is started.";
+  return has_user_gesture_;
+}
+
+ui::PageTransition NavigationHandleImpl::GetPageTransition() {
+  CHECK_NE(INITIAL, state_)
+      << "This accessor should not be called before the request is started.";
+  return transition_;
+}
+
+bool NavigationHandleImpl::IsExternalProtocol() {
+  CHECK_NE(INITIAL, state_)
+      << "This accessor should not be called before the request is started.";
+  return is_external_protocol_;
+}
+
+net::Error NavigationHandleImpl::GetNetErrorCode() {
+  return net_error_code_;
 }
 
 RenderFrameHostImpl* NavigationHandleImpl::GetRenderFrameHost() {
@@ -70,6 +106,91 @@
   return state_ == DID_COMMIT_ERROR_PAGE;
 }
 
+void NavigationHandleImpl::RegisterThrottleForTesting(
+    scoped_ptr<NavigationThrottle> navigation_throttle) {
+  throttles_.push_back(navigation_throttle.Pass());
+}
+
+NavigationThrottle::ThrottleCheckResult
+NavigationHandleImpl::CallWillStartRequestForTesting(
+    bool is_post,
+    const Referrer& sanitized_referrer,
+    bool has_user_gesture,
+    ui::PageTransition transition,
+    bool is_external_protocol) {
+  return WillStartRequest(is_post, sanitized_referrer, has_user_gesture,
+                          transition, is_external_protocol);
+}
+
+NavigationThrottle::ThrottleCheckResult
+NavigationHandleImpl::CallWillRedirectRequestForTesting(
+    const GURL& new_url,
+    bool new_method_is_post,
+    const GURL& new_referrer_url,
+    bool new_is_external_protocol) {
+  return WillRedirectRequest(new_url, new_method_is_post, new_referrer_url,
+                             new_is_external_protocol);
+}
+
+NavigationThrottle::ThrottleCheckResult NavigationHandleImpl::WillStartRequest(
+    bool is_post,
+    const Referrer& sanitized_referrer,
+    bool has_user_gesture,
+    ui::PageTransition transition,
+    bool is_external_protocol) {
+  // Update the navigation parameters.
+  is_post_ = is_post;
+  sanitized_referrer_ = sanitized_referrer;
+  has_user_gesture_ = has_user_gesture;
+  transition_ = transition;
+  is_external_protocol_ = is_external_protocol;
+
+  state_ = WILL_SEND_REQUEST;
+
+  // Register the navigation throttles. The ScopedVector returned by
+  // GetNavigationThrottles is not assigned to throttles_ directly because it
+  // would overwrite any throttle previously added with
+  // RegisterThrottleForTesting.
+  ScopedVector<NavigationThrottle> throttles_to_register =
+      GetContentClient()->browser()->CreateThrottlesForNavigation(this);
+  if (throttles_to_register.size() > 0) {
+    throttles_.insert(throttles_.end(), throttles_to_register.begin(),
+                      throttles_to_register.end());
+    throttles_to_register.weak_clear();
+  }
+
+  // Notify each throttle of the request.
+  for (NavigationThrottle* throttle : throttles_) {
+    NavigationThrottle::ThrottleCheckResult result =
+        throttle->WillStartRequest();
+    if (result == NavigationThrottle::CANCEL_AND_IGNORE)
+      return NavigationThrottle::CANCEL_AND_IGNORE;
+  }
+  return NavigationThrottle::PROCEED;
+}
+
+NavigationThrottle::ThrottleCheckResult
+NavigationHandleImpl::WillRedirectRequest(const GURL& new_url,
+                                          bool new_method_is_post,
+                                          const GURL& new_referrer_url,
+                                          bool new_is_external_protocol) {
+  // Update the navigation parameters.
+  url_ = new_url;
+  is_post_ = new_method_is_post;
+  sanitized_referrer_.url = new_referrer_url;
+  sanitized_referrer_ = Referrer::SanitizeForRequest(url_, sanitized_referrer_);
+  is_external_protocol_ = new_is_external_protocol;
+
+  // Have each throttle be notified of the request.
+  for (NavigationThrottle* throttle : throttles_) {
+    NavigationThrottle::ThrottleCheckResult result =
+        throttle->WillRedirectRequest();
+    if (result == NavigationThrottle::CANCEL_AND_IGNORE)
+      return NavigationThrottle::CANCEL_AND_IGNORE;
+  }
+  return NavigationThrottle::PROCEED;
+}
+
 void NavigationHandleImpl::DidRedirectNavigation(const GURL& new_url) {
   url_ = new_url;
   delegate_->DidRedirectNavigation(this);
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index 4ea8c14..edd7b555 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -9,8 +9,10 @@
 
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -54,19 +56,38 @@
 class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
  public:
   static scoped_ptr<NavigationHandleImpl> Create(const GURL& url,
-                                                 const bool is_main_frame,
+                                                 bool is_main_frame,
                                                  NavigatorDelegate* delegate);
-
   ~NavigationHandleImpl() override;
 
   // NavigationHandle implementation:
-  const GURL& GetURL() const override;
-  net::Error GetNetErrorCode() const override;
-  bool IsInMainFrame() const override;
+  const GURL& GetURL() override;
+  bool IsInMainFrame() override;
+  bool IsPost() override;
+  const Referrer& GetReferrer() override;
+  bool HasUserGesture() override;
+  ui::PageTransition GetPageTransition() override;
+  bool IsExternalProtocol() override;
+  net::Error GetNetErrorCode() override;
   RenderFrameHostImpl* GetRenderFrameHost() override;
   bool IsSamePage() override;
   bool HasCommitted() override;
   bool IsErrorPage() override;
+  void RegisterThrottleForTesting(
+      scoped_ptr<NavigationThrottle> navigation_throttle) override;
+  NavigationThrottle::ThrottleCheckResult CallWillStartRequestForTesting(
+      bool is_post,
+      const Referrer& sanitized_referrer,
+      bool has_user_gesture,
+      ui::PageTransition transition,
+      bool is_external_protocol) override;
+  NavigationThrottle::ThrottleCheckResult CallWillRedirectRequestForTesting(
+      const GURL& new_url,
+      bool new_method_is_post,
+      const GURL& new_referrer_url,
+      bool new_is_external_protocol) override;
+
+  NavigatorDelegate* delegate() const { return delegate_; }
 
   void set_net_error_code(net::Error net_error_code) {
     net_error_code_ = net_error_code;
@@ -81,6 +102,21 @@
     is_transferring_ = is_transferring;
   }
 
+  // Called when the URLRequest will start in the network stack.
+  NavigationThrottle::ThrottleCheckResult WillStartRequest(
+      bool is_post,
+      const Referrer& sanitized_referrer,
+      bool has_user_gesture,
+      ui::PageTransition transition,
+      bool is_external_protocol);
+
+  // Called when the URLRequest will be redirected in the network stack.
+  NavigationThrottle::ThrottleCheckResult WillRedirectRequest(
+      const GURL& new_url,
+      bool new_method_is_post,
+      const GURL& new_referrer_url,
+      bool new_is_external_protocol);
+
   // Called when the navigation was redirected. This will update the |url_| and
   // inform the delegate.
   void DidRedirectNavigation(const GURL& new_url);
@@ -98,7 +134,8 @@
  private:
   // Used to track the state the navigation is currently in.
   enum State {
-    DID_START = 0,
+    INITIAL = 0,
+    WILL_SEND_REQUEST,
     READY_TO_COMMIT,
     DID_COMMIT,
     DID_COMMIT_ERROR_PAGE,
@@ -110,12 +147,19 @@
 
   // See NavigationHandle for a description of those member variables.
   GURL url_;
-  net::Error net_error_code_;
-  State state_;
   const bool is_main_frame_;
+  bool is_post_;
+  Referrer sanitized_referrer_;
+  bool has_user_gesture_;
+  ui::PageTransition transition_;
+  bool is_external_protocol_;
+  net::Error net_error_code_;
   RenderFrameHostImpl* render_frame_host_;
   bool is_same_page_;
 
+  // The state the navigation is in.
+  State state_;
+
   // Whether the navigation is in the middle of a transfer. Set to false when
   // the DidStartProvisionalLoad is received from the new renderer.
   bool is_transferring_;
@@ -124,6 +168,9 @@
   // navigation.
   NavigatorDelegate* delegate_;
 
+  // A list of Throttles registered for this navigation.
+  ScopedVector<NavigationThrottle> throttles_;
+
   DISALLOW_COPY_AND_ASSIGN(NavigationHandleImpl);
 };
 
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index b3888984..f515a696 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -14,6 +14,7 @@
 #include "content/browser/site_instance_impl.h"
 #include "content/common/resource_request_body.h"
 #include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/stream_handle.h"
 #include "content/public/common/content_client.h"
 #include "net/base/load_flags.h"
@@ -179,6 +180,20 @@
   state_ = STARTED;
 
   if (ShouldMakeNetworkRequestForURL(common_params_.url)) {
+    // TODO(clamy): pass the real value for |is_external_protocol| if needed.
+    NavigationThrottle::ThrottleCheckResult result =
+        navigation_handle_->WillStartRequest(
+            begin_params_.method == "POST",
+            Referrer::SanitizeForRequest(common_params_.url,
+                                         common_params_.referrer),
+            begin_params_.has_user_gesture, common_params_.transition, false);
+
+    // Abort the request if needed. This will destroy the NavigationRequest.
+    if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
+      frame_tree_node_->ResetNavigationRequest(false);
+      return false;
+    }
+
     loader_ = NavigationURLLoader::Create(
         frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
         frame_tree_node_->frame_tree_node_id(), info_.Pass(), this);
@@ -211,12 +226,24 @@
 void NavigationRequest::OnRequestRedirected(
     const net::RedirectInfo& redirect_info,
     const scoped_refptr<ResourceResponse>& response) {
-  // TODO(davidben): Track other changes from redirects. These are important
-  // for, e.g., reloads.
   common_params_.url = redirect_info.new_url;
+  begin_params_.method = redirect_info.new_method;
+  common_params_.referrer.url = GURL(redirect_info.new_referrer);
 
-  // TODO(davidben): This where prerender and navigation_interceptor should be
-  // integrated. For now, just always follow all redirects.
+  // TODO(clamy): Have CSP + security upgrade checks here.
+  // TODO(clamy): Kill the renderer if FilterURL fails?
+  // TODO(clamy): pass the real value for |is_external_protocol| if needed.
+  NavigationThrottle::ThrottleCheckResult result =
+      navigation_handle_->WillRedirectRequest(
+          common_params_.url, begin_params_.method == "POST",
+          common_params_.referrer.url, false);
+
+  // Abort the request if needed. This will destroy the NavigationRequest.
+  if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
+    frame_tree_node_->ResetNavigationRequest(false);
+    return;
+  }
+
   loader_->FollowRedirect();
 
   navigation_handle_->DidRedirectNavigation(redirect_info.new_url);
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index a1530b4..b711278 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -164,8 +164,10 @@
   // Note: When the navigation is ready to commit, the url in |common_params|
   // will be set to the final navigation url, obtained after following all
   // redirects.
+  // Note: |common_params_| and |begin_params_| are not const as they can be
+  // modified during redirects.
   CommonNavigationParams common_params_;
-  const BeginNavigationParams begin_params_;
+  BeginNavigationParams begin_params_;
   const RequestNavigationParams request_params_;
   const bool browser_initiated_;
 
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index f9028d9..0759ebf 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -159,7 +159,7 @@
   }
 
   render_frame_host->SetNavigationHandle(
-      NavigationHandleImpl::Create(url, is_main_frame, delegate_));
+      NavigationHandleImpl::Create(validated_url, is_main_frame, delegate_));
 }
 
 void NavigatorImpl::DidFailProvisionalLoadWithError(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 16e89ef..488fad6a 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1361,8 +1361,10 @@
     scoped_refptr<ResourceRequestBody> body) {
   CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kEnableBrowserSideNavigation));
+  CommonNavigationParams validated_params = common_params;
+  GetProcess()->FilterURL(false, &validated_params.url);
   frame_tree_node()->navigator()->OnBeginNavigation(
-      frame_tree_node(), common_params, begin_params, body);
+      frame_tree_node(), validated_params, begin_params, body);
 }
 
 void RenderFrameHostImpl::OnDispatchLoad() {
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index 2eace36..f8e556c1 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -318,6 +318,9 @@
     int size;
     if (!buffer_->ShareToProcess(filter->PeerHandle(), &handle, &size))
       return false;
+    // TODO(erikchen): Temporary debugging to help track down crash.
+    // http://crbug.com/527588.
+    CHECK_LE(size, 512 * 1024);
     filter->Send(new ResourceMsg_SetDataBuffer(
         GetRequestID(), handle, size, filter->peer_pid()));
     sent_first_data_msg_ = true;
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc
new file mode 100644
index 0000000..8dd143c
--- /dev/null
+++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -0,0 +1,154 @@
+// Copyright 2015 The Chromium Authors. 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/loader/navigation_resource_throttle.h"
+
+#include "base/callback.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_controller.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/referrer.h"
+#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "ui/base/page_transition_types.h"
+
+namespace content {
+
+namespace {
+typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
+    UIChecksPerformedCallback;
+
+void CheckWillStartRequestOnUIThread(UIChecksPerformedCallback callback,
+                                     int render_process_id,
+                                     int render_frame_host_id,
+                                     bool is_post,
+                                     const Referrer& sanitized_referrer,
+                                     bool has_user_gesture,
+                                     ui::PageTransition transition,
+                                     bool is_external_protocol) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::PROCEED;
+  RenderFrameHostImpl* render_frame_host =
+      RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
+  if (render_frame_host) {
+    NavigationHandleImpl* navigation_handle =
+        render_frame_host->navigation_handle();
+    if (navigation_handle) {
+      result = navigation_handle->WillStartRequest(is_post, sanitized_referrer,
+                                                   has_user_gesture, transition,
+                                                   is_external_protocol);
+    }
+  }
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::Bind(callback, result));
+}
+
+void CheckWillRedirectRequestOnUIThread(UIChecksPerformedCallback callback,
+                                        int render_process_id,
+                                        int render_frame_host_id,
+                                        const GURL& new_url,
+                                        bool new_method_is_post,
+                                        const GURL& new_referrer_url,
+                                        bool new_is_external_protocol) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::PROCEED;
+  RenderFrameHostImpl* render_frame_host =
+      RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
+  if (render_frame_host) {
+    NavigationHandleImpl* navigation_handle =
+        render_frame_host->navigation_handle();
+    if (navigation_handle) {
+      RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
+      GURL new_validated_url = new_url;
+      rph->FilterURL(false, &new_validated_url);
+      result = navigation_handle->WillRedirectRequest(
+          new_validated_url, new_method_is_post, new_referrer_url,
+          new_is_external_protocol);
+    }
+  }
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::Bind(callback, result));
+}
+}  // namespace
+
+NavigationResourceThrottle::NavigationResourceThrottle(net::URLRequest* request)
+    : request_(request), weak_ptr_factory_(this) {}
+
+NavigationResourceThrottle::~NavigationResourceThrottle() {}
+
+void NavigationResourceThrottle::WillStartRequest(bool* defer) {
+  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+  if (!info)
+    return;
+
+  int render_process_id, render_frame_id;
+  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
+    return;
+
+  bool is_external_protocol =
+      !info->GetContext()->GetRequestContext()->job_factory()->IsHandledURL(
+          request_->url());
+  UIChecksPerformedCallback callback =
+      base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
+                 weak_ptr_factory_.GetWeakPtr());
+  DCHECK(request_->method() == "POST" || request_->method() == "GET");
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&CheckWillStartRequestOnUIThread, callback, render_process_id,
+                 render_frame_id, request_->method() == "POST",
+                 Referrer::SanitizeForRequest(
+                     request_->url(), Referrer(GURL(request_->referrer()),
+                                               info->GetReferrerPolicy())),
+                 info->HasUserGesture(), info->GetPageTransition(),
+                 is_external_protocol));
+  *defer = true;
+}
+
+void NavigationResourceThrottle::WillRedirectRequest(
+    const net::RedirectInfo& redirect_info,
+    bool* defer) {
+  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+  if (!info)
+    return;
+
+  int render_process_id, render_frame_id;
+  if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
+    return;
+
+  bool new_is_external_protocol =
+      !info->GetContext()->GetRequestContext()->job_factory()->IsHandledURL(
+          request_->url());
+  DCHECK(redirect_info.new_method == "POST" ||
+         redirect_info.new_method == "GET");
+  UIChecksPerformedCallback callback =
+      base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
+                 weak_ptr_factory_.GetWeakPtr());
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&CheckWillRedirectRequestOnUIThread, callback,
+                 render_process_id, render_frame_id, redirect_info.new_url,
+                 redirect_info.new_method == "POST",
+                 GURL(redirect_info.new_referrer), new_is_external_protocol));
+  *defer = true;
+}
+
+const char* NavigationResourceThrottle::GetNameForLogging() const {
+  return "NavigationResourceThrottle";
+}
+
+void NavigationResourceThrottle::OnUIChecksPerformed(
+    NavigationThrottle::ThrottleCheckResult result) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (result == NavigationThrottle::CANCEL_AND_IGNORE) {
+    controller()->CancelAndIgnore();
+  } else {
+    controller()->Resume();
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/loader/navigation_resource_throttle.h b/content/browser/loader/navigation_resource_throttle.h
new file mode 100644
index 0000000..e46b59d
--- /dev/null
+++ b/content/browser/loader/navigation_resource_throttle.h
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors. 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_LOADER_NAVIGATION_RESOURCE_THROTTLE_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_THROTTLE_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "content/public/browser/resource_throttle.h"
+
+namespace net {
+class URLRequest;
+}
+
+namespace content {
+
+// This ResourceThrottle is used to convey throttling information to the UI
+// thread during navigations. The UI thread can then use its NavigationThrottle
+// mechanism to interact with the navigation.
+class NavigationResourceThrottle : public ResourceThrottle {
+ public:
+  NavigationResourceThrottle(net::URLRequest* request);
+  ~NavigationResourceThrottle() override;
+
+  // ResourceThrottle overrides:
+  void WillStartRequest(bool* defer) override;
+  void WillRedirectRequest(const net::RedirectInfo& redirect_info,
+                           bool* defer) override;
+  const char* GetNameForLogging() const override;
+
+ private:
+  void OnUIChecksPerformed(NavigationThrottle::ThrottleCheckResult result);
+
+  net::URLRequest* request_;
+  base::WeakPtrFactory<NavigationResourceThrottle> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(NavigationResourceThrottle);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_THROTTLE_H_
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index c0694695..1b74147 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -41,6 +41,7 @@
 #include "content/browser/loader/detachable_resource_handler.h"
 #include "content/browser/loader/mime_type_resource_handler.h"
 #include "content/browser/loader/navigation_resource_handler.h"
+#include "content/browser/loader/navigation_resource_throttle.h"
 #include "content/browser/loader/navigation_url_loader_impl_core.h"
 #include "content/browser/loader/power_save_block_resource_throttle.h"
 #include "content/browser/loader/redirect_to_file_resource_handler.h"
@@ -1480,6 +1481,16 @@
                                             plugin_service, request));
 
   ScopedVector<ResourceThrottle> throttles;
+
+  // Add a NavigationResourceThrottle for navigations.
+  // PlzNavigate: the throttle is unnecessary as communication with the UI
+  // thread is handled by the NavigationURLloader.
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableBrowserSideNavigation) &&
+      IsResourceTypeFrame(resource_type)) {
+    throttles.push_back(new NavigationResourceThrottle(request));
+  }
+
   if (delegate_) {
     delegate_->RequestBeginning(request,
                                 resource_context,
diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc
index cab3a10..12b4b80 100644
--- a/content/browser/loader/upload_data_stream_builder.cc
+++ b/content/browser/loader/upload_data_stream_builder.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/loader/upload_data_stream_builder.h"
 
+#include <limits>
 #include <utility>
 #include <vector>
 
@@ -13,11 +14,11 @@
 #include "content/common/resource_request_body.h"
 #include "net/base/elements_upload_data_stream.h"
 #include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_disk_cache_entry_element_reader.h"
 #include "net/base/upload_file_element_reader.h"
 #include "storage/browser/blob/blob_data_handle.h"
-#include "storage/browser/blob/blob_data_snapshot.h"
+#include "storage/browser/blob/blob_reader.h"
 #include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/upload_blob_element_reader.h"
 
 namespace disk_cache {
 class Entry;
@@ -69,89 +70,15 @@
   DISALLOW_COPY_AND_ASSIGN(FileElementReader);
 };
 
-// This owns the provided ResourceRequestBody. This is necessary to ensure the
-// BlobData and open disk cache entries survive until upload completion.
-class DiskCacheElementReader : public net::UploadDiskCacheEntryElementReader {
- public:
-  DiskCacheElementReader(ResourceRequestBody* resource_request_body,
-                         disk_cache::Entry* disk_cache_entry,
-                         int disk_cache_stream_index,
-                         const ResourceRequestBody::Element& element)
-      : net::UploadDiskCacheEntryElementReader(disk_cache_entry,
-                                               disk_cache_stream_index,
-                                               element.offset(),
-                                               element.length()),
-        resource_request_body_(resource_request_body) {
-    DCHECK_EQ(ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY,
-              element.type());
-  }
-
-  ~DiskCacheElementReader() override {}
-
- private:
-  scoped_refptr<ResourceRequestBody> resource_request_body_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiskCacheElementReader);
-};
-
-void ResolveBlobReference(
-    ResourceRequestBody* body,
-    storage::BlobStorageContext* blob_context,
-    const ResourceRequestBody::Element& element,
-    std::vector<std::pair<const ResourceRequestBody::Element*,
-                          const storage::BlobDataItem*>>* resolved_elements) {
-  DCHECK(blob_context);
-  scoped_ptr<storage::BlobDataHandle> handle =
-      blob_context->GetBlobDataFromUUID(element.blob_uuid());
-  DCHECK(handle);
-  if (!handle)
-    return;
-
-  // TODO(dmurph): Create a reader for blobs instead of decomposing the blob
-  // and storing the snapshot on the request to keep the resources around.
-  // Currently a handle is attached to the request in the resource dispatcher
-  // host, so we know the blob won't go away, but it's not very clear or useful.
-  scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot();
-  // If there is no element in the referred blob data, just return.
-  if (snapshot->items().empty())
-    return;
-
-  // Append the elements in the referenced blob data.
-  for (const auto& item : snapshot->items()) {
-    DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type());
-    resolved_elements->push_back(
-        std::make_pair(item->data_element_ptr(), item.get()));
-  }
-  const void* key = snapshot.get();
-  body->SetUserData(key, snapshot.release());
-}
-
 }  // namespace
 
 scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
     ResourceRequestBody* body,
     storage::BlobStorageContext* blob_context,
     storage::FileSystemContext* file_system_context,
-    base::TaskRunner* file_task_runner) {
-  // Resolve all blob elements.
-  std::vector<std::pair<const ResourceRequestBody::Element*,
-                        const storage::BlobDataItem*>> resolved_elements;
-  for (size_t i = 0; i < body->elements()->size(); ++i) {
-    const ResourceRequestBody::Element& element = (*body->elements())[i];
-    if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) {
-      ResolveBlobReference(body, blob_context, element, &resolved_elements);
-    } else if (element.type() !=
-               ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY) {
-      resolved_elements.push_back(std::make_pair(&element, nullptr));
-    } else {
-      NOTREACHED();
-    }
-  }
-
+    base::SingleThreadTaskRunner* file_task_runner) {
   ScopedVector<net::UploadElementReader> element_readers;
-  for (const auto& element_and_blob_item_pair : resolved_elements) {
-    const ResourceRequestBody::Element& element =
-        *element_and_blob_item_pair.first;
+  for (const auto& element : *body->elements()) {
     switch (element.type()) {
       case ResourceRequestBody::Element::TYPE_BYTES:
         element_readers.push_back(new BytesElementReader(body, element));
@@ -172,22 +99,18 @@
                 element.length(),
                 element.expected_modification_time()));
         break;
-      case ResourceRequestBody::Element::TYPE_BLOB:
-        // Blob elements should be resolved beforehand.
-        // TODO(dmurph): Create blob reader and store the snapshot in there.
-        NOTREACHED();
-        break;
-      case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: {
-        // TODO(gavinp): If Build() is called with a DataElement of
-        // TYPE_DISK_CACHE_ENTRY then this code won't work because we won't call
-        // ResolveBlobReference() and so we won't find |item|. Is this OK?
-        const storage::BlobDataItem* item = element_and_blob_item_pair.second;
-        element_readers.push_back(
-            new DiskCacheElementReader(body, item->disk_cache_entry(),
-                                       item->disk_cache_stream_index(),
-                                       element));
+      case ResourceRequestBody::Element::TYPE_BLOB: {
+        DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
+        DCHECK_EQ(0ul, element.offset());
+        scoped_ptr<storage::BlobDataHandle> handle =
+            blob_context->GetBlobDataFromUUID(element.blob_uuid());
+        storage::BlobDataHandle* handle_ptr = handle.get();
+        element_readers.push_back(new storage::UploadBlobElementReader(
+            handle_ptr->CreateReader(file_system_context, file_task_runner),
+            handle.Pass()));
         break;
       }
+      case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY:
       case ResourceRequestBody::Element::TYPE_UNKNOWN:
         NOTREACHED();
         break;
diff --git a/content/browser/loader/upload_data_stream_builder.h b/content/browser/loader/upload_data_stream_builder.h
index 228aade7..abbcae82 100644
--- a/content/browser/loader/upload_data_stream_builder.h
+++ b/content/browser/loader/upload_data_stream_builder.h
@@ -9,7 +9,7 @@
 #include "content/common/content_export.h"
 
 namespace base {
-class TaskRunner;
+class SingleThreadTaskRunner;
 }
 
 namespace storage {
@@ -44,7 +44,7 @@
       ResourceRequestBody* body,
       storage::BlobStorageContext* blob_context,
       storage::FileSystemContext* file_system_context,
-      base::TaskRunner* file_task_runner);
+      base::SingleThreadTaskRunner* file_task_runner);
 };
 
 }  // namespace content
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc
index b3edd5d..e323a4e9 100644
--- a/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -18,11 +18,11 @@
 #include "net/base/test_completion_callback.h"
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/base/upload_data_stream.h"
-#include "net/base/upload_disk_cache_entry_element_reader.h"
 #include "net/base/upload_file_element_reader.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/upload_blob_element_reader.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -31,351 +31,59 @@
 using storage::BlobStorageContext;
 
 namespace content {
-namespace {
 
-const int kTestDiskCacheStreamIndex = 0;
-
-// Our disk cache tests don't need a real data handle since the tests themselves
-// scope the disk cache and entries.
-class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
- private:
-  ~EmptyDataHandle() override {}
-};
-
-scoped_ptr<disk_cache::Backend> CreateInMemoryDiskCache() {
-  scoped_ptr<disk_cache::Backend> cache;
-  net::TestCompletionCallback callback;
-  int rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE,
-                                          net::CACHE_BACKEND_DEFAULT,
-                                          base::FilePath(), 0,
-                                          false, nullptr, nullptr, &cache,
-                                          callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
-
-  return cache.Pass();
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
-                                                const char* key,
-                                                const std::string& data) {
-  disk_cache::Entry* temp_entry = nullptr;
-  net::TestCompletionCallback callback;
-  int rv = cache->CreateEntry(key, &temp_entry, callback.callback());
-  if (callback.GetResult(rv) != net::OK)
-    return nullptr;
-  disk_cache::ScopedEntryPtr entry(temp_entry);
-
-  scoped_refptr<net::StringIOBuffer> iobuffer = new net::StringIOBuffer(data);
-  rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
-                        iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
-  return entry.Pass();
-}
-
-bool AreElementsEqual(const net::UploadElementReader& reader,
-                      const ResourceRequestBody::Element& element) {
-  switch(element.type()) {
-    case ResourceRequestBody::Element::TYPE_BYTES: {
-      const net::UploadBytesElementReader* bytes_reader =
-          reader.AsBytesReader();
-      return bytes_reader &&
-          element.length() == bytes_reader->length() &&
-          std::equal(element.bytes(), element.bytes() + element.length(),
-                     bytes_reader->bytes());
-    }
-    case ResourceRequestBody::Element::TYPE_FILE: {
-      const net::UploadFileElementReader* file_reader = reader.AsFileReader();
-      return file_reader &&
-          file_reader->path() == element.path() &&
-          file_reader->range_offset() == element.offset() &&
-          file_reader->range_length() == element.length() &&
-          file_reader->expected_modification_time() ==
-          element.expected_modification_time();
-      break;
-    }
-    case ResourceRequestBody::Element::TYPE_DISK_CACHE_ENTRY: {
-      // TODO(gavinp): Should we be comparing a higher level structure
-      // such as the BlobDataItem so that we can do stronger equality
-      // comparisons?
-      const net::UploadDiskCacheEntryElementReader* disk_cache_entry_reader =
-          reader.AsDiskCacheEntryReaderForTests();
-      return disk_cache_entry_reader &&
-          disk_cache_entry_reader->range_offset_for_tests() ==
-              static_cast<int>(element.offset()) &&
-          disk_cache_entry_reader->range_length_for_tests() ==
-              static_cast<int>(element.length());
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-  return false;
-}
-
-}  // namespace
-
-TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) {
-  base::MessageLoop message_loop;
-  scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
-
-  const char kData[] = "123";
-  const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
-  const uint64 kFileOffset = 10U;
-  const uint64 kFileLength = 100U;
-  const base::Time kFileTime = base::Time::FromDoubleT(999);
-  const int64 kIdentifier = 12345;
-
-  request_body->AppendBytes(kData, arraysize(kData) - 1);
-  request_body->AppendFileRange(base::FilePath(kFilePath),
-                                kFileOffset, kFileLength, kFileTime);
-  request_body->set_identifier(kIdentifier);
-
-  scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
-      request_body.get(), NULL, NULL,
-      base::ThreadTaskRunnerHandle::Get().get()));
-
-  EXPECT_EQ(kIdentifier, upload->identifier());
-  ASSERT_TRUE(upload->GetElementReaders());
-  ASSERT_EQ(request_body->elements()->size(),
-            upload->GetElementReaders()->size());
-
-  const net::UploadBytesElementReader* r1 =
-      (*upload->GetElementReaders())[0]->AsBytesReader();
-  ASSERT_TRUE(r1);
-  EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
-
-  const net::UploadFileElementReader* r2 =
-      (*upload->GetElementReaders())[1]->AsFileReader();
-  ASSERT_TRUE(r2);
-  EXPECT_EQ(kFilePath, r2->path().value());
-  EXPECT_EQ(kFileOffset, r2->range_offset());
-  EXPECT_EQ(kFileLength, r2->range_length());
-  EXPECT_EQ(kFileTime, r2->expected_modification_time());
-}
-
-TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
+TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
   base::MessageLoop message_loop;
   {
-    // Setup blob data for testing.
-    base::Time time1, time2;
-    base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1);
-    base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2);
+    scoped_refptr<ResourceRequestBody> request_body = new ResourceRequestBody;
 
-    BlobStorageContext blob_storage_context;
+    const std::string kBlob = "blobuuid";
+    const std::string kBlobData = "blobdata";
+    const char kData[] = "123";
+    const base::FilePath::StringType kFilePath = FILE_PATH_LITERAL("abc");
+    const uint64 kFileOffset = 10U;
+    const uint64 kFileLength = 100U;
+    const base::Time kFileTime = base::Time::FromDoubleT(999);
+    const int64 kIdentifier = 12345;
 
-    const std::string blob_id0("id-0");
-    scoped_ptr<BlobDataBuilder> blob_data_builder(
-        new BlobDataBuilder(blob_id0));
-    scoped_ptr<BlobDataHandle> handle1 =
-        blob_storage_context.AddFinishedBlob(blob_data_builder.get());
+    BlobStorageContext context;
+    BlobDataBuilder builder(kBlob);
+    builder.AppendData(kBlobData);
+    scoped_ptr<BlobDataHandle> handle = context.AddFinishedBlob(&builder);
 
-    const std::string blob_id1("id-1");
-    const std::string kBlobData = "BlobData";
-    blob_data_builder.reset(new BlobDataBuilder(blob_id1));
-    blob_data_builder->AppendData(kBlobData);
-    blob_data_builder->AppendFile(
-        base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
-    scoped_ptr<BlobDataHandle> handle2 =
-        blob_storage_context.AddFinishedBlob(blob_data_builder.get());
-
-    const std::string blob_id2("id-2");
-    const std::string kDiskCacheData = "DiskCacheData";
-    scoped_ptr<disk_cache::Backend> disk_cache_backend =
-        CreateInMemoryDiskCache();
-    ASSERT_TRUE(disk_cache_backend);
-    disk_cache::ScopedEntryPtr disk_cache_entry =
-        CreateDiskCacheEntry(disk_cache_backend.get(), "a key", kDiskCacheData);
-    ASSERT_TRUE(disk_cache_entry);
-    blob_data_builder.reset(new BlobDataBuilder(blob_id2));
-    blob_data_builder->AppendDiskCacheEntry(
-        new EmptyDataHandle(), disk_cache_entry.get(),
-        kTestDiskCacheStreamIndex);
-    scoped_ptr<BlobDataHandle> handle3 =
-        blob_storage_context.AddFinishedBlob(blob_data_builder.get());
-
-    // Setup upload data elements for comparison.
-    ResourceRequestBody::Element blob_element1, blob_element2, blob_element3;
-    blob_element1.SetToBytes(kBlobData.c_str(), kBlobData.size());
-    blob_element2.SetToFilePathRange(
-        base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
-    blob_element3.SetToDiskCacheEntryRange(0, kDiskCacheData.size());
-
-    ResourceRequestBody::Element upload_element1, upload_element2;
-    upload_element1.SetToBytes("Hello", 5);
-    upload_element2.SetToFilePathRange(
-        base::FilePath(FILE_PATH_LITERAL("foo1.txt")), 0, 20, time2);
-
-    // Test no blob reference.
-    scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
-    request_body->AppendBytes(
-        upload_element1.bytes(),
-        upload_element1.length());
-    request_body->AppendFileRange(
-        upload_element2.path(),
-        upload_element2.offset(),
-        upload_element2.length(),
-        upload_element2.expected_modification_time());
+    request_body->AppendBytes(kData, arraysize(kData) - 1);
+    request_body->AppendFileRange(base::FilePath(kFilePath), kFileOffset,
+                                  kFileLength, kFileTime);
+    request_body->AppendBlob(kBlob);
+    request_body->set_identifier(kIdentifier);
 
     scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
+        request_body.get(), &context, NULL,
         base::ThreadTaskRunnerHandle::Get().get()));
 
+    EXPECT_EQ(kIdentifier, upload->identifier());
     ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(2U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], upload_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], upload_element2));
+    ASSERT_EQ(request_body->elements()->size(),
+              upload->GetElementReaders()->size());
 
-    // Test having only one blob reference that refers to empty blob data.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBlob(blob_id0);
+    const net::UploadBytesElementReader* r1 =
+        (*upload->GetElementReaders())[0]->AsBytesReader();
+    ASSERT_TRUE(r1);
+    EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
 
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(0U, upload->GetElementReaders()->size());
+    const net::UploadFileElementReader* r2 =
+        (*upload->GetElementReaders())[1]->AsFileReader();
+    ASSERT_TRUE(r2);
+    EXPECT_EQ(kFilePath, r2->path().value());
+    EXPECT_EQ(kFileOffset, r2->range_offset());
+    EXPECT_EQ(kFileLength, r2->range_length());
+    EXPECT_EQ(kFileTime, r2->expected_modification_time());
 
-    // Test having only one blob reference.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBlob(blob_id1);
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(2U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], blob_element2));
-
-    // Test having one blob reference which refers to a disk cache entry.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBlob(blob_id2);
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, nullptr,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(1U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], blob_element3));
-
-    // Test having one blob reference at the beginning.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBlob(blob_id1);
-    request_body->AppendBytes(
-        upload_element1.bytes(),
-        upload_element1.length());
-    request_body->AppendFileRange(
-        upload_element2.path(),
-        upload_element2.offset(),
-        upload_element2.length(),
-        upload_element2.expected_modification_time());
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(4U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], blob_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[2], upload_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[3], upload_element2));
-
-    // Test having one blob reference at the end.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBytes(
-        upload_element1.bytes(),
-        upload_element1.length());
-    request_body->AppendFileRange(
-        upload_element2.path(),
-        upload_element2.offset(),
-        upload_element2.length(),
-        upload_element2.expected_modification_time());
-    request_body->AppendBlob(blob_id1);
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(4U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], upload_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], upload_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[2], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[3], blob_element2));
-
-    // Test having one blob reference in the middle.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBytes(
-        upload_element1.bytes(),
-        upload_element1.length());
-    request_body->AppendBlob(blob_id1);
-    request_body->AppendFileRange(
-        upload_element2.path(),
-        upload_element2.offset(),
-        upload_element2.length(),
-        upload_element2.expected_modification_time());
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(4U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], upload_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[2], blob_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[3], upload_element2));
-
-    // Test having multiple blob references.
-    request_body = new ResourceRequestBody();
-    request_body->AppendBlob(blob_id1);
-    request_body->AppendBytes(
-        upload_element1.bytes(),
-        upload_element1.length());
-    request_body->AppendBlob(blob_id1);
-    request_body->AppendBlob(blob_id1);
-    request_body->AppendFileRange(
-        upload_element2.path(),
-        upload_element2.offset(),
-        upload_element2.length(),
-        upload_element2.expected_modification_time());
-
-    upload = UploadDataStreamBuilder::Build(
-        request_body.get(), &blob_storage_context, NULL,
-        base::ThreadTaskRunnerHandle::Get().get());
-    ASSERT_TRUE(upload->GetElementReaders());
-    ASSERT_EQ(8U, upload->GetElementReaders()->size());
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[0], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[1], blob_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[2], upload_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[3], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[4], blob_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[5], blob_element1));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[6], blob_element2));
-    EXPECT_TRUE(AreElementsEqual(
-        *(*upload->GetElementReaders())[7], upload_element2));
+    const storage::UploadBlobElementReader* r3 =
+        static_cast<storage::UploadBlobElementReader*>(
+            (*upload->GetElementReaders())[2]);
+    ASSERT_TRUE(r3);
+    EXPECT_EQ("blobuuid", r3->uuid());
   }
   // Clean up for ASAN.
   base::RunLoop().RunUntilIdle();
@@ -402,9 +110,6 @@
     scoped_ptr<BlobDataHandle> handle =
         blob_storage_context.AddFinishedBlob(blob_data_builder.get());
 
-    ResourceRequestBody::Element blob_element;
-    blob_element.SetToFilePathRange(test_blob_path, 0, kZeroLength, blob_time);
-
     scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
     scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
         request_body.get(), &blob_storage_context, NULL,
@@ -421,9 +126,6 @@
     ASSERT_TRUE(upload->GetElementReaders());
     const auto& readers = *upload->GetElementReaders();
     ASSERT_EQ(3U, readers.size());
-    EXPECT_TRUE(AreElementsEqual(*readers[0], blob_element));
-    EXPECT_TRUE(AreElementsEqual(*readers[1], blob_element));
-    EXPECT_TRUE(AreElementsEqual(*readers[2], blob_element));
 
     net::TestCompletionCallback init_callback;
     ASSERT_EQ(net::ERR_IO_PENDING, upload->Init(init_callback.callback()));
diff --git a/content/browser/media/android/browser_demuxer_android.cc b/content/browser/media/android/browser_demuxer_android.cc
index b90fb39..aab876394 100644
--- a/content/browser/media/android/browser_demuxer_android.cc
+++ b/content/browser/media/android/browser_demuxer_android.cc
@@ -5,7 +5,7 @@
 #include "content/browser/media/android/browser_demuxer_android.h"
 
 #include "content/common/media/media_player_messages_android.h"
-#include "media/base/android/media_codec_player.h"
+#include "media/base/android/media_task_runner.h"
 #include "media/base/media_switches.h"
 
 namespace content {
@@ -56,7 +56,7 @@
 BrowserDemuxerAndroid::BrowserDemuxerAndroid()
     : BrowserMessageFilter(MediaPlayerMsgStart) {
   task_runner_ =
-      media::MediaPlayerAndroid::UseMediaThread() ?
+      media::UseMediaThreadForMediaPlayback() ?
       media::GetMediaTaskRunner().get() :
       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get();
 
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc
index ff9463d6..76c22c19 100644
--- a/content/browser/media/android/browser_media_player_manager.cc
+++ b/content/browser/media/android/browser_media_player_manager.cc
@@ -29,6 +29,7 @@
 #include "media/base/android/media_codec_player.h"
 #include "media/base/android/media_player_bridge.h"
 #include "media/base/android/media_source_player.h"
+#include "media/base/android/media_task_runner.h"
 #include "media/base/android/media_url_interceptor.h"
 
 using media::MediaCodecPlayer;
@@ -164,7 +165,7 @@
     }
 
     case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
-      if (MediaPlayerAndroid::UseMediaThread()) {
+      if (media::UseMediaThreadForMediaPlayback()) {
         return new MediaCodecPlayer(
             media_player_params.player_id,
             weak_ptr_factory_.GetWeakPtr(),
diff --git a/content/browser/media/android/media_drm_credential_manager.h b/content/browser/media/android/media_drm_credential_manager.h
index 56794e1..97bfe80 100644
--- a/content/browser/media/android/media_drm_credential_manager.h
+++ b/content/browser/media/android/media_drm_credential_manager.h
@@ -52,7 +52,7 @@
   bool ResetCredentialsInternal(SecurityLevel security_level);
 
   // The MediaDrmBridge object used to perform the credential reset.
-  scoped_ptr<media::MediaDrmBridge> media_drm_bridge_;
+  media::ScopedMediaDrmBridgePtr media_drm_bridge_;
 
   // The callback provided by the caller.
   ResetCredentialsCB reset_credentials_cb_;
diff --git a/content/browser/media/cdm/browser_cdm_manager.cc b/content/browser/media/cdm/browser_cdm_manager.cc
index eefceba..7294ef4 100644
--- a/content/browser/media/cdm/browser_cdm_manager.cc
+++ b/content/browser/media/cdm/browser_cdm_manager.cc
@@ -32,6 +32,7 @@
 
 using media::BrowserCdm;
 using media::MediaKeys;
+using media::ScopedBrowserCdmPtr;
 
 namespace {
 
@@ -541,7 +542,7 @@
   scoped_ptr<SimplePromise> promise(new SimplePromise(
       weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
 
-  scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
+  ScopedBrowserCdmPtr cdm(media::CreateBrowserCdm(
       key_system, use_hw_secure_codecs,
       BROWSER_CDM_MANAGER_CB(OnSessionMessage),
       BROWSER_CDM_MANAGER_CB(OnSessionClosed),
diff --git a/content/browser/media/cdm/browser_cdm_manager.h b/content/browser/media/cdm/browser_cdm_manager.h
index 629a49d..857cdd1 100644
--- a/content/browser/media/cdm/browser_cdm_manager.h
+++ b/content/browser/media/cdm/browser_cdm_manager.h
@@ -20,6 +20,7 @@
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/common/permission_status.mojom.h"
 #include "ipc/ipc_message.h"
+#include "media/base/browser_cdm.h"
 #include "media/base/cdm_promise.h"
 #include "media/base/eme_constants.h"
 #include "media/base/media_keys.h"
@@ -27,10 +28,6 @@
 
 struct CdmHostMsg_CreateSessionAndGenerateRequest_Params;
 
-namespace media {
-class BrowserCdm;
-}
-
 namespace content {
 
 // This class manages all CDM objects. It receives control operations from the
@@ -200,7 +197,7 @@
   // |cdm_id|.
 
   // Map of managed BrowserCdms.
-  typedef base::ScopedPtrHashMap<uint64, scoped_ptr<media::BrowserCdm>> CdmMap;
+  typedef base::ScopedPtrHashMap<uint64, media::ScopedBrowserCdmPtr> CdmMap;
   CdmMap cdm_map_;
 
   // Map of CDM's security origin.
diff --git a/content/browser/memory/memory_message_filter.cc b/content/browser/memory/memory_message_filter.cc
index b386717..8f6fe48 100644
--- a/content/browser/memory/memory_message_filter.cc
+++ b/content/browser/memory/memory_message_filter.cc
@@ -31,4 +31,9 @@
   Send(new MemoryMsg_SetPressureNotificationsSuppressed(suppressed));
 }
 
+void MemoryMessageFilter::SendSimulatePressureNotification(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  Send(new MemoryMsg_SimulatePressureNotification(level));
+}
+
 }  // namespace content
diff --git a/content/browser/memory/memory_message_filter.h b/content/browser/memory/memory_message_filter.h
index 122a7aa9..d489c25 100644
--- a/content/browser/memory/memory_message_filter.h
+++ b/content/browser/memory/memory_message_filter.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_MEMORY_MEMORY_MESSAGE_FILTER_H_
 #define CONTENT_BROWSER_MEMORY_MEMORY_MESSAGE_FILTER_H_
 
+#include "base/memory/memory_pressure_listener.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_message_filter.h"
 
@@ -22,6 +23,8 @@
   bool OnMessageReceived(const IPC::Message& message) override;
 
   void SendSetPressureNotificationsSuppressed(bool suppressed);
+  void SendSimulatePressureNotification(
+      base::MemoryPressureListener::MemoryPressureLevel level);
 
  protected:
   ~MemoryMessageFilter() override;
diff --git a/content/browser/memory/memory_pressure_controller.cc b/content/browser/memory/memory_pressure_controller.cc
index 41738e5..67f31b4a 100644
--- a/content/browser/memory/memory_pressure_controller.cc
+++ b/content/browser/memory/memory_pressure_controller.cc
@@ -5,7 +5,6 @@
 #include "content/browser/memory/memory_pressure_controller.h"
 
 #include "base/bind.h"
-#include "base/memory/memory_pressure_listener.h"
 #include "content/browser/memory/memory_message_filter.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -51,7 +50,7 @@
     bool suppressed) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     // Note that passing base::Unretained(this) is safe here because the
-    // controller is a leaky singleton (i.e. it is never deleted).
+    // controller is a leaky singleton.
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&MemoryPressureController::
@@ -64,10 +63,33 @@
   base::MemoryPressureListener::SetNotificationsSuppressed(suppressed);
 
   // Enable/disable suppressing memory notifications in all child processes.
-  for (MemoryMessageFilterSet::iterator it = memory_message_filters_.begin();
-       it != memory_message_filters_.end(); ++it) {
-    it->get()->SendSetPressureNotificationsSuppressed(suppressed);
+  for (const scoped_refptr<MemoryMessageFilter>& filter :
+       memory_message_filters_)
+    filter->SendSetPressureNotificationsSuppressed(suppressed);
+}
+
+void MemoryPressureController::SimulatePressureNotificationInAllProcesses(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  DCHECK_NE(level, base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE);
+
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    // Note that passing base::Unretained(this) is safe here because the
+    // controller is a leaky singleton.
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(&MemoryPressureController::
+                       SimulatePressureNotificationInAllProcesses,
+                   base::Unretained(this), level));
+    return;
   }
+
+  // Simulate memory pressure notification in the browser process.
+  base::MemoryPressureListener::SimulatePressureNotification(level);
+
+  // Simulate memory pressure notification in all child processes.
+  for (const scoped_refptr<MemoryMessageFilter>& filter :
+       memory_message_filters_)
+    filter->SendSimulatePressureNotification(level);
 }
 
 }  // namespace content
diff --git a/content/browser/memory/memory_pressure_controller.h b/content/browser/memory/memory_pressure_controller.h
index 848b2d4..934f847 100644
--- a/content/browser/memory/memory_pressure_controller.h
+++ b/content/browser/memory/memory_pressure_controller.h
@@ -8,6 +8,7 @@
 #include <set>
 
 #include "base/callback.h"
+#include "base/memory/memory_pressure_listener.h"
 #include "base/memory/singleton.h"
 #include "content/common/content_export.h"
 
@@ -21,8 +22,10 @@
   void OnMemoryMessageFilterAdded(MemoryMessageFilter* filter);
   void OnMemoryMessageFilterRemoved(MemoryMessageFilter* filter);
 
-  // This method can be called from any thread.
+  // These methods can be called from any thread.
   void SetPressureNotificationsSuppressedInAllProcesses(bool suppressed);
+  void SimulatePressureNotificationInAllProcesses(
+      base::MemoryPressureListener::MemoryPressureLevel level);
 
   // This method can be called from any thread.
   static MemoryPressureController* GetInstance();
diff --git a/content/browser/memory/memory_pressure_controller_browsertest.cc b/content/browser/memory/memory_pressure_controller_browsertest.cc
index b1452d8..c0d4069 100644
--- a/content/browser/memory/memory_pressure_controller_browsertest.cc
+++ b/content/browser/memory/memory_pressure_controller_browsertest.cc
@@ -27,6 +27,17 @@
   return suppressed == base::get<0>(param);
 }
 
+MATCHER_P(IsSimulateMessage, level, "") {
+  // Ensure that the message is deleted upon return.
+  scoped_ptr<IPC::Message> message(arg);
+  if (message == nullptr)
+    return false;
+  MemoryMsg_SimulatePressureNotification::Param param;
+  if (!MemoryMsg_SimulatePressureNotification::Read(message.get(), &param))
+    return false;
+  return level == base::get<0>(param);
+}
+
 class MemoryMessageFilterForTesting : public MemoryMessageFilter {
  public:
   MOCK_METHOD1(Send, bool(IPC::Message* message));
@@ -62,6 +73,10 @@
 };
 
 class MemoryPressureControllerBrowserTest : public ContentBrowserTest {
+ public:
+  MOCK_METHOD1(OnMemoryPressure,
+               void(base::MemoryPressureListener::MemoryPressureLevel level));
+
  protected:
   void SetPressureNotificationsSuppressedInAllProcessesAndWait(
       bool suppressed) {
@@ -69,6 +84,13 @@
         ->SetPressureNotificationsSuppressedInAllProcesses(suppressed);
     RunAllPendingInMessageLoop(BrowserThread::IO);
   }
+
+  void SimulatePressureNotificationInAllProcessesAndWait(
+      base::MemoryPressureListener::MemoryPressureLevel level) {
+    MemoryPressureController::GetInstance()
+        ->SimulatePressureNotificationInAllProcesses(level);
+    RunAllPendingInMessageLoop(BrowserThread::IO);
+  }
 };
 
 IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
@@ -128,4 +150,56 @@
   EXPECT_FALSE(base::MemoryPressureListener::AreNotificationsSuppressed());
 }
 
+IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
+                       SimulatePressureNotificationInAllProcesses) {
+  const auto MEMORY_PRESSURE_LEVEL_MODERATE =
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
+  const auto MEMORY_PRESSURE_LEVEL_CRITICAL =
+      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
+
+  scoped_refptr<MemoryMessageFilterForTesting> filter(
+      new MemoryMessageFilterForTesting);
+  scoped_ptr<base::MemoryPressureListener> listener(
+      new base::MemoryPressureListener(
+          base::Bind(&MemoryPressureControllerBrowserTest::OnMemoryPressure,
+                     base::Unretained(this))));
+
+  NavigateToURL(shell(), GetTestUrl("", "title.html"));
+
+  filter->Add();
+
+  EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_CRITICAL)))
+      .Times(1);
+  EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_CRITICAL)).Times(1);
+  SimulatePressureNotificationInAllProcessesAndWait(
+      MEMORY_PRESSURE_LEVEL_CRITICAL);
+  RunAllPendingInMessageLoop();  // Wait for the listener to run.
+
+  // Enable suppressing memory pressure notifications in all processes. This
+  // should have no impact on simulating memory pressure notifications.
+  EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(true))).Times(1);
+  SetPressureNotificationsSuppressedInAllProcessesAndWait(true);
+
+  EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
+      .Times(1);
+  EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_MODERATE)).Times(1);
+  SimulatePressureNotificationInAllProcessesAndWait(
+      MEMORY_PRESSURE_LEVEL_MODERATE);
+  RunAllPendingInMessageLoop();  // Wait for the listener to run.
+
+  // Disable suppressing memory pressure notifications in all processes. This
+  // should have no impact on simulating memory pressure notifications.
+  EXPECT_CALL(*filter, Send(IsSetSuppressedMessage(false))).Times(1);
+  SetPressureNotificationsSuppressedInAllProcessesAndWait(false);
+
+  EXPECT_CALL(*filter, Send(IsSimulateMessage(MEMORY_PRESSURE_LEVEL_MODERATE)))
+      .Times(1);
+  EXPECT_CALL(*this, OnMemoryPressure(MEMORY_PRESSURE_LEVEL_MODERATE)).Times(1);
+  SimulatePressureNotificationInAllProcessesAndWait(
+      MEMORY_PRESSURE_LEVEL_MODERATE);
+  RunAllPendingInMessageLoop();  // Wait for the listener to run.
+
+  filter->Remove();
+}
+
 }  // namespace content
diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc
index aa8cea5..f75619d 100644
--- a/content/browser/push_messaging/push_messaging_message_filter.cc
+++ b/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -64,15 +64,15 @@
                             PUSH_GETREGISTRATION_STATUS_LAST + 1);
 }
 
-// Curries the |success| and |curve25519dh| parameters over to |callback| and
+// Curries the |success| and |p256dh| parameters over to |callback| and
 // posts a task to invoke |callback| on the IO thread.
 void ForwardPublicEncryptionKeysToIOThreadProxy(
     const PushMessagingService::PublicKeyCallback& callback,
     bool success,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(callback, success, curve25519dh));
+                          base::Bind(callback, success, p256dh));
 }
 
 // Concatenates the subscription id with the endpoint base to create a new
@@ -148,7 +148,7 @@
 
   void DidRegister(const RegisterData& data,
                    const std::string& push_registration_id,
-                   const std::vector<uint8_t>& curve25519dh,
+                   const std::vector<uint8_t>& p256dh,
                    PushRegistrationStatus status);
 
   // Private Unregister methods on UI thread -----------------------------------
@@ -366,7 +366,7 @@
     const RegisterData& data,
     const std::string& push_registration_id,
     bool success,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!success) {
     SendRegisterError(data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE);
@@ -374,7 +374,7 @@
   }
 
   SendRegisterSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE,
-                      push_registration_id, curve25519dh);
+                      push_registration_id, p256dh);
 }
 
 void PushMessagingMessageFilter::DidGetSenderIdFromStorage(
@@ -451,14 +451,14 @@
 void PushMessagingMessageFilter::Core::DidRegister(
     const RegisterData& data,
     const std::string& push_registration_id,
-    const std::vector<uint8_t>& curve25519dh,
+    const std::vector<uint8_t>& p256dh,
     PushRegistrationStatus status) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&PushMessagingMessageFilter::PersistRegistrationOnIO,
-                   io_parent_, data, push_registration_id, curve25519dh));
+                   io_parent_, data, push_registration_id, p256dh));
   } else {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
@@ -470,7 +470,7 @@
 void PushMessagingMessageFilter::PersistRegistrationOnIO(
     const RegisterData& data,
     const std::string& push_registration_id,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   service_worker_context_->StoreRegistrationUserData(
       data.service_worker_registration_id,
@@ -479,19 +479,19 @@
       push_registration_id,
       base::Bind(&PushMessagingMessageFilter::DidPersistRegistrationOnIO,
                  weak_factory_io_to_io_.GetWeakPtr(),
-                 data, push_registration_id, curve25519dh));
+                 data, push_registration_id, p256dh));
 }
 
 void PushMessagingMessageFilter::DidPersistRegistrationOnIO(
     const RegisterData& data,
     const std::string& push_registration_id,
-    const std::vector<uint8_t>& curve25519dh,
+    const std::vector<uint8_t>& p256dh,
     ServiceWorkerStatusCode service_worker_status) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (service_worker_status == SERVICE_WORKER_OK) {
     SendRegisterSuccess(data,
                         PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE,
-                        push_registration_id, curve25519dh);
+                        push_registration_id, p256dh);
   } else {
     // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count.
     SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR);
@@ -516,7 +516,7 @@
     const RegisterData& data,
     PushRegistrationStatus status,
     const std::string& push_registration_id,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   // Only called from IO thread, but would be safe to call from UI thread.
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (push_endpoint_base_.is_empty()) {
@@ -531,12 +531,12 @@
         data.render_frame_id,
         data.request_id,
         CreatePushEndpoint(push_endpoint_base_, push_registration_id),
-        curve25519dh));
+        p256dh));
   } else {
     Send(new PushMessagingMsg_SubscribeFromWorkerSuccess(
         data.request_id,
         CreatePushEndpoint(push_endpoint_base_, push_registration_id),
-        curve25519dh));
+        p256dh));
   }
   RecordRegistrationStatus(status);
 }
@@ -847,7 +847,7 @@
     int request_id,
     const GURL& endpoint,
     bool success,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!success) {
     PushGetRegistrationStatus status =
@@ -860,7 +860,7 @@
   }
 
   Send(new PushMessagingMsg_GetRegistrationSuccess(request_id, endpoint,
-                                                   curve25519dh));
+                                                   p256dh));
 
   RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS);
 }
diff --git a/content/browser/push_messaging/push_messaging_message_filter.h b/content/browser/push_messaging/push_messaging_message_filter.h
index c95d477..737baf2 100644
--- a/content/browser/push_messaging/push_messaging_message_filter.h
+++ b/content/browser/push_messaging/push_messaging_message_filter.h
@@ -76,7 +76,7 @@
   void DidGetEncryptionKeys(const RegisterData& data,
                             const std::string& push_registration_id,
                             bool success,
-                            const std::vector<uint8_t>& curve25519dh);
+                            const std::vector<uint8_t>& p256dh);
 
   void DidGetSenderIdFromStorage(const RegisterData& data,
                                  const std::string& sender_id,
@@ -85,12 +85,12 @@
   // Called via PostTask from UI thread.
   void PersistRegistrationOnIO(const RegisterData& data,
                                const std::string& push_registration_id,
-                               const std::vector<uint8_t>& curve25519dh);
+                               const std::vector<uint8_t>& p256dh);
 
   void DidPersistRegistrationOnIO(
       const RegisterData& data,
       const std::string& push_registration_id,
-      const std::vector<uint8_t>& curve25519dh,
+      const std::vector<uint8_t>& p256dh,
       ServiceWorkerStatusCode service_worker_status);
 
   // Called both from IO thread, and via PostTask from UI thread.
@@ -100,7 +100,7 @@
   void SendRegisterSuccess(const RegisterData& data,
                            PushRegistrationStatus status,
                            const std::string& push_registration_id,
-                           const std::vector<uint8_t>& curve25519dh);
+                           const std::vector<uint8_t>& p256dh);
 
   // Unsubscribe methods on IO thread ------------------------------------------
 
@@ -152,7 +152,7 @@
   void DidGetRegistrationKeys(int request_id,
                               const GURL& endpoint,
                               bool success,
-                              const std::vector<uint8_t>& curve25519dh);
+                              const std::vector<uint8_t>& p256dh);
 
   // Helper methods on IO thread -----------------------------------------------
 
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc
index d1c5e46..02d53e8a 100644
--- a/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -172,16 +172,11 @@
 // Mac doesn't yet have a gesture recognizer, so can't support turning touch
 // events into scroll gestures.
 // Will be fixed with http://crbug.com/337142
-// Flaky on Android, see https://crbug.com/376668.
+// Flaky on all platforms, see https://crbug.com/376668.
 //
 // Verify the test infrastructure works - we can touch-scroll the page and get a
 // touchcancel as expected.
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
-#define MAYBE_DefaultAuto DISABLED_DefaultAuto
-#else
-#define MAYBE_DefaultAuto DefaultAuto
-#endif
-IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_DefaultAuto) {
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_DefaultAuto) {
   LoadURL();
 
   bool scrolled = DoTouchScroll(gfx::Point(50, 50), gfx::Vector2d(0, 45));
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/content/browser/renderer_host/input/web_input_event_builders_mac.mm
index 5b454d0..00d34f8 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_mac.mm
+++ b/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -526,11 +526,18 @@
   // shouldn't be used by Blink to scroll the current page, because we want
   // to get that key back for it to do history navigation. Hence, the
   // corresponding situation on OS X is to set this for cmd key presses.
+
   // cmd-b and and cmd-i are system wide key bindings that OS X doesn't
   // handle for us, so the editor handles them.
-  return event.modifiers & blink::WebInputEvent::MetaKey &&
-         event.windowsKeyCode != ui::VKEY_B &&
-         event.windowsKeyCode != ui::VKEY_I;
+  int modifiers = event.modifiers & blink::WebInputEvent::InputModifiers;
+  if (modifiers == blink::WebInputEvent::MetaKey &&
+      event.windowsKeyCode == ui::VKEY_B)
+    return false;
+  if (modifiers == blink::WebInputEvent::MetaKey &&
+      event.windowsKeyCode == ui::VKEY_I)
+    return false;
+
+  return event.modifiers & blink::WebInputEvent::MetaKey;
 }
 
 blink::WebMouseWheelEvent::Phase PhaseForNSEventPhase(
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index 0d5cc56..2c550651 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
 
 #import <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h>
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/keycodes/dom/dom_code.h"
@@ -207,3 +208,39 @@
     EXPECT_EQ(WebInputEvent::KeyUp, web_event.type);
   }
 }
+
+// Test system key events recognition.
+TEST(WebInputEventBuilderMacTest, SystemKeyEvents) {
+  // Cmd + B should not be treated as system event.
+  NSEvent* macEvent =
+      BuildFakeKeyEvent(kVK_ANSI_B, 'B', NSCommandKeyMask, NSKeyDown);
+  WebKeyboardEvent webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_FALSE(webEvent.isSystemKey);
+
+  // Cmd + I should not be treated as system event.
+  macEvent = BuildFakeKeyEvent(kVK_ANSI_I, 'I', NSCommandKeyMask, NSKeyDown);
+  webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_FALSE(webEvent.isSystemKey);
+
+  // Cmd + <some other modifier> + <B|I> should be treated as system event.
+  macEvent = BuildFakeKeyEvent(kVK_ANSI_B, 'B',
+                               NSCommandKeyMask | NSShiftKeyMask, NSKeyDown);
+  webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_TRUE(webEvent.isSystemKey);
+  macEvent = BuildFakeKeyEvent(kVK_ANSI_I, 'I',
+                               NSCommandKeyMask | NSControlKeyMask, NSKeyDown);
+  webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_TRUE(webEvent.isSystemKey);
+
+  // Cmd + <any letter other then B and I> should be treated as system event.
+  macEvent = BuildFakeKeyEvent(kVK_ANSI_S, 'S', NSCommandKeyMask, NSKeyDown);
+  webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_TRUE(webEvent.isSystemKey);
+
+  // Cmd + <some other modifier> + <any letter other then B and I> should be
+  // treated as system event.
+  macEvent = BuildFakeKeyEvent(kVK_ANSI_S, 'S',
+                               NSCommandKeyMask | NSShiftKeyMask, NSKeyDown);
+  webEvent = WebKeyboardEventBuilder::Build(macEvent);
+  EXPECT_TRUE(webEvent.isSystemKey);
+}
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h
index 4a6b035..586e4d97 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -14,7 +14,7 @@
 //
 // AudioInputHostMsg_CloseStream -> OnCloseStream -> AIC::Close ->
 //
-// This class is owned by BrowserRenderProcessHost and instantiated on UI
+// This class is owned by RenderProcessHostImpl and instantiated on UI
 // thread. All other operations and method calls happen on IO thread, so we
 // need to be extra careful about the lifetime of this object.
 //
diff --git a/content/browser/renderer_host/media/audio_output_device_enumerator.cc b/content/browser/renderer_host/media/audio_output_device_enumerator.cc
index 516cde0..13f875f6 100644
--- a/content/browser/renderer_host/media/audio_output_device_enumerator.cc
+++ b/content/browser/renderer_host/media/audio_output_device_enumerator.cc
@@ -26,7 +26,7 @@
   // If no devices in enumeration, return a list with a default device
   if (device_names.empty()) {
     snapshot.push_back({media::AudioManagerBase::kDefaultDeviceId,
-                        media::AudioManagerBase::kDefaultDeviceName,
+                        media::AudioManager::GetDefaultDeviceName(),
                         audio_manager->GetDefaultOutputStreamParameters()});
     return snapshot;
   }
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 8196c87..df16bce5 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -82,8 +82,11 @@
 bool IsValidDeviceId(const std::string& device_id) {
   static const std::string::size_type kValidLength = 64;
 
-  if (device_id.empty())
+  if (device_id.empty() ||
+      device_id == media::AudioManagerBase::kDefaultDeviceId ||
+      device_id == media::AudioManagerBase::kCommunicationsDeviceId) {
     return true;
+  }
 
   if (device_id.length() != kValidLength)
     return false;
@@ -386,7 +389,8 @@
     return;
 
   if (!IsValidDeviceId(device_id)) {
-    Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, false, DummyParams()));
+    Send(new AudioMsg_NotifyDeviceAuthorized(
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, DummyParams()));
     return;
   }
 
@@ -407,7 +411,8 @@
       output_params.set_effects(info->device.matched_output.effects);
       authorizations_.insert(MakeAuthorizationData(
           stream_id, true, info->device.matched_output_device_id));
-      Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, true, output_params));
+      Send(new AudioMsg_NotifyDeviceAuthorized(
+          stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params));
       return;
     }
   }
@@ -434,7 +439,9 @@
 
   if (!have_access) {
     authorizations_.erase(auth_data);
-    Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, false, DummyParams()));
+    Send(new AudioMsg_NotifyDeviceAuthorized(
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+        DummyParams()));
     return;
   }
 
@@ -457,14 +464,15 @@
 
   if (!device_found) {
     authorizations_.erase(auth_data);
-    Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, false, DummyParams()));
+    Send(new AudioMsg_NotifyDeviceAuthorized(
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, DummyParams()));
     return;
   }
 
   auth_data->second.first = true;
   auth_data->second.second = device_info.unique_id;
-  Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, true,
-                                           device_info.output_params));
+  Send(new AudioMsg_NotifyDeviceAuthorized(
+      stream_id, media::OUTPUT_DEVICE_STATUS_OK, device_info.output_params));
 }
 
 void AudioRendererHost::OnCreateStream(int stream_id,
@@ -586,11 +594,18 @@
            << ", render_frame_id=" << render_frame_id
            << ", device_id=" << device_id
            << ", security_origin=" << security_origin << ")";
-  if (!LookupById(stream_id) || !IsValidDeviceId(device_id)) {
+  if (!LookupById(stream_id)) {
     Send(new AudioMsg_NotifyOutputDeviceSwitched(
-        stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL));
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
     return;
   }
+
+  if (!IsValidDeviceId(device_id)) {
+    Send(new AudioMsg_NotifyOutputDeviceSwitched(
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND));
+    return;
+  }
+
   GURL gurl_security_origin = ConvertToGURL(security_origin);
   CheckOutputDeviceAccess(
       render_frame_id, device_id, gurl_security_origin,
@@ -606,14 +621,14 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!have_access) {
     Send(new AudioMsg_NotifyOutputDeviceSwitched(
-        stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED));
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED));
     return;
   }
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
     Send(new AudioMsg_NotifyOutputDeviceSwitched(
-        stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL));
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
     return;
   }
 
@@ -640,10 +655,10 @@
     const AudioOutputDeviceInfo& device_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!success) {
-    media::SwitchOutputDeviceResult result =
+    media::OutputDeviceStatus result =
         device_info.unique_id.empty()
-            ? media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND
-            : media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL;
+            ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND
+            : media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
 
     Send(new AudioMsg_NotifyOutputDeviceSwitched(stream_id, result));
     return;
@@ -652,7 +667,7 @@
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
     Send(new AudioMsg_NotifyOutputDeviceSwitched(
-        stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL));
+        stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
     return;
   }
 
@@ -664,8 +679,8 @@
 
 void AudioRendererHost::OnDeviceSwitched(int stream_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  Send(new AudioMsg_NotifyOutputDeviceSwitched(
-      stream_id, media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS));
+  Send(new AudioMsg_NotifyOutputDeviceSwitched(stream_id,
+                                               media::OUTPUT_DEVICE_STATUS_OK));
 }
 
 void AudioRendererHost::SendErrorMessage(int stream_id) {
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index d8dc90d..cfda5ec 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -5,7 +5,7 @@
 // AudioRendererHost serves audio related requests from AudioRenderer which
 // lives inside the render process and provide access to audio hardware.
 //
-// This class is owned by BrowserRenderProcessHost, and instantiated on UI
+// This class is owned by RenderProcessHostImpl, and instantiated on UI
 // thread, but all other operations and method calls happen on IO thread, so we
 // need to be extra careful about the lifetime of this object. AudioManager is a
 // singleton and created in IO thread, audio output streams are also created in
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 559ff12..4e9c3cd 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -75,14 +75,14 @@
   // A list of mock methods.
   MOCK_METHOD3(OnDeviceAuthorized,
                void(int stream_id,
-                    bool success,
+                    media::OutputDeviceStatus device_status,
                     const media::AudioParameters& output_params));
   MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
   MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
   MOCK_METHOD1(OnStreamPaused, void(int stream_id));
   MOCK_METHOD1(OnStreamError, void(int stream_id));
   MOCK_METHOD2(OnOutputDeviceSwitched,
-               void(int stream_id, media::SwitchOutputDeviceResult result));
+               void(int stream_id, media::OutputDeviceStatus result));
 
  private:
   virtual ~MockAudioRendererHost() {
@@ -117,9 +117,9 @@
   }
 
   void OnNotifyDeviceAuthorized(int stream_id,
-                                bool success,
+                                media::OutputDeviceStatus device_status,
                                 const media::AudioParameters& output_params) {
-    OnDeviceAuthorized(stream_id, success, output_params);
+    OnDeviceAuthorized(stream_id, device_status, output_params);
   }
 
   void OnNotifyStreamCreated(
@@ -159,12 +159,12 @@
   }
 
   void OnNotifyOutputDeviceSwitched(int stream_id,
-                                    media::SwitchOutputDeviceResult result) {
+                                    media::OutputDeviceStatus result) {
     switch (result) {
-      case media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS:
-      case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND:
-      case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED:
-      case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL:
+      case media::OUTPUT_DEVICE_STATUS_OK:
+      case media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND:
+      case media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED:
+      case media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL:
         OnOutputDeviceSwitched(stream_id, result);
         break;
       default:
@@ -234,7 +234,9 @@
 
  protected:
   void Create(bool unified_stream) {
-    EXPECT_CALL(*host_.get(), OnDeviceAuthorized(kStreamId, true, _));
+    EXPECT_CALL(
+        *host_.get(),
+        OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _));
     EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
 
     EXPECT_CALL(mirroring_manager_,
@@ -292,7 +294,7 @@
   void SwitchOutputDevice(int stream_id,
                           const std::string& device_id,
                           const url::Origin& security_origin,
-                          media::SwitchOutputDeviceResult expected_result) {
+                          media::OutputDeviceStatus expected_result) {
     EXPECT_CALL(*host_.get(),
                 OnOutputDeviceSwitched(stream_id, expected_result));
     host_->OnSwitchOutputDevice(stream_id, kRenderFrameId, device_id,
@@ -374,28 +376,28 @@
 TEST_F(AudioRendererHostTest, SwitchOutputDevice) {
   Create(false);
   SwitchOutputDevice(kStreamId, kDefaultDeviceID, kDefaultSecurityOrigin,
-                     media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+                     media::OUTPUT_DEVICE_STATUS_OK);
   Close();
 }
 
 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNotAuthorized) {
   Create(false);
   SwitchOutputDevice(kStreamId, kBadDeviceID, kSecurityOrigin,
-                     media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED);
+                     media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED);
   Close();
 }
 
 TEST_F(AudioRendererHostTest, SwitchOutputDeviceInvalidDeviceId) {
   Create(false);
   SwitchOutputDevice(kStreamId, kInvalidDeviceID, kSecurityOrigin,
-                     media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+                     media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND);
   Close();
 }
 
 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNoStream) {
   Create(false);
   SwitchOutputDevice(kBadStreamId, kDefaultDeviceID, kDefaultSecurityOrigin,
-                     media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+                     media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
   Close();
 }
 
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 90aa8a41..2b411e0 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -16,6 +16,7 @@
 #include "base/profiler/scoped_tracker.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
@@ -30,13 +31,13 @@
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/media_device_id.h"
 #include "content/public/browser/media_observer.h"
 #include "content/public/browser/media_request_state.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/media_stream_request.h"
+#include "crypto/hmac.h"
 #include "media/audio/audio_manager_base.h"
 #include "media/audio/audio_parameters.h"
 #include "media/base/channel_layout.h"
@@ -884,8 +885,8 @@
     return false;
 
   for (const StreamDeviceInfo& device_info : cache->devices) {
-    if (content::DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
-                                            device_info.device.id)) {
+    if (DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
+                                   device_info.device.id)) {
       *device_id = device_info.device.id;
       return true;
     }
@@ -926,7 +927,7 @@
   for (const LabeledDeviceRequest& labeled_request : requests_) {
     const DeviceRequest* request = labeled_request.second;
     for (const StreamDeviceInfo& device_info : request->devices) {
-      const std::string source_id = content::GetHMACForMediaDeviceID(
+      const std::string source_id = GetHMACForMediaDeviceID(
           request->salt_callback, request->security_origin, device.id);
       if (device_info.device.id == source_id &&
           device_info.device.type == device.type) {
@@ -1079,10 +1080,8 @@
   if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
       request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT ||
       request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
-    device->id = content::GetHMACForMediaDeviceID(
-        request->salt_callback,
-        request->security_origin,
-        device->id);
+    device->id = GetHMACForMediaDeviceID(request->salt_callback,
+                                         request->security_origin, device->id);
   }
 }
 
@@ -1420,10 +1419,9 @@
   DCHECK(existing_device_info);
   DCHECK(existing_request_state);
 
-  std::string source_id = content::GetHMACForMediaDeviceID(
-      new_request.salt_callback,
-      new_request.security_origin,
-      new_device_info.id);
+  std::string source_id =
+      GetHMACForMediaDeviceID(new_request.salt_callback,
+                              new_request.security_origin, new_device_info.id);
 
   for (const LabeledDeviceRequest& labeled_request : requests_) {
     const DeviceRequest* request = labeled_request.second;
@@ -2135,4 +2133,39 @@
 }
 #endif
 
+// static
+std::string MediaStreamManager::GetHMACForMediaDeviceID(
+    const ResourceContext::SaltCallback& sc,
+    const GURL& security_origin,
+    const std::string& raw_unique_id) {
+  DCHECK(security_origin.is_valid());
+  DCHECK(!raw_unique_id.empty());
+  if (raw_unique_id == media::AudioManagerBase::kDefaultDeviceId ||
+      raw_unique_id == media::AudioManagerBase::kCommunicationsDeviceId) {
+    return raw_unique_id;
+  }
+
+  crypto::HMAC hmac(crypto::HMAC::SHA256);
+  const size_t digest_length = hmac.DigestLength();
+  std::vector<uint8> digest(digest_length);
+  std::string salt = sc.Run();
+  bool result = hmac.Init(security_origin.spec()) &&
+                hmac.Sign(raw_unique_id + salt, &digest[0], digest.size());
+  DCHECK(result);
+  return base::ToLowerASCII(base::HexEncode(&digest[0], digest.size()));
+}
+
+// static
+bool MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+    const ResourceContext::SaltCallback& sc,
+    const GURL& security_origin,
+    const std::string& device_guid,
+    const std::string& raw_unique_id) {
+  DCHECK(security_origin.is_valid());
+  DCHECK(!raw_unique_id.empty());
+  std::string guid_from_raw_device_id =
+      GetHMACForMediaDeviceID(sc, security_origin, raw_unique_id);
+  return guid_from_raw_device_id == device_guid;
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 9dad605..af0658a 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -213,6 +213,21 @@
   // generated stream (or when using --use-fake-ui-for-media-stream).
   void UseFakeUIForTests(scoped_ptr<FakeMediaStreamUIProxy> fake_ui);
 
+  // Generates a hash of a device's unique ID usable by one
+  // particular security origin.
+  static std::string GetHMACForMediaDeviceID(
+      const ResourceContext::SaltCallback& sc,
+      const GURL& security_origin,
+      const std::string& raw_unique_id);
+
+  // Convenience method to check if |device_guid| is an HMAC of
+  // |raw_device_id| for |security_origin|.
+  static bool DoesMediaDeviceIDMatchHMAC(
+      const ResourceContext::SaltCallback& sc,
+      const GURL& security_origin,
+      const std::string& device_guid,
+      const std::string& raw_unique_id);
+
  private:
   // Contains all data needed to keep track of requests.
   class DeviceRequest;
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index fc0028c..9ef2bd3 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -50,6 +50,17 @@
 typedef media::FakeAudioManager AudioManagerPlatform;
 #endif
 
+namespace {
+
+std::string ReturnMockSalt() {
+  return std::string();
+}
+
+ResourceContext::SaltCallback GetMockSaltCallback() {
+  return base::Bind(&ReturnMockSalt);
+}
+
+}  // namespace
 
 // This class mocks the audio manager and overrides the
 // GetAudioInputDeviceNames() method to ensure that we can run our tests on
@@ -182,4 +193,39 @@
   run_loop_.Run();
 }
 
+TEST_F(MediaStreamManagerTest, DeviceID) {
+  GURL security_origin("http://localhost");
+  const std::string unique_default_id(
+      media::AudioManagerBase::kDefaultDeviceId);
+  const std::string hashed_default_id =
+      MediaStreamManager::GetHMACForMediaDeviceID(
+          GetMockSaltCallback(), security_origin, unique_default_id);
+  EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+      GetMockSaltCallback(), security_origin, hashed_default_id,
+      unique_default_id));
+  EXPECT_EQ(unique_default_id, hashed_default_id);
+
+  const std::string unique_communications_id(
+      media::AudioManagerBase::kCommunicationsDeviceId);
+  const std::string hashed_communications_id =
+      MediaStreamManager::GetHMACForMediaDeviceID(
+          GetMockSaltCallback(), security_origin, unique_communications_id);
+  EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+      GetMockSaltCallback(), security_origin, hashed_communications_id,
+      unique_communications_id));
+  EXPECT_EQ(unique_communications_id, hashed_communications_id);
+
+  const std::string unique_other_id("other-unique-id");
+  const std::string hashed_other_id =
+      MediaStreamManager::GetHMACForMediaDeviceID(
+          GetMockSaltCallback(), security_origin, unique_other_id);
+  EXPECT_TRUE(MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+      GetMockSaltCallback(), security_origin, hashed_other_id,
+      unique_other_id));
+  EXPECT_NE(unique_other_id, hashed_other_id);
+  EXPECT_EQ(hashed_other_id.size(), 64U);
+  for (const char& c : hashed_other_id)
+    EXPECT_TRUE((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6e0a2ed..8717e3e7 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1260,6 +1260,7 @@
     switches::kDisableDisplayList2dCanvas,
     switches::kDisableDistanceFieldText,
     switches::kDisableEncryptedMedia,
+    switches::kDisableFeatures,
     switches::kDisableFileSystem,
     switches::kDisableGpuCompositing,
     switches::kDisableGpuMemoryBufferVideoFrames,
@@ -1294,11 +1295,11 @@
     switches::kEnableBrowserSideNavigation,
     switches::kEnableCompositorAnimationTimelines,
     switches::kEnableCredentialManagerAPI,
-    switches::kEnableDelayAgnosticAec,
     switches::kEnableDisplayList2dCanvas,
     switches::kEnableDistanceFieldText,
     switches::kEnableExperimentalCanvasFeatures,
     switches::kEnableExperimentalWebPlatformFeatures,
+    switches::kEnableFeatures,
     switches::kEnableGPUClientLogging,
     switches::kEnableGpuClientTracing,
     switches::kEnableGpuMemoryBufferVideoFrames,
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 37cf40e..370cae3 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -265,6 +265,8 @@
 
   BluetoothDispatcherHost* GetBluetoothDispatcherHost();
 
+  bool backgrounded() const { return backgrounded_; };
+
  protected:
   // A proxy for our IPC::Channel that lives on the IO thread (see
   // browser_process.h)
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index de8176b..e08efc9 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -258,18 +258,6 @@
   // Tells the renderer view to focus the first (last if reverse is true) node.
   void SetInitialFocus(bool reverse);
 
-  // Get html data by serializing all frames of current page with lists
-  // which contain all resource links that have local copy.
-  // The parameter links contain original URLs of all saved links.
-  // The parameter local_paths contain corresponding local file paths of
-  // all saved links, which matched with vector:links one by one.
-  // The parameter local_directory_name is relative path of directory which
-  // contain all saved auxiliary files included all sub frames and resouces.
-  void GetSerializedHtmlDataForCurrentPageWithLocalLinks(
-      const std::vector<GURL>& links,
-      const std::vector<base::FilePath>& local_paths,
-      const base::FilePath& local_directory_name);
-
   // Notifies the RenderViewHost that its load state changed.
   void LoadStateChanged(const GURL& url,
                         const net::LoadStateWithParam& load_state,
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 37fef07..1b407058 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -5,7 +5,6 @@
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 
 #include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 9e7b36a..8cfa8bd 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -350,7 +350,16 @@
     devtools_proxy_->NotifyWorkerReadyForInspection();
 }
 
+void EmbeddedWorkerInstance::OnScriptReadStarted() {
+  starting_phase_ = SCRIPT_READ_STARTED;
+}
+
+void EmbeddedWorkerInstance::OnScriptReadFinished() {
+  starting_phase_ = SCRIPT_READ_FINISHED;
+}
+
 void EmbeddedWorkerInstance::OnScriptLoaded() {
+  FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoaded());
   starting_phase_ = SCRIPT_LOADED;
 }
 
@@ -386,6 +395,7 @@
 }
 
 void EmbeddedWorkerInstance::OnScriptLoadFailed() {
+  FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoadFailed());
 }
 
 void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
@@ -540,6 +550,10 @@
       return "Script evaluated";
     case THREAD_STARTED:
       return "Thread started";
+    case SCRIPT_READ_STARTED:
+      return "Script read started";
+    case SCRIPT_READ_FINISHED:
+      return "Script read finished";
     case STARTING_PHASE_MAX_VALUE:
       NOTREACHED();
   }
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index eccba27..05731a0 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -53,8 +53,7 @@
     STOPPING,
   };
 
-  // This enum is used in UMA histograms, so don't change the order or remove
-  // entries.
+  // This enum is used in UMA histograms. Append-only.
   enum StartingPhase {
     NOT_STARTING,
     ALLOCATING_PROCESS,
@@ -63,7 +62,12 @@
     SCRIPT_DOWNLOADING,
     SCRIPT_LOADED,
     SCRIPT_EVALUATED,
-    THREAD_STARTED,  // Happens after SENT_START_WORKER and before SCRIPT_LOADED
+    THREAD_STARTED,  // Happens after SCRIPT_LOADED and before SCRIPT_EVALUATED
+    // Script read happens after SENT_START_WORKER and before SCRIPT_LOADED
+    // (installed scripts only)
+    SCRIPT_READ_STARTED,
+    SCRIPT_READ_FINISHED,
+    // Add new values here.
     STARTING_PHASE_MAX_VALUE,
   };
 
@@ -78,6 +82,8 @@
     virtual void OnStopped(Status old_status) {}
     // The browser-side IPC endpoint for communication with the worker died.
     virtual void OnDetached(Status old_status) {}
+    virtual void OnScriptLoaded() {}
+    virtual void OnScriptLoadFailed() {}
     virtual void OnReportException(const base::string16& error_message,
                                    int line_number,
                                    int column_number,
@@ -141,6 +147,11 @@
   // Called when the script load request accessed the network.
   void OnNetworkAccessedForScriptLoad();
 
+  // Called when reading the main script from the service worker script cache
+  // begins and ends.
+  void OnScriptReadStarted();
+  void OnScriptReadFinished();
+
   static std::string StatusToString(Status status);
   static std::string StartingPhaseToString(StartingPhase phase);
 
diff --git a/content/browser/service_worker/service_worker_cache_writer.cc b/content/browser/service_worker/service_worker_cache_writer.cc
deleted file mode 100644
index e934300..0000000
--- a/content/browser/service_worker/service_worker_cache_writer.cc
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/service_worker/service_worker_cache_writer.h"
-
-#include <algorithm>
-#include <string>
-
-#include "content/browser/appcache/appcache_response.h"
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_storage.h"
-
-namespace {
-
-const size_t kCopyBufferSize = 16 * 1024;
-
-// Shim class used to turn always-async functions into async-or-result
-// functions. See the comments below near ReadInfoHelper.
-class AsyncOnlyCompletionCallbackAdaptor
-    : public base::RefCounted<AsyncOnlyCompletionCallbackAdaptor> {
- public:
-  explicit AsyncOnlyCompletionCallbackAdaptor(
-      const net::CompletionCallback& callback)
-      : async_(false), result_(net::ERR_IO_PENDING), callback_(callback) {}
-
-  void set_async(bool async) { async_ = async; }
-  bool async() { return async_; }
-  int result() { return result_; }
-
-  void WrappedCallback(int result) {
-    result_ = result;
-    if (async_)
-      callback_.Run(result);
-  }
-
- private:
-  friend class base::RefCounted<AsyncOnlyCompletionCallbackAdaptor>;
-  virtual ~AsyncOnlyCompletionCallbackAdaptor() {}
-
-  bool async_;
-  int result_;
-  net::CompletionCallback callback_;
-};
-
-}  // namespace
-
-namespace content {
-
-int ServiceWorkerCacheWriter::DoLoop(int status) {
-  do {
-    switch (state_) {
-      case STATE_START:
-        status = DoStart(status);
-        break;
-      case STATE_READ_HEADERS_FOR_COMPARE:
-        status = DoReadHeadersForCompare(status);
-        break;
-      case STATE_READ_HEADERS_FOR_COMPARE_DONE:
-        status = DoReadHeadersForCompareDone(status);
-        break;
-      case STATE_READ_DATA_FOR_COMPARE:
-        status = DoReadDataForCompare(status);
-        break;
-      case STATE_READ_DATA_FOR_COMPARE_DONE:
-        status = DoReadDataForCompareDone(status);
-        break;
-      case STATE_READ_HEADERS_FOR_COPY:
-        status = DoReadHeadersForCopy(status);
-        break;
-      case STATE_READ_HEADERS_FOR_COPY_DONE:
-        status = DoReadHeadersForCopyDone(status);
-        break;
-      case STATE_READ_DATA_FOR_COPY:
-        status = DoReadDataForCopy(status);
-        break;
-      case STATE_READ_DATA_FOR_COPY_DONE:
-        status = DoReadDataForCopyDone(status);
-        break;
-      case STATE_WRITE_HEADERS_FOR_PASSTHROUGH:
-        status = DoWriteHeadersForPassthrough(status);
-        break;
-      case STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE:
-        status = DoWriteHeadersForPassthroughDone(status);
-        break;
-      case STATE_WRITE_DATA_FOR_PASSTHROUGH:
-        status = DoWriteDataForPassthrough(status);
-        break;
-      case STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE:
-        status = DoWriteDataForPassthroughDone(status);
-        break;
-      case STATE_WRITE_HEADERS_FOR_COPY:
-        status = DoWriteHeadersForCopy(status);
-        break;
-      case STATE_WRITE_HEADERS_FOR_COPY_DONE:
-        status = DoWriteHeadersForCopyDone(status);
-        break;
-      case STATE_WRITE_DATA_FOR_COPY:
-        status = DoWriteDataForCopy(status);
-        break;
-      case STATE_WRITE_DATA_FOR_COPY_DONE:
-        status = DoWriteDataForCopyDone(status);
-        break;
-      case STATE_DONE:
-        status = DoDone(status);
-        break;
-      default:
-        NOTREACHED() << "Unknown state in DoLoop";
-        state_ = STATE_DONE;
-        break;
-    }
-  } while (status >= net::OK && state_ != STATE_DONE);
-  io_pending_ = (status == net::ERR_IO_PENDING);
-  return status;
-}
-
-ServiceWorkerCacheWriter::ServiceWorkerCacheWriter(
-    const ResponseReaderCreator& reader_creator,
-    const ResponseWriterCreator& writer_creator)
-    : state_(STATE_START),
-      io_pending_(false),
-      comparing_(false),
-      did_replace_(false),
-      reader_creator_(reader_creator),
-      writer_creator_(writer_creator),
-      weak_factory_(this) {}
-
-ServiceWorkerCacheWriter::~ServiceWorkerCacheWriter() {}
-
-net::Error ServiceWorkerCacheWriter::MaybeWriteHeaders(
-    HttpResponseInfoIOBuffer* headers,
-    const OnWriteCompleteCallback& callback) {
-  DCHECK(!io_pending_);
-
-  headers_to_write_ = headers;
-  pending_callback_ = callback;
-  DCHECK_EQ(state_, STATE_START);
-  int result = DoLoop(net::OK);
-
-  // Synchronous errors and successes always go to STATE_DONE.
-  if (result != net::ERR_IO_PENDING)
-    DCHECK_EQ(state_, STATE_DONE);
-
-  // ERR_IO_PENDING has to have one of the STATE_*_DONE states as the next state
-  // (not STATE_DONE itself).
-  if (result == net::ERR_IO_PENDING) {
-    DCHECK(state_ == STATE_READ_HEADERS_FOR_COMPARE_DONE ||
-           state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
-           state_ == STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE)
-        << "Unexpected state: " << state_;
-    io_pending_ = true;
-  }
-
-  return result >= 0 ? net::OK : static_cast<net::Error>(result);
-}
-
-net::Error ServiceWorkerCacheWriter::MaybeWriteData(
-    net::IOBuffer* buf,
-    size_t buf_size,
-    const OnWriteCompleteCallback& callback) {
-  DCHECK(!io_pending_);
-
-  data_to_write_ = buf;
-  len_to_write_ = buf_size;
-  pending_callback_ = callback;
-
-  if (comparing_)
-    state_ = STATE_READ_DATA_FOR_COMPARE;
-  else
-    state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH;
-
-  int result = DoLoop(net::OK);
-
-  // Synchronous completions are always STATE_DONE.
-  if (result != net::ERR_IO_PENDING)
-    DCHECK_EQ(state_, STATE_DONE);
-
-  // Asynchronous completion means the state machine must be waiting in one of
-  // the Done states for an IO operation to complete:
-  if (result == net::ERR_IO_PENDING) {
-    // Note that STATE_READ_HEADERS_FOR_COMPARE_DONE is excluded because the
-    // headers are compared in MaybeWriteHeaders, not here, and
-    // STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write
-    // is done by MaybeWriteHeaders.
-    DCHECK(state_ == STATE_READ_DATA_FOR_COMPARE_DONE ||
-           state_ == STATE_READ_HEADERS_FOR_COPY_DONE ||
-           state_ == STATE_READ_DATA_FOR_COPY_DONE ||
-           state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
-           state_ == STATE_WRITE_DATA_FOR_COPY_DONE ||
-           state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE)
-        << "Unexpected state: " << state_;
-  }
-
-  return result >= 0 ? net::OK : static_cast<net::Error>(result);
-}
-
-int ServiceWorkerCacheWriter::DoStart(int result) {
-  bytes_written_ = 0;
-  compare_reader_ = reader_creator_.Run();
-  if (compare_reader_.get()) {
-    state_ = STATE_READ_HEADERS_FOR_COMPARE;
-    comparing_ = true;
-  } else {
-    // No existing reader, just write the headers back directly.
-    state_ = STATE_WRITE_HEADERS_FOR_PASSTHROUGH;
-    comparing_ = false;
-  }
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoReadHeadersForCompare(int result) {
-  DCHECK(headers_to_write_);
-
-  headers_to_read_ = new HttpResponseInfoIOBuffer;
-  state_ = STATE_READ_HEADERS_FOR_COMPARE_DONE;
-  return ReadInfoHelper(compare_reader_, headers_to_read_.get());
-}
-
-int ServiceWorkerCacheWriter::DoReadHeadersForCompareDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  cached_length_ = headers_to_read_->response_data_size;
-  bytes_compared_ = 0;
-  state_ = STATE_DONE;
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoReadDataForCompare(int result) {
-  DCHECK(data_to_write_);
-
-  data_to_read_ = new net::IOBuffer(len_to_write_);
-  len_to_read_ = len_to_write_;
-  state_ = STATE_READ_DATA_FOR_COMPARE_DONE;
-  compare_offset_ = 0;
-  // If this was an EOF, don't issue a read.
-  if (len_to_write_ > 0)
-    result = ReadDataHelper(compare_reader_, data_to_read_.get(), len_to_read_);
-  return result;
-}
-
-int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
-  DCHECK(data_to_read_);
-  DCHECK(data_to_write_);
-  DCHECK_EQ(len_to_read_, len_to_write_);
-  DCHECK_LE(result + compare_offset_, static_cast<size_t>(len_to_write_));
-
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-
-  // Premature EOF while reading the service worker script cache data to
-  // compare. Fail the comparison.
-  if (result == 0 && len_to_write_ != 0) {
-    comparing_ = false;
-    state_ = STATE_READ_HEADERS_FOR_COPY;
-    return net::OK;
-  }
-
-  // Compare the data from the ServiceWorker script cache to the data from the
-  // network.
-  if (memcmp(data_to_read_->data(), data_to_write_->data() + compare_offset_,
-             result)) {
-    // Data mismatched. This method already validated that all the bytes through
-    // |bytes_compared_| were identical, so copy the first |bytes_compared_|
-    // over, then start writing network data back after the changed point.
-    comparing_ = false;
-    state_ = STATE_READ_HEADERS_FOR_COPY;
-    return net::OK;
-  }
-
-  compare_offset_ += result;
-
-  // This is a little bit tricky. It is possible that not enough data was read
-  // to finish comparing the entire block of data from the network (which is
-  // kept in len_to_write_), so this method may need to issue another read and
-  // return to this state.
-  //
-  // Compare isn't complete yet. Issue another read for the remaining data. Note
-  // that this reuses the same IOBuffer.
-  if (compare_offset_ < static_cast<size_t>(len_to_read_)) {
-    state_ = STATE_READ_DATA_FOR_COMPARE_DONE;
-    return ReadDataHelper(compare_reader_, data_to_read_.get(),
-                          len_to_read_ - compare_offset_);
-  }
-
-  // Cached entry is longer than the network entry but the prefix matches. Copy
-  // just the prefix.
-  if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) {
-    comparing_ = false;
-    state_ = STATE_READ_HEADERS_FOR_COPY;
-    return net::OK;
-  }
-
-  // bytes_compared_ only gets incremented when a full block is compared, to
-  // avoid having to use only parts of the buffered network data.
-  bytes_compared_ += result;
-  state_ = STATE_DONE;
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoReadHeadersForCopy(int result) {
-  bytes_copied_ = 0;
-  copy_reader_ = reader_creator_.Run();
-  headers_to_read_ = new HttpResponseInfoIOBuffer;
-  data_to_copy_ = new net::IOBuffer(kCopyBufferSize);
-  state_ = STATE_READ_HEADERS_FOR_COPY_DONE;
-  return ReadInfoHelper(copy_reader_, headers_to_read_.get());
-}
-
-int ServiceWorkerCacheWriter::DoReadHeadersForCopyDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  state_ = STATE_WRITE_HEADERS_FOR_COPY;
-  return net::OK;
-}
-
-// Write the just-read headers back to the cache.
-// Note that this method must create |writer_|, since the only paths to this
-// state never create a writer.
-// Also note that this *discards* the read headers and replaces them with the
-// net headers.
-int ServiceWorkerCacheWriter::DoWriteHeadersForCopy(int result) {
-  DCHECK(!writer_);
-  writer_ = writer_creator_.Run();
-  state_ = STATE_WRITE_HEADERS_FOR_COPY_DONE;
-  return WriteInfoHelper(writer_, headers_to_write_.get());
-}
-
-int ServiceWorkerCacheWriter::DoWriteHeadersForCopyDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  state_ = STATE_READ_DATA_FOR_COPY;
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoReadDataForCopy(int result) {
-  size_t to_read = std::min(kCopyBufferSize, bytes_compared_ - bytes_copied_);
-  // At this point, all compared bytes have been read. Currently
-  // |data_to_write_| and |len_to_write_| hold the chunk of network input that
-  // caused the comparison failure, so those need to be written back and this
-  // object needs to go into passthrough mode.
-  if (to_read == 0) {
-    state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH;
-    return net::OK;
-  }
-  state_ = STATE_READ_DATA_FOR_COPY_DONE;
-  return ReadDataHelper(copy_reader_, data_to_copy_.get(), to_read);
-}
-
-int ServiceWorkerCacheWriter::DoReadDataForCopyDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  state_ = STATE_WRITE_DATA_FOR_COPY;
-  return result;
-}
-
-int ServiceWorkerCacheWriter::DoWriteDataForCopy(int result) {
-  state_ = STATE_WRITE_DATA_FOR_COPY_DONE;
-  DCHECK_GT(result, 0);
-  return WriteDataHelper(writer_, data_to_copy_.get(), result);
-}
-
-int ServiceWorkerCacheWriter::DoWriteDataForCopyDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  bytes_written_ += result;
-  bytes_copied_ += result;
-  state_ = STATE_READ_DATA_FOR_COPY;
-  return result;
-}
-
-int ServiceWorkerCacheWriter::DoWriteHeadersForPassthrough(int result) {
-  writer_ = writer_creator_.Run();
-  state_ = STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE;
-  return WriteInfoHelper(writer_, headers_to_write_.get());
-}
-
-int ServiceWorkerCacheWriter::DoWriteHeadersForPassthroughDone(int result) {
-  state_ = STATE_DONE;
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoWriteDataForPassthrough(int result) {
-  state_ = STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE;
-  if (len_to_write_ > 0)
-    result = WriteDataHelper(writer_, data_to_write_.get(), len_to_write_);
-  return result;
-}
-
-int ServiceWorkerCacheWriter::DoWriteDataForPassthroughDone(int result) {
-  if (result < 0) {
-    state_ = STATE_DONE;
-    return result;
-  }
-  bytes_written_ += result;
-  state_ = STATE_DONE;
-  return net::OK;
-}
-
-int ServiceWorkerCacheWriter::DoDone(int result) {
-  state_ = STATE_DONE;
-  return net::OK;
-}
-
-// These helpers adapt the AppCache "always use the callback" pattern to the
-// //net "only use the callback for async" pattern using
-// AsyncCompletionCallbackAdaptor.
-//
-// Specifically, these methods return result codes directly for synchronous
-// completions, and only run their callback (which is AsyncDoLoop) for
-// asynchronous completions.
-
-int ServiceWorkerCacheWriter::ReadInfoHelper(
-    const scoped_ptr<ServiceWorkerResponseReader>& reader,
-    HttpResponseInfoIOBuffer* buf) {
-  net::CompletionCallback run_callback = base::Bind(
-      &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr());
-  scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor(
-      new AsyncOnlyCompletionCallbackAdaptor(run_callback));
-  reader->ReadInfo(
-      buf, base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback,
-                      adaptor));
-  adaptor->set_async(true);
-  return adaptor->result();
-}
-
-int ServiceWorkerCacheWriter::ReadDataHelper(
-    const scoped_ptr<ServiceWorkerResponseReader>& reader,
-    net::IOBuffer* buf,
-    int buf_len) {
-  net::CompletionCallback run_callback = base::Bind(
-      &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr());
-  scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor(
-      new AsyncOnlyCompletionCallbackAdaptor(run_callback));
-  reader->ReadData(
-      buf, buf_len,
-      base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback,
-                 adaptor));
-  adaptor->set_async(true);
-  return adaptor->result();
-}
-
-int ServiceWorkerCacheWriter::WriteInfoHelper(
-    const scoped_ptr<ServiceWorkerResponseWriter>& writer,
-    HttpResponseInfoIOBuffer* buf) {
-  did_replace_ = true;
-  net::CompletionCallback run_callback = base::Bind(
-      &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr());
-  scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor(
-      new AsyncOnlyCompletionCallbackAdaptor(run_callback));
-  writer->WriteInfo(
-      buf, base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback,
-                      adaptor));
-  adaptor->set_async(true);
-  return adaptor->result();
-}
-
-int ServiceWorkerCacheWriter::WriteDataHelper(
-    const scoped_ptr<ServiceWorkerResponseWriter>& writer,
-    net::IOBuffer* buf,
-    int buf_len) {
-  net::CompletionCallback run_callback = base::Bind(
-      &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr());
-  scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor(
-      new AsyncOnlyCompletionCallbackAdaptor(run_callback));
-  writer->WriteData(
-      buf, buf_len,
-      base::Bind(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback,
-                 adaptor));
-  adaptor->set_async(true);
-  return adaptor->result();
-}
-
-void ServiceWorkerCacheWriter::AsyncDoLoop(int result) {
-  result = DoLoop(result);
-  // If the result is ERR_IO_PENDING, the pending callback will be run by a
-  // later invocation of AsyncDoLoop.
-  if (result != net::ERR_IO_PENDING) {
-    OnWriteCompleteCallback callback = pending_callback_;
-    pending_callback_.Reset();
-    net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result);
-    io_pending_ = false;
-    callback.Run(error);
-  }
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_cache_writer.h b/content/browser/service_worker/service_worker_cache_writer.h
deleted file mode 100644
index dde71a6..0000000
--- a/content/browser/service_worker/service_worker_cache_writer.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_
-
-#include <map>
-#include <set>
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-
-namespace content {
-
-struct HttpResponseInfoIOBuffer;
-class ServiceWorkerCacheWriterCore;
-class ServiceWorkerResponseReader;
-class ServiceWorkerResponseWriter;
-class ServiceWorkerStorage;
-
-// This class is responsible for possibly updating the ServiceWorker script
-// cache for an installed ServiceWorker main script. If there is no existing
-// cache entry, this class always writes supplied data back to the cache; if
-// there is an existing cache entry, this class only writes supplied data back
-// if there is a cache mismatch.
-//
-// Note that writes done by this class cannot be "short" - ie, if they succeed,
-// they always write all the supplied data back. Therefore completions are
-// signalled with net::Error without a count of bytes written.
-//
-// This class's behavior is modelled as a state machine; see the DoLoop function
-// for comments about this.
-class CONTENT_EXPORT ServiceWorkerCacheWriter {
- public:
-  using OnWriteCompleteCallback = base::Callback<void(net::Error)>;
-
-  // The types for the factory functions passed into the constructor. These are
-  // responsible for creating readers from the existing cache entry and writers
-  // to the new cache entry when called. These are passed in as factories
-  // instead of passing readers and writers in directly to avoid creating
-  // writers to entries that won't be updated, and because this class may need
-  // multiple readers internally.
-  using ResponseReaderCreator =
-      base::Callback<scoped_ptr<ServiceWorkerResponseReader>(void)>;
-  using ResponseWriterCreator =
-      base::Callback<scoped_ptr<ServiceWorkerResponseWriter>(void)>;
-
-  // The existing reader may be null, in which case this instance will
-  // unconditionally write back data supplied to |MaybeWriteHeaders| and
-  // |MaybeWriteData|.
-  ServiceWorkerCacheWriter(const ResponseReaderCreator& reader_creator,
-                           const ResponseWriterCreator& writer_creator);
-
-  ~ServiceWorkerCacheWriter();
-
-  // Writes the supplied |headers| back to the cache. Returns ERR_IO_PENDING if
-  // the write will complete asynchronously, in which case |callback| will be
-  // called when it completes. Otherwise, returns a code other than
-  // ERR_IO_PENDING and does not invoke |callback|. Note that this method will
-  // not necessarily write data back to the cache if the incoming data is
-  // equivalent to the existing cached data. See the source of this function for
-  // details about how this function drives the state machine.
-  net::Error MaybeWriteHeaders(HttpResponseInfoIOBuffer* headers,
-                               const OnWriteCompleteCallback& callback);
-
-  // Writes the supplied body data |data| back to the cache. Returns
-  // ERR_IO_PENDING if the write will complete asynchronously, in which case
-  // |callback| will be called when it completes. Otherwise, returns a code
-  // other than ERR_IO_PENDING and does not invoke |callback|. Note that this
-  // method will not necessarily write data back to the cache if the incoming
-  // data is equivalent to the existing cached data. See the source of this
-  // function for details about how this function drives the state machine.
-  net::Error MaybeWriteData(net::IOBuffer* buf,
-                            size_t buf_size,
-                            const OnWriteCompleteCallback& callback);
-
-  // Returns a count of bytes written back to the cache.
-  size_t bytes_written() const { return bytes_written_; }
-  bool did_replace() const { return did_replace_; }
-
- private:
-  // States for the state machine.
-  //
-  // The state machine flows roughly like this: if there is no existing cache
-  // entry, incoming headers and data are written directly back to the cache
-  // ("passthrough mode", the PASSTHROUGH states). If there is an existing cache
-  // entry, incoming headers and data are compared to the existing cache entry
-  // ("compare mode", the COMPARE states); if at any point the incoming
-  // headers/data are not equal to the cached headers/data, this class copies
-  // the cached data up to the point where the incoming data and the cached data
-  // diverged ("copy mode", the COPY states), then switches to "passthrough
-  // mode" to write the remainder of the incoming data. The overall effect is to
-  // avoid rewriting the cache entry if the incoming data is identical to the
-  // cached data.
-  //
-  // Note that after a call to MaybeWriteHeaders or MaybeWriteData completes,
-  // the machine is always in STATE_DONE, indicating that the call is finished;
-  // those methods are responsible for setting a new initial state.
-  enum State {
-    STATE_START,
-    // Control flows linearly through these four states, then loops from
-    // READ_DATA_FOR_COMPARE_DONE to READ_DATA_FOR_COMPARE, or exits to
-    // READ_HEADERS_FOR_COPY.
-    STATE_READ_HEADERS_FOR_COMPARE,
-    STATE_READ_HEADERS_FOR_COMPARE_DONE,
-    STATE_READ_DATA_FOR_COMPARE,
-    STATE_READ_DATA_FOR_COMPARE_DONE,
-
-    // Control flows linearly through these states, with each pass from
-    // READ_DATA_FOR_COPY to WRITE_DATA_FOR_COPY_DONE copying one block of data
-    // at a time. Control loops from WRITE_DATA_FOR_COPY_DONE back to
-    // READ_DATA_FOR_COPY if there is more data to copy, or exits to
-    // WRITE_DATA_FOR_PASSTHROUGH.
-    STATE_READ_HEADERS_FOR_COPY,
-    STATE_READ_HEADERS_FOR_COPY_DONE,
-    STATE_WRITE_HEADERS_FOR_COPY,
-    STATE_WRITE_HEADERS_FOR_COPY_DONE,
-    STATE_READ_DATA_FOR_COPY,
-    STATE_READ_DATA_FOR_COPY_DONE,
-    STATE_WRITE_DATA_FOR_COPY,
-    STATE_WRITE_DATA_FOR_COPY_DONE,
-
-    // Control flows linearly through these states, with a loop between
-    // WRITE_DATA_FOR_PASSTHROUGH and WRITE_DATA_FOR_PASSTHROUGH_DONE.
-    STATE_WRITE_HEADERS_FOR_PASSTHROUGH,
-    STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE,
-    STATE_WRITE_DATA_FOR_PASSTHROUGH,
-    STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE,
-
-    // This state means "done with the current call; ready for another one."
-    STATE_DONE,
-  };
-
-  // Drives this class's state machine. This function steps the state machine
-  // until one of:
-  //   a) One of the state functions returns an error
-  //   b) The state machine reaches STATE_DONE
-  // A successful value (net::OK or greater) indicates that the requested
-  // operation completed synchronously. A return value of ERR_IO_PENDING
-  // indicates that some step had to submit asynchronous IO for later
-  // completion, and the state machine will resume running (via AsyncDoLoop)
-  // when that asynchronous IO completes. Any other return value indicates that
-  // the requested operation failed synchronously.
-  int DoLoop(int result);
-
-  // State handlers. See function comments in the corresponding source file for
-  // details on these.
-  int DoStart(int result);
-  int DoReadHeadersForCompare(int result);
-  int DoReadHeadersForCompareDone(int result);
-  int DoReadDataForCompare(int result);
-  int DoReadDataForCompareDone(int result);
-  int DoReadHeadersForCopy(int result);
-  int DoReadHeadersForCopyDone(int result);
-  int DoWriteHeadersForCopy(int result);
-  int DoWriteHeadersForCopyDone(int result);
-  int DoReadDataForCopy(int result);
-  int DoReadDataForCopyDone(int result);
-  int DoWriteDataForCopy(int result);
-  int DoWriteDataForCopyDone(int result);
-  int DoWriteHeadersForPassthrough(int result);
-  int DoWriteHeadersForPassthroughDone(int result);
-  int DoWriteDataForPassthrough(int result);
-  int DoWriteDataForPassthroughDone(int result);
-  int DoDone(int result);
-
-  // Wrappers for asynchronous calls. These are responsible for scheduling a
-  // callback to drive the state machine if needed. These either:
-  //   a) Return ERR_IO_PENDING, and schedule a callback to run the state
-  //      machine's Run() later, or
-  //   b) Return some other value and do not schedule a callback.
-  int ReadInfoHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader,
-                     HttpResponseInfoIOBuffer* buf);
-  int ReadDataHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader,
-                     net::IOBuffer* buf,
-                     int buf_len);
-  int WriteInfoHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer,
-                      HttpResponseInfoIOBuffer* buf);
-  int WriteDataHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer,
-                      net::IOBuffer* buf,
-                      int buf_len);
-
-  // Callback used by the above helpers for their IO operations. This is only
-  // run when those IO operations complete asynchronously, in which case it
-  // invokes the synchronous DoLoop function and runs the client callback (the
-  // one passed into MaybeWriteData/MaybeWriteHeaders) if that invocation
-  // of DoLoop completes synchronously.
-  void AsyncDoLoop(int result);
-
-  State state_;
-  // Note that this variable is only used for assertions; it reflects "state !=
-  // DONE && not in synchronous DoLoop".
-  bool io_pending_;
-  bool comparing_;
-
-  scoped_refptr<HttpResponseInfoIOBuffer> headers_to_read_;
-  scoped_refptr<HttpResponseInfoIOBuffer> headers_to_write_;
-  scoped_refptr<net::IOBuffer> data_to_read_;
-  int len_to_read_;
-  scoped_refptr<net::IOBuffer> data_to_copy_;
-  scoped_refptr<net::IOBuffer> data_to_write_;
-  int len_to_write_;
-  OnWriteCompleteCallback pending_callback_;
-
-  size_t cached_length_;
-
-  size_t bytes_compared_;
-  size_t bytes_copied_;
-  size_t bytes_written_;
-
-  bool did_replace_;
-
-  size_t compare_offset_;
-
-  ResponseReaderCreator reader_creator_;
-  ResponseWriterCreator writer_creator_;
-  scoped_ptr<ServiceWorkerResponseReader> compare_reader_;
-  scoped_ptr<ServiceWorkerResponseReader> copy_reader_;
-  scoped_ptr<ServiceWorkerResponseWriter> writer_;
-  base::WeakPtrFactory<ServiceWorkerCacheWriter> weak_factory_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_
diff --git a/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/content/browser/service_worker/service_worker_cache_writer_unittest.cc
deleted file mode 100644
index c58b57b5..0000000
--- a/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ /dev/null
@@ -1,697 +0,0 @@
-// Copyright 2015 The Chromium Authors. 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/service_worker/service_worker_cache_writer.h"
-
-#include <list>
-#include <queue>
-#include <string>
-
-#include "base/stl_util.h"
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-
-// A test implementation of ServiceWorkerResponseReader.
-//
-// This class exposes the ability to expect reads (see ExpectRead*() below).
-// Each call to ReadInfo() or ReadData() consumes another expected read, in the
-// order those reads were expected, so:
-//    reader->ExpectReadInfoOk(5, false);
-//    reader->ExpectReadDataOk("abcdef", false);
-//    reader->ExpectReadDataOk("ghijkl", false);
-// Expects these calls, in this order:
-//    reader->ReadInfo(...);  // reader writes 5 into
-//                            // |info_buf->response_data_size|
-//    reader->ReadData(...);  // reader writes "abcdef" into |buf|
-//    reader->ReadData(...);  // reader writes "ghijkl" into |buf|
-// If an unexpected call happens, this class DCHECKs.
-// If an expected read is marked "async", it will not complete immediately, but
-// must be completed by the test using CompletePendingRead().
-// These is a convenience method AllExpectedReadsDone() which returns whether
-// there are any expected reads that have not yet happened.
-class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader {
- public:
-  MockServiceWorkerResponseReader() : ServiceWorkerResponseReader(0, nullptr) {}
-  ~MockServiceWorkerResponseReader() override {}
-
-  // ServiceWorkerResponseReader overrides
-  void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
-                const net::CompletionCallback& callback) override;
-  void ReadData(net::IOBuffer* buf,
-                int buf_len,
-                const net::CompletionCallback& callback) override;
-
-  // Test helpers. ExpectReadInfo() and ExpectReadData() give precise control
-  // over both the data to be written and the result to return.
-  // ExpectReadInfoOk() and ExpectReadDataOk() are convenience functions for
-  // expecting successful reads, which always have their length as their result.
-
-  // Expect a call to ReadInfo() on this reader. For these functions, |len| will
-  // be used as |response_data_size|, not as the length of this particular read.
-  void ExpectReadInfo(size_t len, bool async, int result);
-  void ExpectReadInfoOk(size_t len, bool async);
-
-  // Expect a call to ReadData() on this reader. For these functions, |len| is
-  // the length of the data to be written back; in ExpectReadDataOk(), |len| is
-  // implicitly the length of |data|.
-  void ExpectReadData(const char* data, size_t len, bool async, int result);
-  void ExpectReadDataOk(const std::string& data, bool async);
-
-  // Complete a pending async read. It is an error to call this function without
-  // a pending async read (ie, a previous call to ReadInfo() or ReadData()
-  // having not run its callback yet).
-  void CompletePendingRead();
-
-  // Returns whether all expected reads have occurred.
-  bool AllExpectedReadsDone() { return expected_reads_.size() == 0; }
-
- private:
-  struct ExpectedRead {
-    ExpectedRead(size_t len, bool async, int result)
-        : data(nullptr), len(len), info(true), async(async), result(result) {}
-    ExpectedRead(const char* data, size_t len, bool async, int result)
-        : data(data), len(len), info(false), async(async), result(result) {}
-    const char* data;
-    size_t len;
-    bool info;
-    bool async;
-    int result;
-  };
-
-  std::queue<ExpectedRead> expected_reads_;
-  scoped_refptr<net::IOBuffer> pending_buffer_;
-  size_t pending_buffer_len_;
-  scoped_refptr<HttpResponseInfoIOBuffer> pending_info_;
-  net::CompletionCallback pending_callback_;
-};
-
-void MockServiceWorkerResponseReader::ReadInfo(
-    HttpResponseInfoIOBuffer* info_buf,
-    const net::CompletionCallback& callback) {
-  DCHECK(!expected_reads_.empty());
-  ExpectedRead expected = expected_reads_.front();
-  EXPECT_TRUE(expected.info);
-  if (expected.async) {
-    pending_info_ = info_buf;
-    pending_callback_ = callback;
-  } else {
-    expected_reads_.pop();
-    info_buf->response_data_size = expected.len;
-    callback.Run(expected.result);
-  }
-}
-
-void MockServiceWorkerResponseReader::ReadData(
-    net::IOBuffer* buf,
-    int buf_len,
-    const net::CompletionCallback& callback) {
-  DCHECK(!expected_reads_.empty());
-  ExpectedRead expected = expected_reads_.front();
-  EXPECT_FALSE(expected.info);
-  if (expected.async) {
-    pending_callback_ = callback;
-    pending_buffer_ = buf;
-    pending_buffer_len_ = static_cast<size_t>(buf_len);
-  } else {
-    expected_reads_.pop();
-    if (expected.len > 0) {
-      size_t to_read = std::min(static_cast<size_t>(buf_len), expected.len);
-      memcpy(buf->data(), expected.data, to_read);
-    }
-    callback.Run(expected.result);
-  }
-}
-
-void MockServiceWorkerResponseReader::ExpectReadInfo(size_t len,
-                                                     bool async,
-                                                     int result) {
-  expected_reads_.push(ExpectedRead(len, async, result));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadInfoOk(size_t len, bool async) {
-  expected_reads_.push(ExpectedRead(len, async, len));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadData(const char* data,
-                                                     size_t len,
-                                                     bool async,
-                                                     int result) {
-  expected_reads_.push(ExpectedRead(data, len, async, result));
-}
-
-void MockServiceWorkerResponseReader::ExpectReadDataOk(const std::string& data,
-                                                       bool async) {
-  expected_reads_.push(
-      ExpectedRead(data.data(), data.size(), async, data.size()));
-}
-
-void MockServiceWorkerResponseReader::CompletePendingRead() {
-  DCHECK(!expected_reads_.empty());
-  ExpectedRead expected = expected_reads_.front();
-  expected_reads_.pop();
-  EXPECT_TRUE(expected.async);
-  if (expected.info) {
-    pending_info_->response_data_size = expected.len;
-  } else {
-    size_t to_read = std::min(pending_buffer_len_, expected.len);
-    if (to_read > 0)
-      memcpy(pending_buffer_->data(), expected.data, to_read);
-  }
-  pending_info_ = nullptr;
-  pending_buffer_ = nullptr;
-  net::CompletionCallback callback = pending_callback_;
-  pending_callback_.Reset();
-  callback.Run(expected.result);
-}
-
-// A test implementation of ServiceWorkerResponseWriter.
-//
-// This class exposes the ability to expect writes (see ExpectWrite*Ok() below).
-// Each write to this class via WriteInfo() or WriteData() consumes another
-// expected write, in the order they were added, so:
-//   writer->ExpectWriteInfoOk(5, false);
-//   writer->ExpectWriteDataOk(6, false);
-//   writer->ExpectWriteDataOk(6, false);
-// Expects these calls, in this order:
-//   writer->WriteInfo(...);  // checks that |buf->response_data_size| == 5
-//   writer->WriteData(...);  // checks that 6 bytes are being written
-//   writer->WriteData(...);  // checks that another 6 bytes are being written
-// If this class receives an unexpected call to WriteInfo() or WriteData(), it
-// DCHECKs.
-// Expected writes marked async do not complete synchronously, but rather return
-// without running their callback and need to be completed with
-// CompletePendingWrite().
-// A convenience method AllExpectedWritesDone() is exposed so tests can ensure
-// that all expected writes have been consumed by matching calls to WriteInfo()
-// or WriteData().
-class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter {
- public:
-  MockServiceWorkerResponseWriter()
-      : ServiceWorkerResponseWriter(0, nullptr),
-        info_written_(0),
-        data_written_(0) {}
-  ~MockServiceWorkerResponseWriter() override {}
-
-  // ServiceWorkerResponseWriter overrides
-  void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
-                 const net::CompletionCallback& callback) override;
-  void WriteData(net::IOBuffer* buf,
-                 int buf_len,
-                 const net::CompletionCallback& callback) override;
-
-  // Enqueue expected writes.
-  void ExpectWriteInfoOk(size_t len, bool async);
-  void ExpectWriteDataOk(size_t len, bool async);
-
-  // Complete a pending asynchronous write. This method DCHECKs unless there is
-  // a pending write (a write for which WriteInfo() or WriteData() has been
-  // called but the callback has not yet been run).
-  void CompletePendingWrite();
-
-  // Returns whether all expected reads have been consumed.
-  bool AllExpectedWritesDone() { return expected_writes_.size() == 0; }
-
- private:
-  struct ExpectedWrite {
-    ExpectedWrite(bool is_info, size_t length, bool async, int result)
-        : is_info(is_info), length(length), async(async), result(result) {}
-    bool is_info;
-    size_t length;
-    bool async;
-    int result;
-  };
-
-  std::queue<ExpectedWrite> expected_writes_;
-
-  size_t info_written_;
-  size_t data_written_;
-
-  net::CompletionCallback pending_callback_;
-};
-
-void MockServiceWorkerResponseWriter::WriteInfo(
-    HttpResponseInfoIOBuffer* info_buf,
-    const net::CompletionCallback& callback) {
-  DCHECK(!expected_writes_.empty());
-  ExpectedWrite write = expected_writes_.front();
-  EXPECT_TRUE(write.is_info);
-  EXPECT_EQ(write.length, static_cast<size_t>(info_buf->response_data_size));
-  info_written_ += info_buf->response_data_size;
-  if (!write.async) {
-    expected_writes_.pop();
-    callback.Run(write.result);
-  } else {
-    pending_callback_ = callback;
-  }
-}
-
-void MockServiceWorkerResponseWriter::WriteData(
-    net::IOBuffer* buf,
-    int buf_len,
-    const net::CompletionCallback& callback) {
-  DCHECK(!expected_writes_.empty());
-  ExpectedWrite write = expected_writes_.front();
-  EXPECT_FALSE(write.is_info);
-  EXPECT_EQ(write.length, static_cast<size_t>(buf_len));
-  data_written_ += buf_len;
-  if (!write.async) {
-    expected_writes_.pop();
-    callback.Run(write.result);
-  } else {
-    pending_callback_ = callback;
-  }
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteInfoOk(size_t length,
-                                                        bool async) {
-  ExpectedWrite expected(true, length, async, length);
-  expected_writes_.push(expected);
-}
-
-void MockServiceWorkerResponseWriter::ExpectWriteDataOk(size_t length,
-                                                        bool async) {
-  ExpectedWrite expected(false, length, async, length);
-  expected_writes_.push(expected);
-}
-
-void MockServiceWorkerResponseWriter::CompletePendingWrite() {
-  DCHECK(!expected_writes_.empty());
-  ExpectedWrite write = expected_writes_.front();
-  DCHECK(write.async);
-  expected_writes_.pop();
-  pending_callback_.Run(write.result);
-}
-
-class ServiceWorkerCacheWriterTest : public ::testing::Test {
- public:
-  ServiceWorkerCacheWriterTest()
-      : readers_deleter_(&readers_), writers_deleter_(&writers_) {}
-
-  void SetUp() override {
-    ::testing::Test::SetUp();
-    cache_writer_.reset(new ServiceWorkerCacheWriter(
-        base::Bind(&ServiceWorkerCacheWriterTest::CreateReader,
-                   base::Unretained(this)),
-        base::Bind(&ServiceWorkerCacheWriterTest::CreateWriter,
-                   base::Unretained(this))));
-    write_complete_ = false;
-  }
-
-  MockServiceWorkerResponseReader* ExpectReader() {
-    scoped_ptr<MockServiceWorkerResponseReader> reader(
-        new MockServiceWorkerResponseReader);
-    MockServiceWorkerResponseReader* borrowed_reader = reader.get();
-    readers_.push_back(reader.release());  // give ownership to |readers_|
-    return borrowed_reader;
-  }
-
-  MockServiceWorkerResponseWriter* ExpectWriter() {
-    scoped_ptr<MockServiceWorkerResponseWriter> writer(
-        new MockServiceWorkerResponseWriter);
-    MockServiceWorkerResponseWriter* borrowed_writer = writer.get();
-    writers_.push_back(writer.release());  // give ownership to |writers_|
-    return borrowed_writer;
-  }
-
- protected:
-  // TODO(ellyjones): when unique_ptr<> is allowed, make these instead:
-  //   std::list<unique_ptr<...>>
-  // Right now, these cannot use scoped_ptr.
-  // Their elements are deleted by the STLElementDeleters below when this object
-  // goes out of scope.
-  std::list<MockServiceWorkerResponseReader*> readers_;
-  std::list<MockServiceWorkerResponseWriter*> writers_;
-  STLElementDeleter<std::list<MockServiceWorkerResponseReader*>>
-      readers_deleter_;
-  STLElementDeleter<std::list<MockServiceWorkerResponseWriter*>>
-      writers_deleter_;
-  scoped_ptr<ServiceWorkerCacheWriter> cache_writer_;
-  bool write_complete_;
-  net::Error last_error_;
-
-  scoped_ptr<ServiceWorkerResponseReader> CreateReader() {
-    if (readers_.empty())
-      return make_scoped_ptr<ServiceWorkerResponseReader>(nullptr);
-    scoped_ptr<ServiceWorkerResponseReader> reader(readers_.front());
-    readers_.pop_front();
-    return reader.Pass();
-  }
-  scoped_ptr<ServiceWorkerResponseWriter> CreateWriter() {
-    if (writers_.empty())
-      return make_scoped_ptr<ServiceWorkerResponseWriter>(nullptr);
-    scoped_ptr<ServiceWorkerResponseWriter> writer(writers_.front());
-    writers_.pop_front();
-    return writer.Pass();
-  }
-
-  ServiceWorkerCacheWriter::OnWriteCompleteCallback CreateWriteCallback() {
-    return base::Bind(&ServiceWorkerCacheWriterTest::OnWriteComplete,
-                      base::Unretained(this));
-  }
-
-  void OnWriteComplete(net::Error error) {
-    write_complete_ = true;
-    last_error_ = error;
-  }
-
-  net::Error WriteHeaders(size_t len) {
-    scoped_refptr<HttpResponseInfoIOBuffer> buf(new HttpResponseInfoIOBuffer);
-    buf->response_data_size = len;
-    return cache_writer_->MaybeWriteHeaders(buf.get(), CreateWriteCallback());
-  }
-
-  net::Error WriteData(const std::string& data) {
-    scoped_refptr<net::IOBuffer> buf = new net::StringIOBuffer(data);
-    return cache_writer_->MaybeWriteData(buf.get(), data.size(),
-                                         CreateWriteCallback());
-  }
-};
-
-// Passthrough tests:
-// In these tests, the ServiceWorkerCacheWriter under test has no existing
-// reader, since no calls to ExpectReader() have been made; this means that
-// there is no existing cached response and the incoming data is written back to
-// the cache directly.
-
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersSync) {
-  const size_t kHeaderSize = 16;
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  writer->ExpectWriteInfoOk(kHeaderSize, false);
-
-  net::Error error = WriteHeaders(kHeaderSize);
-  EXPECT_EQ(net::OK, error);
-  EXPECT_FALSE(write_complete_);
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughHeadersAsync) {
-  size_t kHeaderSize = 16;
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  writer->ExpectWriteInfoOk(kHeaderSize, true);
-
-  net::Error error = WriteHeaders(kHeaderSize);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  EXPECT_FALSE(write_complete_);
-  writer->CompletePendingWrite();
-  EXPECT_TRUE(write_complete_);
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataSync) {
-  const std::string data1 = "abcdef";
-  const std::string data2 = "ghijklmno";
-  size_t response_size = data1.size() + data2.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  writer->ExpectWriteInfoOk(response_size, false);
-  writer->ExpectWriteDataOk(data1.size(), false);
-  writer->ExpectWriteDataOk(data2.size(), false);
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::OK, error);
-
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-
-  error = WriteData(data2);
-  EXPECT_EQ(net::OK, error);
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, PassthroughDataAsync) {
-  const std::string data1 = "abcdef";
-  const std::string data2 = "ghijklmno";
-  size_t response_size = data1.size() + data2.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  writer->ExpectWriteInfoOk(response_size, false);
-  writer->ExpectWriteDataOk(data1.size(), true);
-  writer->ExpectWriteDataOk(data2.size(), true);
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::OK, error);
-
-  error = WriteData(data1);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  writer->CompletePendingWrite();
-  EXPECT_TRUE(write_complete_);
-
-  write_complete_ = false;
-  error = WriteData(data2);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  writer->CompletePendingWrite();
-  EXPECT_TRUE(write_complete_);
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-}
-
-// Comparison tests:
-// For the Compare* tests below, the ServiceWorkerCacheWriter under test has a
-// reader for an existing cached response, so it will compare the response being
-// written to it against the existing cached response.
-
-TEST_F(ServiceWorkerCacheWriterTest, CompareHeadersSync) {
-  size_t response_size = 3;
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  MockServiceWorkerResponseReader* reader = ExpectReader();
-
-  reader->ExpectReadInfoOk(response_size, false);
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::OK, error);
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_TRUE(reader->AllExpectedReadsDone());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkSync) {
-  const std::string data1 = "abcdef";
-  size_t response_size = data1.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  MockServiceWorkerResponseReader* reader = ExpectReader();
-
-  reader->ExpectReadInfoOk(response_size, false);
-  reader->ExpectReadDataOk(data1, false);
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::OK, error);
-
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_TRUE(reader->AllExpectedReadsDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, CompareShortCacheReads) {
-  const size_t kHeaderSize = 16;
-  const std::string& data1 = "abcdef";
-  const std::string& cache_data2 = "ghi";
-  const std::string& cache_data3 = "j";
-  const std::string& cache_data4 = "kl";
-  const std::string& net_data2 = "ghijkl";
-  const std::string& data5 = "mnopqrst";
-
-  MockServiceWorkerResponseReader* reader = ExpectReader();
-  reader->ExpectReadInfo(kHeaderSize, false, kHeaderSize);
-  reader->ExpectReadDataOk(data1, false);
-  reader->ExpectReadDataOk(cache_data2, false);
-  reader->ExpectReadDataOk(cache_data3, false);
-  reader->ExpectReadDataOk(cache_data4, false);
-  reader->ExpectReadDataOk(data5, false);
-
-  net::Error error = WriteHeaders(kHeaderSize);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(net_data2);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data5);
-  EXPECT_EQ(net::OK, error);
-  EXPECT_TRUE(reader->AllExpectedReadsDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataOkAsync) {
-  const std::string data1 = "abcdef";
-  size_t response_size = data1.size();
-
-  MockServiceWorkerResponseReader* reader = ExpectReader();
-
-  reader->ExpectReadInfoOk(response_size, true);
-  reader->ExpectReadDataOk(data1, true);
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  reader->CompletePendingRead();
-
-  error = WriteData(data1);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  reader->CompletePendingRead();
-
-  EXPECT_TRUE(reader->AllExpectedReadsDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-TEST_F(ServiceWorkerCacheWriterTest, CompareDataManyOkAsync) {
-  const std::string expected_data[] = {
-      "abcdef", "ghijkl", "mnopqr", "stuvwxyz",
-  };
-  size_t response_size = 0;
-  for (size_t i = 0; i < arraysize(expected_data); ++i)
-    response_size += expected_data[i].size();
-
-  MockServiceWorkerResponseReader* reader = ExpectReader();
-
-  reader->ExpectReadInfoOk(response_size, true);
-  for (size_t i = 0; i < arraysize(expected_data); ++i) {
-    reader->ExpectReadDataOk(expected_data[i], true);
-  }
-
-  net::Error error = WriteHeaders(response_size);
-  EXPECT_EQ(net::ERR_IO_PENDING, error);
-  reader->CompletePendingRead();
-
-  for (size_t i = 0; i < arraysize(expected_data); ++i) {
-    error = WriteData(expected_data[i]);
-    EXPECT_EQ(net::ERR_IO_PENDING, error);
-    reader->CompletePendingRead();
-    EXPECT_EQ(net::OK, last_error_);
-  }
-
-  EXPECT_TRUE(reader->AllExpectedReadsDone());
-  EXPECT_EQ(0U, cache_writer_->bytes_written());
-}
-
-// This test writes headers and three data blocks data1, data2, data3; data2
-// differs in the cached version. The writer should be asked to rewrite the
-// headers and body with the new value, and the copy reader should be asked to
-// read the header and data1.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopySync) {
-  std::string data1 = "abcdef";
-  std::string cache_data2 = "ghijkl";
-  std::string net_data2 = "mnopqr";
-  std::string data3 = "stuvwxyz";
-  size_t cache_response_size = data1.size() + cache_data2.size() + data3.size();
-  size_t net_response_size = data1.size() + net_data2.size() + data3.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  MockServiceWorkerResponseReader* compare_reader = ExpectReader();
-  MockServiceWorkerResponseReader* copy_reader = ExpectReader();
-
-  compare_reader->ExpectReadInfoOk(cache_response_size, false);
-  compare_reader->ExpectReadDataOk(data1, false);
-  compare_reader->ExpectReadDataOk(cache_data2, false);
-
-  copy_reader->ExpectReadInfoOk(cache_response_size, false);
-  copy_reader->ExpectReadDataOk(data1, false);
-
-  writer->ExpectWriteInfoOk(net_response_size, false);
-  writer->ExpectWriteDataOk(data1.size(), false);
-  writer->ExpectWriteDataOk(net_data2.size(), false);
-  writer->ExpectWriteDataOk(data3.size(), false);
-
-  net::Error error = WriteHeaders(net_response_size);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(net_data2);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data3);
-  EXPECT_EQ(net::OK, error);
-
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
-  EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
-}
-
-// Tests behavior when the cached data is shorter than the network data.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyShort) {
-  std::string data1 = "abcdef";
-  std::string cache_data2 = "mnop";
-  std::string net_data2 = "mnopqr";
-  std::string data3 = "stuvwxyz";
-  size_t cache_response_size = data1.size() + cache_data2.size() + data3.size();
-  size_t net_response_size = data1.size() + net_data2.size() + data3.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  MockServiceWorkerResponseReader* compare_reader = ExpectReader();
-  MockServiceWorkerResponseReader* copy_reader = ExpectReader();
-
-  compare_reader->ExpectReadInfoOk(cache_response_size, false);
-  compare_reader->ExpectReadDataOk(data1, false);
-  compare_reader->ExpectReadDataOk(cache_data2, false);
-  compare_reader->ExpectReadDataOk("", false);  // EOF read
-
-  copy_reader->ExpectReadInfoOk(cache_response_size, false);
-  copy_reader->ExpectReadDataOk(data1, false);
-
-  writer->ExpectWriteInfoOk(net_response_size, false);
-  writer->ExpectWriteDataOk(data1.size(), false);
-  writer->ExpectWriteDataOk(net_data2.size(), false);
-  writer->ExpectWriteDataOk(data3.size(), false);
-
-  net::Error error = WriteHeaders(net_response_size);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(net_data2);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data3);
-  EXPECT_EQ(net::OK, error);
-
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
-  EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
-}
-
-// Tests behavior when the cached data is longer than the network data.
-TEST_F(ServiceWorkerCacheWriterTest, CompareFailedCopyLong) {
-  std::string data1 = "abcdef";
-  std::string cache_data2 = "mnop";
-  std::string net_data2 = "mnop";
-  std::string cache_data3 = "qr";
-  size_t cached_size = data1.size() + cache_data2.size() + cache_data3.size();
-  size_t net_size = data1.size() + net_data2.size();
-
-  MockServiceWorkerResponseWriter* writer = ExpectWriter();
-  MockServiceWorkerResponseReader* compare_reader = ExpectReader();
-  MockServiceWorkerResponseReader* copy_reader = ExpectReader();
-
-  compare_reader->ExpectReadInfoOk(cached_size, false);
-  compare_reader->ExpectReadDataOk(data1, false);
-  compare_reader->ExpectReadDataOk(cache_data2, false);
-
-  // The comparison should fail at the end of |cache_data2|, when the cache
-  // writer realizes the two responses are different sizes, and then the network
-  // data should be written back starting with |net_data2|.
-  copy_reader->ExpectReadInfoOk(cached_size, false);
-  copy_reader->ExpectReadDataOk(data1, false);
-  copy_reader->ExpectReadDataOk(net_data2, false);
-
-  writer->ExpectWriteInfoOk(net_size, false);
-  writer->ExpectWriteDataOk(data1.size(), false);
-  writer->ExpectWriteDataOk(net_data2.size(), false);
-
-  net::Error error = WriteHeaders(net_size);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(data1);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData(net_data2);
-  EXPECT_EQ(net::OK, error);
-  error = WriteData("");
-  EXPECT_EQ(net::OK, error);
-
-  EXPECT_TRUE(writer->AllExpectedWritesDone());
-  EXPECT_TRUE(compare_reader->AllExpectedReadsDone());
-  EXPECT_TRUE(copy_reader->AllExpectedReadsDone());
-}
-
-}  // namespace
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_request_handler.cc b/content/browser/service_worker/service_worker_context_request_handler.cc
index 8d51885..847b5c82 100644
--- a/content/browser/service_worker/service_worker_context_request_handler.cc
+++ b/content/browser/service_worker/service_worker_context_request_handler.cc
@@ -90,8 +90,9 @@
 
   int64 response_id = kInvalidServiceWorkerResponseId;
   if (ShouldReadFromScriptCache(request->url(), &response_id)) {
-    return new ServiceWorkerReadFromCacheJob(
-        request, network_delegate, context_, version_, response_id);
+    return new ServiceWorkerReadFromCacheJob(request, network_delegate,
+                                             resource_type_, context_, version_,
+                                             response_id);
   }
 
   // NULL means use the network.
diff --git a/content/browser/service_worker/service_worker_process_manager.cc b/content/browser/service_worker/service_worker_process_manager.cc
index a310bcc1..bc0de358 100644
--- a/content/browser/service_worker/service_worker_process_manager.cc
+++ b/content/browser/service_worker/service_worker_process_manager.cc
@@ -28,6 +28,11 @@
   RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
   if (!rph || rph->FastShutdownStarted())
     return false;
+  // TODO(horo): This is a quick fix for crbug.com/531345. We need to revisit
+  // the behavior of ServiceWorker and the timer suspension of background
+  // processes which was intoruced by crrev.com/1133143003.
+  if (static_cast<RenderProcessHostImpl*>(rph)->backgrounded())
+    return false;
 
   static_cast<RenderProcessHostImpl*>(rph)->IncrementWorkerRefCount();
   return true;
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.cc b/content/browser/service_worker/service_worker_read_from_cache_job.cc
index f6809dd..aecf390 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -25,16 +25,17 @@
 ServiceWorkerReadFromCacheJob::ServiceWorkerReadFromCacheJob(
     net::URLRequest* request,
     net::NetworkDelegate* network_delegate,
+    ResourceType resource_type,
     base::WeakPtr<ServiceWorkerContextCore> context,
     const scoped_refptr<ServiceWorkerVersion>& version,
     int64 response_id)
     : net::URLRequestJob(request, network_delegate),
+      resource_type_(resource_type),
       context_(context),
       version_(version),
       response_id_(response_id),
       has_been_killed_(false),
-      weak_factory_(this) {
-}
+      weak_factory_(this) {}
 
 ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
 }
@@ -52,6 +53,8 @@
 
   // Create a response reader and start reading the headers,
   // we'll continue when thats done.
+  if (is_main_script())
+    version_->embedded_worker()->OnScriptReadStarted();
   reader_ = context_->storage()->CreateResponseReader(response_id_);
   http_info_io_buffer_ = new HttpResponseInfoIOBuffer;
   reader_->ReadInfo(
@@ -204,6 +207,8 @@
       registration->DeleteVersion(version_);
     }
   }
+  if (is_main_script())
+    version_->embedded_worker()->OnScriptReadFinished();
   NotifyDone(status);
 }
 
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h
index 82d9d5f..9c3fa855 100644
--- a/content/browser/service_worker/service_worker_read_from_cache_job.h
+++ b/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -11,6 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
 #include "net/http/http_byte_range.h"
 #include "net/url_request/url_request_job.h"
 
@@ -29,6 +30,7 @@
   ServiceWorkerReadFromCacheJob(
       net::URLRequest* request,
       net::NetworkDelegate* network_delegate,
+      ResourceType resource_type,
       base::WeakPtr<ServiceWorkerContextCore> context,
       const scoped_refptr<ServiceWorkerVersion>& version,
       int64 response_id);
@@ -36,6 +38,10 @@
  private:
   ~ServiceWorkerReadFromCacheJob() override;
 
+  bool is_main_script() const {
+    return resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
+  }
+
   // net::URLRequestJob overrides
   void Start() override;
   void Kill() override;
@@ -57,6 +63,7 @@
   void SetupRangeResponse(int response_data_size);
   void Done(const net::URLRequestStatus& status);
 
+  ResourceType resource_type_;
   base::WeakPtr<ServiceWorkerContextCore> context_;
   scoped_refptr<ServiceWorkerVersion> version_;
   int64 response_id_;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 8b188a9d..f2b4750 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1215,6 +1215,16 @@
   OnStoppedInternal(old_status);
 }
 
+void ServiceWorkerVersion::OnScriptLoaded() {
+  if (IsInstalled(status()))
+    UMA_HISTOGRAM_BOOLEAN("ServiceWorker.ScriptLoadSuccess", true);
+}
+
+void ServiceWorkerVersion::OnScriptLoadFailed() {
+  if (IsInstalled(status()))
+    UMA_HISTOGRAM_BOOLEAN("ServiceWorker.ScriptLoadSuccess", false);
+}
+
 void ServiceWorkerVersion::OnReportException(
     const base::string16& error_message,
     int line_number,
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 4f83cbf..b29ac6f 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -403,6 +403,8 @@
   void OnStopping() override;
   void OnStopped(EmbeddedWorkerInstance::Status old_status) override;
   void OnDetached(EmbeddedWorkerInstance::Status old_status) override;
+  void OnScriptLoaded() override;
+  void OnScriptLoadFailed() override;
   void OnReportException(const base::string16& error_message,
                          int line_number,
                          int column_number,
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.cc b/content/browser/service_worker/service_worker_write_to_cache_job.cc
index ca801ca..781a6525 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -4,11 +4,10 @@
 
 #include "content/browser/service_worker/service_worker_write_to_cache_job.h"
 
-#include "base/bind.h"
-#include "base/callback.h"
+#include <algorithm>
+
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
-#include "content/browser/service_worker/service_worker_cache_writer.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
@@ -19,6 +18,7 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
@@ -40,8 +40,260 @@
     "The script resource is behind a redirect, which is disallowed.";
 const char kServiceWorkerAllowed[] = "Service-Worker-Allowed";
 
+const int kBufferSize = 16 * 1024;
+
 }  // namespace
 
+// Reads an existing resource and copies it via
+// ServiceWorkerWriteToCacheJob::WriteData.
+class ServiceWorkerWriteToCacheJob::Copier : public base::RefCounted<Copier> {
+ public:
+  Copier(base::WeakPtr<ServiceWorkerWriteToCacheJob> owner,
+         scoped_ptr<ServiceWorkerResponseReader> reader,
+         int bytes_to_copy,
+         const base::Callback<void(ServiceWorkerStatusCode)>& callback)
+      : owner_(owner),
+        reader_(reader.release()),
+        bytes_to_copy_(bytes_to_copy),
+        callback_(callback) {
+    DCHECK_LT(0, bytes_to_copy_);
+  }
+
+  void Start() {
+    io_buffer_ = new net::IOBuffer(kBufferSize);
+    ReadSomeData();
+  }
+
+ private:
+  friend class base::RefCounted<Copier>;
+  ~Copier() {}
+
+  void ReadSomeData() {
+    reader_->ReadData(io_buffer_.get(), kBufferSize,
+                      base::Bind(&Copier::OnReadDataComplete, this));
+  }
+
+  void OnReadDataComplete(int result) {
+    if (!owner_)
+      return;
+    if (result <= 0) {
+      // We hit EOF or error but weren't done copying.
+      Complete(SERVICE_WORKER_ERROR_FAILED);
+      return;
+    }
+
+    int bytes_to_write = std::min(bytes_to_copy_, result);
+    owner_->WriteData(io_buffer_.get(), bytes_to_write,
+                      base::Bind(&Copier::OnWriteDataComplete, this));
+  }
+
+  void OnWriteDataComplete(int result) {
+    if (result < 0) {
+      Complete(SERVICE_WORKER_ERROR_FAILED);
+      return;
+    }
+
+    DCHECK_LE(result, bytes_to_copy_);
+    bytes_to_copy_ -= result;
+    if (bytes_to_copy_ == 0) {
+      Complete(SERVICE_WORKER_OK);
+      return;
+    }
+
+    ReadSomeData();
+  }
+
+  void Complete(ServiceWorkerStatusCode status) {
+    if (!owner_)
+      return;
+    callback_.Run(status);
+  }
+
+  base::WeakPtr<ServiceWorkerWriteToCacheJob> owner_;
+  scoped_ptr<ServiceWorkerResponseReader> reader_;
+  int bytes_to_copy_ = 0;
+  base::Callback<void(ServiceWorkerStatusCode)> callback_;
+  scoped_refptr<net::IOBuffer> io_buffer_;
+};
+
+// Abstract consumer for ServiceWorkerWriteToCacheJob that processes data from
+// the network.
+class ServiceWorkerWriteToCacheJob::NetDataConsumer {
+ public:
+  virtual ~NetDataConsumer() {}
+
+  // Called by |owner_|'s OnResponseStarted.
+  virtual void OnResponseStarted() = 0;
+
+  // HandleData should call |owner_|->NotifyReadComplete() when done.
+  virtual void HandleData(net::IOBuffer* buf, int size) = 0;
+};
+
+// Dumb consumer that just writes everything it sees to disk.
+class ServiceWorkerWriteToCacheJob::PassThroughConsumer
+    : public ServiceWorkerWriteToCacheJob::NetDataConsumer {
+ public:
+  explicit PassThroughConsumer(ServiceWorkerWriteToCacheJob* owner)
+      : owner_(owner), weak_factory_(this) {}
+  ~PassThroughConsumer() override {}
+
+  void OnResponseStarted() override {
+    owner_->WriteHeaders(
+        base::Bind(&PassThroughConsumer::OnWriteHeadersComplete,
+                   weak_factory_.GetWeakPtr()));
+    owner_->SetPendingIO();
+  }
+
+  void HandleData(net::IOBuffer* buf, int size) override {
+    if (size == 0) {
+      owner_->OnPassThroughComplete();
+      return;
+    }
+
+    owner_->WriteData(buf, size,
+                      base::Bind(&PassThroughConsumer::OnWriteDataComplete,
+                                 weak_factory_.GetWeakPtr()));
+    owner_->SetPendingIO();
+  }
+
+ private:
+  void OnWriteHeadersComplete() {
+    owner_->ClearPendingIO();
+    owner_->CommitHeadersAndNotifyHeadersComplete();
+  }
+
+  void OnWriteDataComplete(int result) {
+    owner_->ClearPendingIO();
+    owner_->NotifyReadComplete(result);
+  }
+
+  ServiceWorkerWriteToCacheJob* owner_;
+  base::WeakPtrFactory<PassThroughConsumer> weak_factory_;
+};
+
+// Compares an existing resource with data progressively fed to it.
+// Calls back to |owner|->OnCompareComplete once done.
+class ServiceWorkerWriteToCacheJob::Comparer
+    : public ServiceWorkerWriteToCacheJob::NetDataConsumer {
+ public:
+  Comparer(ServiceWorkerWriteToCacheJob* owner,
+           scoped_ptr<ServiceWorkerResponseReader> reader)
+      : owner_(owner), reader_(reader.release()), weak_factory_(this) {}
+  ~Comparer() override {}
+
+  void OnResponseStarted() override {
+    owner_->CommitHeadersAndNotifyHeadersComplete();
+  }
+
+  void HandleData(net::IOBuffer* buf, int size) override {
+    net_data_ = buf;
+    net_data_offset_ = 0;
+    net_data_size_ = size;
+
+    if (size == 0 && info_) {
+      Complete(bytes_matched_ == info_->response_data_size);
+      return;
+    }
+
+    if (!info_) {
+      read_buffer_ = new net::IOBuffer(kBufferSize);
+      info_ = new HttpResponseInfoIOBuffer;
+      reader_->ReadInfo(info_.get(), base::Bind(&Comparer::OnReadInfoComplete,
+                                                weak_factory_.GetWeakPtr()));
+      owner_->SetPendingIO();
+      return;
+    }
+
+    ReadSomeData();
+    owner_->SetPendingIO();
+  }
+
+ private:
+  int bytes_remaining() {
+    DCHECK(net_data_);
+    DCHECK_LE(0, net_data_offset_);
+    DCHECK_LE(net_data_offset_, net_data_size_);
+    return net_data_size_ - net_data_offset_;
+  }
+
+  void OnReadInfoComplete(int result) {
+    if (result < 0) {
+      Complete(false);
+      return;
+    }
+
+    if (bytes_remaining() == 0) {
+      Complete(bytes_matched_ == info_->response_data_size);
+      return;
+    }
+
+    ReadSomeData();
+  }
+
+  void ReadSomeData() {
+    DCHECK_LT(0, bytes_remaining());
+    int bytes_to_read = std::min(bytes_remaining(), kBufferSize);
+    reader_->ReadData(
+        read_buffer_.get(), bytes_to_read,
+        base::Bind(&Comparer::OnReadDataComplete, weak_factory_.GetWeakPtr()));
+  }
+
+  void OnReadDataComplete(int result) {
+    if (result <= 0) {
+      // We hit error or EOF but had more to compare.
+      Complete(false);
+      return;
+    }
+
+    DCHECK_LE(result, bytes_remaining());
+    if (memcmp(net_data_->data() + net_data_offset_, read_buffer_->data(),
+               result) != 0) {
+      Complete(false);
+      return;
+    }
+
+    net_data_offset_ += result;
+    if (bytes_remaining() == 0) {
+      NotifyReadComplete();
+      return;
+    }
+
+    ReadSomeData();
+  }
+
+  // Completes one HandleData() call.
+  void NotifyReadComplete() {
+    int size = net_data_size_;
+    net_data_ = nullptr;
+    net_data_offset_ = 0;
+    net_data_size_ = 0;
+
+    bytes_matched_ += size;
+    owner_->ClearPendingIO();
+    owner_->NotifyReadComplete(size);
+  }
+
+  // Completes the entire Comparer.
+  void Complete(bool is_equal) {
+    owner_->OnCompareComplete(bytes_matched_, is_equal);
+  }
+
+  ServiceWorkerWriteToCacheJob* owner_;
+  scoped_ptr<ServiceWorkerResponseReader> reader_;
+  scoped_refptr<net::IOBuffer> read_buffer_;
+  scoped_refptr<HttpResponseInfoIOBuffer> info_;
+
+  // Cumulative number of bytes successfully compared.
+  int bytes_matched_ = 0;
+
+  // State used for one HandleData() call.
+  scoped_refptr<net::IOBuffer> net_data_;
+  int net_data_offset_ = 0;
+  int net_data_size_ = 0;
+
+  base::WeakPtrFactory<Comparer> weak_factory_;
+};
+
 ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
     net::URLRequest* request,
     net::NetworkDelegate* network_delegate,
@@ -79,14 +331,14 @@
         net::URLRequestStatus::FAILED, net::ERR_FAILED));
     return;
   }
+  if (incumbent_response_id_ != kInvalidServiceWorkerResourceId) {
+    scoped_ptr<ServiceWorkerResponseReader> incumbent_reader =
+        context_->storage()->CreateResponseReader(incumbent_response_id_);
+    consumer_.reset(new Comparer(this, incumbent_reader.Pass()));
+  } else {
+    consumer_.reset(new PassThroughConsumer(this));
+  }
 
-  // These uses of Unretained are safe because this object is the sole owner of
-  // |cache_writer_|, which in turn is the sole user of these callbacks.
-  cache_writer_.reset(new ServiceWorkerCacheWriter(
-      base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseReader,
-                 base::Unretained(this)),
-      base::Bind(&ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter,
-                 base::Unretained(this))));
   version_->script_cache_map()->NotifyStartedCaching(
       url_, response_id_);
   did_notify_started_ = true;
@@ -99,9 +351,12 @@
   weak_factory_.InvalidateWeakPtrs();
   has_been_killed_ = true;
   net_request_.reset();
-  if (did_notify_started_) {
-    NotifyFinishedCaching(net::URLRequestStatus::FromError(net::ERR_ABORTED),
-                          kKilledError);
+  if (did_notify_started_ && !did_notify_finished_) {
+    version_->script_cache_map()->NotifyFinishedCaching(
+        url_, -1,
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_ABORTED),
+        kKilledError);
+    did_notify_finished_ = true;
   }
   writer_.reset();
   context_.reset();
@@ -157,21 +412,17 @@
     return false;
 
   if (!status.is_success()) {
-    NotifyDoneHelper(status, kFetchScriptError);
+    AsyncNotifyDoneHelper(status, kFetchScriptError);
     return false;
   }
 
-  HandleNetData(*bytes_read);
-
-  if (!status.is_success()) {
-    NotifyDoneHelper(status, "");
+  DCHECK_EQ(0, *bytes_read);
+  consumer_->HandleData(buf, 0);
+  if (did_notify_finished_)
+    return GetStatus().is_success();
+  if (GetStatus().is_io_pending())
     return false;
-  }
-
-  // Since URLRequestStatus::is_success() means "SUCCESS or IO_PENDING", but the
-  // contract of this function is "return true for synchronous successes only",
-  // it is important to test against SUCCESS explicitly here.
-  return GetStatus().status() == net::URLRequestStatus::SUCCESS;
+  return status.is_success();
 }
 
 const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const {
@@ -210,14 +461,104 @@
     int* bytes_read) {
   DCHECK_GT(buf_size, 0);
   DCHECK(bytes_read);
+  *bytes_read = 0;
   io_buffer_ = buf;
   io_buffer_bytes_ = 0;
-  if (!net_request_->Read(buf, buf_size, bytes_read))
-    DCHECK_NE(net::URLRequestStatus::SUCCESS, net_request_->status().status());
+  int net_bytes_read = 0;
+  if (!net_request_->Read(buf, buf_size, &net_bytes_read)) {
+    if (net_request_->status().is_io_pending())
+      return net_request_->status();
+    DCHECK(!net_request_->status().is_success());
+    return net_request_->status();
+  }
 
+  if (net_bytes_read != 0) {
+    HandleNetData(net_bytes_read);
+    DCHECK(GetStatus().is_io_pending());
+    return GetStatus();
+  }
+
+  DCHECK(net_request_->status().is_success());
   return net_request_->status();
 }
 
+void ServiceWorkerWriteToCacheJob::WriteHeaders(const base::Closure& callback) {
+  if (!context_) {
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
+        kFetchScriptError);
+    return;
+  }
+  TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+                               "ServiceWorkerWriteToCacheJob::ExecutingJob",
+                               this, "WriteHeaders");
+  writer_ = context_->storage()->CreateResponseWriter(response_id_);
+  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
+      new HttpResponseInfoIOBuffer(
+          new net::HttpResponseInfo(net_request_->response_info()));
+  writer_->WriteInfo(
+      info_buffer.get(),
+      base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(
+    const base::Closure& callback,
+    int result) {
+  if (result < 0) {
+    ServiceWorkerMetrics::CountWriteResponseResult(
+        ServiceWorkerMetrics::WRITE_HEADERS_ERROR);
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, result),
+        kFetchScriptError);
+    return;
+  }
+  TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+                               "ServiceWorkerWriteToCacheJob::ExecutingJob",
+                               this, "WriteHeadersCompleted");
+  callback.Run();
+}
+
+void ServiceWorkerWriteToCacheJob::WriteData(
+    net::IOBuffer* buf,
+    int bytes_to_write,
+    const base::Callback<void(int result)>& callback) {
+  DCHECK_LT(0, bytes_to_write);
+  TRACE_EVENT_ASYNC_STEP_INTO1(
+      "ServiceWorker", "ServiceWorkerWriteToCacheJob::ExecutingJob", this,
+      "WriteData", "Amount to write", bytes_to_write);
+
+  writer_->WriteData(
+      buf, bytes_to_write,
+      base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
+                 weak_factory_.GetWeakPtr(), callback));
+}
+
+void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(
+    const base::Callback<void(int result)>& callback,
+    int result) {
+  DCHECK_NE(0, result);
+  if (!context_) {
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
+        kFetchScriptError);
+    return;
+  }
+  if (result < 0) {
+    ServiceWorkerMetrics::CountWriteResponseResult(
+        ServiceWorkerMetrics::WRITE_DATA_ERROR);
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, result),
+        kFetchScriptError);
+    return;
+  }
+  ServiceWorkerMetrics::CountWriteResponseResult(
+      ServiceWorkerMetrics::WRITE_OK);
+  callback.Run(result);
+  TRACE_EVENT_ASYNC_END0("ServiceWorker",
+                         "ServiceWorkerWriteToCacheJob::ExecutingJob", this);
+}
+
 void ServiceWorkerWriteToCacheJob::OnReceivedRedirect(
     net::URLRequest* request,
     const net::RedirectInfo& redirect_info,
@@ -226,9 +567,9 @@
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerWriteToCacheJob::OnReceivedRedirect");
   // Script resources can't redirect.
-  NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                         net::ERR_UNSAFE_REDIRECT),
-                   kRedirectError);
+  AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                              net::ERR_UNSAFE_REDIRECT),
+                        kRedirectError);
 }
 
 void ServiceWorkerWriteToCacheJob::OnAuthRequired(
@@ -238,7 +579,7 @@
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerWriteToCacheJob::OnAuthRequired");
   // TODO(michaeln): Pass this thru to our jobs client.
-  NotifyDoneHelper(
+  AsyncNotifyDoneHelper(
       net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
       kClientAuthenticationError);
 }
@@ -251,7 +592,7 @@
                "ServiceWorkerWriteToCacheJob::OnCertificateRequested");
   // TODO(michaeln): Pass this thru to our jobs client.
   // see NotifyCertificateRequested.
-  NotifyDoneHelper(
+  AsyncNotifyDoneHelper(
       net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
       kClientAuthenticationError);
 }
@@ -265,9 +606,9 @@
                "ServiceWorkerWriteToCacheJob::OnSSLCertificateError");
   // TODO(michaeln): Pass this thru to our jobs client,
   // see NotifySSLCertificateError.
-  NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                         net::ERR_INSECURE_RESPONSE),
-                   kSSLError);
+  AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                              net::ERR_INSECURE_RESPONSE),
+                        kSSLError);
 }
 
 void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart(
@@ -283,15 +624,15 @@
     net::URLRequest* request) {
   DCHECK_EQ(net_request_, request);
   if (!request->status().is_success()) {
-    NotifyDoneHelper(request->status(), kFetchScriptError);
+    AsyncNotifyDoneHelper(request->status(), kFetchScriptError);
     return;
   }
   if (request->GetResponseCode() / 100 != 2) {
     std::string error_message =
         base::StringPrintf(kBadHTTPResponseError, request->GetResponseCode());
-    NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                           net::ERR_INVALID_RESPONSE),
-                     error_message);
+    AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                                net::ERR_INVALID_RESPONSE),
+                          error_message);
     // TODO(michaeln): Instead of error'ing immediately, send the net
     // response to our consumer, just don't cache it?
     return;
@@ -302,9 +643,9 @@
     const net::HttpNetworkSession::Params* session_params =
         request->context()->GetNetworkSessionParams();
     if (!session_params || !session_params->ignore_certificate_errors) {
-      NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                             net::ERR_INSECURE_RESPONSE),
-                       kSSLError);
+      AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                                  net::ERR_INSECURE_RESPONSE),
+                            kSSLError);
       return;
     }
   }
@@ -319,9 +660,9 @@
           mime_type.empty()
               ? kNoMIMEError
               : base::StringPrintf(kBadMIMEError, mime_type.c_str());
-      NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                             net::ERR_INSECURE_RESPONSE),
-                       error_message);
+      AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                                  net::ERR_INSECURE_RESPONSE),
+                            error_message);
       return;
     }
 
@@ -334,46 +675,17 @@
   if (net_request_->response_info().network_accessed)
     version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
 
-  http_info_.reset(new net::HttpResponseInfo(net_request_->response_info()));
-  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
-      new HttpResponseInfoIOBuffer(
-          new net::HttpResponseInfo(net_request_->response_info()));
-  net::Error error = cache_writer_->MaybeWriteHeaders(
-      info_buffer.get(),
-      base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete,
-                 weak_factory_.GetWeakPtr()));
-  SetStatus(net::URLRequestStatus::FromError(error));
-  if (error != net::ERR_IO_PENDING)
-    NotifyHeadersComplete();
+  consumer_->OnResponseStarted();
 }
 
-void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) {
-  SetStatus(net::URLRequestStatus::FromError(error));
+void ServiceWorkerWriteToCacheJob::CommitHeadersAndNotifyHeadersComplete() {
+  http_info_.reset(new net::HttpResponseInfo(net_request_->response_info()));
   NotifyHeadersComplete();
 }
 
 void ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) {
   io_buffer_bytes_ = bytes_read;
-  net::Error error = cache_writer_->MaybeWriteData(
-      io_buffer_.get(), bytes_read,
-      base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
-                 weak_factory_.GetWeakPtr()));
-  SetStatus(net::URLRequestStatus::FromError(error));
-
-  // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete.
-  if (error != net::ERR_IO_PENDING && bytes_read == 0) {
-    NotifyFinishedCaching(net::URLRequestStatus::FromError(error),
-                          std::string());
-  }
-}
-
-void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) {
-  SetStatus(net::URLRequestStatus::FromError(error));
-  DCHECK_NE(net::ERR_IO_PENDING, error);
-  if (io_buffer_bytes_ == 0) {
-    NotifyDoneHelper(net::URLRequestStatus::FromError(error), std::string());
-  }
-  NotifyReadComplete(error == net::OK ? io_buffer_bytes_ : error);
+  consumer_->HandleData(io_buffer_.get(), bytes_read);
 }
 
 void ServiceWorkerWriteToCacheJob::OnReadCompleted(
@@ -382,23 +694,18 @@
   DCHECK_EQ(net_request_, request);
   if (bytes_read < 0) {
     DCHECK(!request->status().is_success());
-    NotifyDoneHelper(request->status(), kFetchScriptError);
+    AsyncNotifyDoneHelper(request->status(), kFetchScriptError);
     return;
   }
-  HandleNetData(bytes_read);
-  // HandleNetData can cause status of this job to change. If the status changes
-  // to IO_PENDING, that means HandleNetData has pending IO, and
-  // NotifyReadComplete will be called later by the appropriate callback.
-  if (!GetStatus().is_io_pending()) {
-    int result = GetStatus().status() == net::URLRequestStatus::SUCCESS
-                     ? bytes_read
-                     : GetStatus().error();
-    // If bytes_read is 0, HandleNetData synchronously completed and this job is
-    // at EOF.
-    if (bytes_read == 0)
-      NotifyDoneHelper(GetStatus(), std::string());
-    NotifyReadComplete(result);
+  if (bytes_read > 0) {
+    HandleNetData(bytes_read);
+    DCHECK(GetStatus().is_io_pending());
+    return;
   }
+
+  // No more data to process, the job is complete.
+  DCHECK(request->status().is_success());
+  HandleNetData(0);
 }
 
 bool ServiceWorkerWriteToCacheJob::CheckPathRestriction(
@@ -412,15 +719,89 @@
   if (!ServiceWorkerUtils::IsPathRestrictionSatisfied(
           version_->scope(), url_,
           has_header ? &service_worker_allowed : nullptr, &error_message)) {
-    NotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                           net::ERR_INSECURE_RESPONSE),
-                     error_message);
+    AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+                                                net::ERR_INSECURE_RESPONSE),
+                          error_message);
     return false;
   }
   return true;
 }
 
-void ServiceWorkerWriteToCacheJob::NotifyDoneHelper(
+void ServiceWorkerWriteToCacheJob::SetPendingIO() {
+  SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+}
+
+void ServiceWorkerWriteToCacheJob::ClearPendingIO() {
+  SetStatus(net::URLRequestStatus());
+}
+
+void ServiceWorkerWriteToCacheJob::OnPassThroughComplete() {
+  NotifyFinishedCaching(net::URLRequestStatus(), std::string());
+  if (GetStatus().is_io_pending()) {
+    ClearPendingIO();
+    NotifyReadComplete(0);
+  }
+}
+
+void ServiceWorkerWriteToCacheJob::OnCompareComplete(int bytes_matched,
+                                                     bool is_equal) {
+  if (is_equal) {
+    // This version is identical to the incumbent, so discard it and fail this
+    // job.
+    version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
+        kFetchScriptError);
+    return;
+  }
+
+  // We must switch to the pass through consumer. Write what is known
+  // (headers + bytes matched) to disk.
+  WriteHeaders(base::Bind(&ServiceWorkerWriteToCacheJob::CopyIncumbent,
+                          weak_factory_.GetWeakPtr(), bytes_matched));
+  SetPendingIO();
+}
+
+void ServiceWorkerWriteToCacheJob::CopyIncumbent(int bytes_to_copy) {
+  if (bytes_to_copy == 0) {
+    OnCopyComplete(SERVICE_WORKER_OK);
+    return;
+  }
+  scoped_ptr<ServiceWorkerResponseReader> incumbent_reader =
+      context_->storage()->CreateResponseReader(incumbent_response_id_);
+  scoped_refptr<Copier> copier = new Copier(
+      weak_factory_.GetWeakPtr(), incumbent_reader.Pass(), bytes_to_copy,
+      base::Bind(&ServiceWorkerWriteToCacheJob::OnCopyComplete,
+                 weak_factory_.GetWeakPtr()));
+  copier->Start();  // It deletes itself when done.
+  DCHECK(GetStatus().is_io_pending());
+}
+
+void ServiceWorkerWriteToCacheJob::OnCopyComplete(
+    ServiceWorkerStatusCode status) {
+  if (status != SERVICE_WORKER_OK) {
+    AsyncNotifyDoneHelper(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED),
+        kFetchScriptError);
+    return;
+  }
+
+  // Continue processing the net data that triggered the comparison fail and
+  // copy.
+  if (io_buffer_bytes_ > 0) {
+    consumer_.reset(new PassThroughConsumer(this));
+    consumer_->HandleData(io_buffer_.get(), io_buffer_bytes_);
+    return;
+  }
+
+  // The copy was triggered by EOF from the network, which
+  // means the job is now done.
+  NotifyFinishedCaching(net::URLRequestStatus(), std::string());
+  ClearPendingIO();
+  NotifyReadComplete(0);
+}
+
+void ServiceWorkerWriteToCacheJob::AsyncNotifyDoneHelper(
     const net::URLRequestStatus& status,
     const std::string& status_message) {
   DCHECK(!status.is_io_pending());
@@ -432,39 +813,13 @@
 void ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
     net::URLRequestStatus status,
     const std::string& status_message) {
-  if (did_notify_finished_)
-    return;
-
-  // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the
-  // incumbent entry wasn't actually replaced because the new entry was
-  // equivalent, the new version didn't actually install because it already
-  // exists.
-  if (status.status() == net::URLRequestStatus::SUCCESS &&
-      !cache_writer_->did_replace()) {
-    status =
-        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED);
-    version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
-  }
-
+  DCHECK(!did_notify_finished_);
   int size = -1;
   if (status.is_success())
-    size = cache_writer_->bytes_written();
-
+    size = writer_ ? writer_->amount_written() : 0;
   version_->script_cache_map()->NotifyFinishedCaching(url_, size, status,
                                                       status_message);
   did_notify_finished_ = true;
 }
 
-scoped_ptr<ServiceWorkerResponseReader>
-ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() {
-  if (incumbent_response_id_ != kInvalidServiceWorkerResponseId)
-    return context_->storage()->CreateResponseReader(incumbent_response_id_);
-  return nullptr;
-}
-
-scoped_ptr<ServiceWorkerResponseWriter>
-ServiceWorkerWriteToCacheJob::CreateCacheResponseWriter() {
-  return context_->storage()->CreateResponseWriter(response_id_);
-}
-
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job.h b/content/browser/service_worker/service_worker_write_to_cache_job.h
index deee1070..9fcd4b86 100644
--- a/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -15,14 +15,13 @@
 #include "content/common/service_worker/service_worker_status_code.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/resource_type.h"
-#include "net/base/net_errors.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_job.h"
 
 namespace content {
 
-class ServiceWorkerCacheWriter;
 class ServiceWorkerContextCore;
+class ServiceWorkerResponseWriter;
 class ServiceWorkerVersions;
 
 // A URLRequestJob derivative used to cache the main script
@@ -59,6 +58,10 @@
                            UpdateAfter24Hours);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
                            UpdateForceBypassCache);
+  class NetDataConsumer;
+  class PassThroughConsumer;
+  class Comparer;
+  class Copier;
 
   ~ServiceWorkerWriteToCacheJob() override;
 
@@ -83,12 +86,14 @@
                                     int buf_size,
                                     int* bytes_read);
 
-  // Callbacks for writing headers and data via |cache_writer_|. Note that since
-  // the MaybeWriteHeaders and MaybeWriteData methods on |cache_writer_| are
-  // guaranteed not to do short writes, these functions only receive a
-  // net::Error indicating success or failure, not a count of bytes written.
-  void OnWriteHeadersComplete(net::Error error);
-  void OnWriteDataComplete(net::Error error);
+  void CommitHeadersAndNotifyHeadersComplete();
+  void WriteHeaders(const base::Closure& callback);
+  void OnWriteHeadersComplete(const base::Closure& callback, int result);
+  void WriteData(net::IOBuffer* buf,
+                 int amount_to_write,
+                 const base::Callback<void(int result)>& callback);
+  void OnWriteDataComplete(const base::Callback<void(int result)>& callback,
+                           int result);
 
   // net::URLRequest::Delegate overrides that observe the net request.
   void OnReceivedRedirect(net::URLRequest* request,
@@ -108,23 +113,20 @@
 
   bool CheckPathRestriction(net::URLRequest* request);
 
-  // Writes network data back to the script cache if needed, and notifies the
-  // script cache of fetch completion at EOF. This function might need to do
-  // asynchronous IO; if so, it signals this through setting the URLRequestJob's
-  // status to IO_PENDING. After this function returns, if the URLRequestJob
-  // isn't IO_PENDING, all of the data in |io_buffer_| has been written back to
-  // the script cache if necessary.
+  void SetPendingIO();
+  void ClearPendingIO();
+  void OnPassThroughComplete();
+  void OnCompareComplete(int bytes_matched, bool is_equal);
+  void CopyIncumbent(int bytes_to_copy);
+  void OnCopyComplete(ServiceWorkerStatusCode status);
   void HandleNetData(int bytes_read);
 
-  void NotifyDoneHelper(const net::URLRequestStatus& status,
-                        const std::string& status_message);
+  void AsyncNotifyDoneHelper(const net::URLRequestStatus& status,
+                             const std::string& status_message);
 
   void NotifyFinishedCaching(net::URLRequestStatus status,
                              const std::string& status_message);
 
-  scoped_ptr<ServiceWorkerResponseReader> CreateCacheResponseReader();
-  scoped_ptr<ServiceWorkerResponseWriter> CreateCacheResponseWriter();
-
   ResourceType resource_type_;  // Differentiate main script and imports
   scoped_refptr<net::IOBuffer> io_buffer_;
   int io_buffer_bytes_;
@@ -136,7 +138,7 @@
   scoped_ptr<net::HttpResponseInfo> http_info_;
   scoped_ptr<ServiceWorkerResponseWriter> writer_;
   scoped_refptr<ServiceWorkerVersion> version_;
-  scoped_ptr<ServiceWorkerCacheWriter> cache_writer_;
+  scoped_ptr<NetDataConsumer> consumer_;
   bool has_been_killed_;
   bool did_notify_started_;
   bool did_notify_finished_;
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 3bbaf33..8c4b8ed 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -70,9 +70,9 @@
   void DecrementRelatedActiveContentsCount();
 
   // Sets the global factory used to create new RenderProcessHosts.  It may be
-  // NULL, in which case the default BrowserRenderProcessHost will be created
-  // (this is the behavior if you don't call this function).  The factory must
-  // be set back to NULL before it's destroyed; ownership is not transferred.
+  // NULL, in which case the default RenderProcessHost will be created (this is
+  // the behavior if you don't call this function).  The factory must be set
+  // back to NULL before it's destroyed; ownership is not transferred.
   static void set_render_process_host_factory(
       const RenderProcessHostFactory* rph_factory);
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 1f5d733..81b2103 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -3003,17 +3003,8 @@
 
 // Verify that named frames are discoverable from their opener's ancestors.
 // See https://crbug.com/511474.
-// Disable this flaky test on the official cros-trunk for now.
-// See crbug.com/515302.
-#if defined(OFFICIAL_BUILD)
-#define MAYBE_DiscoverNamedFrameFromAncestorOfOpener \
-    DISABLED_DiscoverNamedFrameFromAncestorOfOpener
-#else
-#define MAYBE_DiscoverNamedFrameFromAncestorOfOpener \
-    DiscoverNamedFrameFromAncestorOfOpener
-#endif  // defined(OFFICIAL_BUILD)
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_DiscoverNamedFrameFromAncestorOfOpener) {
+                       DiscoverNamedFrameFromAncestorOfOpener) {
   GURL main_url(
       embedded_test_server()->GetURL("a.com", "/site_per_process_main.html"));
   NavigateToURL(shell(), main_url);
diff --git a/content/browser/system_message_window_win.h b/content/browser/system_message_window_win.h
index 43527da7..b29bad57c 100644
--- a/content/browser/system_message_window_win.h
+++ b/content/browser/system_message_window_win.h
@@ -9,7 +9,6 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/profiler/scoped_tracker.h"
 #include "content/common/content_export.h"
 
 namespace content {
diff --git a/content/browser/theme_helper_mac.h b/content/browser/theme_helper_mac.h
index 9ba2bd7..265d0d6 100644
--- a/content/browser/theme_helper_mac.h
+++ b/content/browser/theme_helper_mac.h
@@ -22,15 +22,6 @@
   // as the blink enum value.
   static blink::ScrollerStyle GetPreferredScrollerStyle();
 
-  static void SendThemeChangeToAllRenderers(
-      float initial_button_delay,
-      float autoscroll_button_delay,
-      bool jump_on_track_click,
-      blink::ScrollerStyle preferred_scroller_style,
-      bool redraw,
-      bool scroll_animation_enabled,
-      blink::ScrollbarButtonsPlacement button_placement);
-
  private:
   friend struct base::DefaultSingletonTraits<ThemeHelperMac>;
 
diff --git a/content/browser/theme_helper_mac.mm b/content/browser/theme_helper_mac.mm
index 44b49b9..9b2656b7 100644
--- a/content/browser/theme_helper_mac.mm
+++ b/content/browser/theme_helper_mac.mm
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/sdk_forward_declarations.h"
+#include "base/strings/sys_string_conversions.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
@@ -16,7 +17,11 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_switches.h"
 
+using content::RenderProcessHost;
+using content::ThemeHelperMac;
+
 namespace {
+
 bool GetScrollAnimationEnabled() {
   bool enabled = false;
   id value = nil;
@@ -44,6 +49,39 @@
   else
     return blink::ScrollbarButtonsPlacementDoubleEnd;
 }
+
+void FillScrollbarThemeParams(ViewMsg_UpdateScrollbarTheme_Params* params) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+  [defaults synchronize];
+
+  params->initial_button_delay =
+      [defaults floatForKey:@"NSScrollerButtonDelay"];
+  params->autoscroll_button_delay =
+      [defaults floatForKey:@"NSScrollerButtonPeriod"];
+  params->jump_on_track_click =
+      [defaults boolForKey:@"AppleScrollerPagingBehavior"];
+  params->preferred_scroller_style =
+      ThemeHelperMac::GetPreferredScrollerStyle();
+  params->scroll_animation_enabled = GetScrollAnimationEnabled();
+  params->button_placement = GetButtonPlacement();
+}
+
+ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+  [defaults synchronize];
+
+  return new ViewMsg_SystemColorsChanged(
+      [[defaults stringForKey:@"AppleAquaColorVariant"] intValue],
+      base::SysNSStringToUTF8(
+          [defaults stringForKey:@"AppleHighlightedTextColor"]),
+      base::SysNSStringToUTF8(
+          [defaults stringForKey:@"AppleHighlightColor"]));
+}
+
 } // namespace
 
 @interface ScrollbarPrefsObserver : NSObject
@@ -58,54 +96,60 @@
 @implementation ScrollbarPrefsObserver
 
 + (void)registerAsObserver {
-  [[NSDistributedNotificationCenter defaultCenter]
-      addObserver:self
-         selector:@selector(appearancePrefsChanged:)
-             name:@"AppleAquaScrollBarVariantChanged"
-           object:nil
-suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+  NSDistributedNotificationCenter* distributedCenter =
+      [NSDistributedNotificationCenter defaultCenter];
+  [distributedCenter addObserver:self
+                        selector:@selector(appearancePrefsChanged:)
+                            name:@"AppleAquaScrollBarVariantChanged"
+                          object:nil
+               suspensionBehavior:
+                   NSNotificationSuspensionBehaviorDeliverImmediately];
 
-  [[NSDistributedNotificationCenter defaultCenter]
-      addObserver:self
-         selector:@selector(behaviorPrefsChanged:)
-             name:@"AppleNoRedisplayAppearancePreferenceChanged"
-           object:nil
-suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+  [distributedCenter addObserver:self
+                        selector:@selector(behaviorPrefsChanged:)
+                            name:@"AppleNoRedisplayAppearancePreferenceChanged"
+                          object:nil
+              suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
 
   if (base::mac::IsOSMountainLionOrLater()) {
-    [[NSDistributedNotificationCenter defaultCenter]
-               addObserver:self
-                  selector:@selector(behaviorPrefsChanged:)
-                      name:@"NSScrollAnimationEnabled"
-                    object:nil
-        suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+    [distributedCenter addObserver:self
+                          selector:@selector(behaviorPrefsChanged:)
+                              name:@"NSScrollAnimationEnabled"
+                            object:nil
+                suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
   } else {
     // Register for < 10.8
-    [[NSDistributedNotificationCenter defaultCenter]
-               addObserver:self
-                  selector:@selector(behaviorPrefsChanged:)
-                      name:@"AppleScrollAnimationEnabled"
-                    object:nil
-        suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+    [distributedCenter addObserver:self
+                          selector:@selector(behaviorPrefsChanged:)
+                              name:@"AppleScrollAnimationEnabled"
+                            object:nil
+                suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
   }
 
-  [[NSDistributedNotificationCenter defaultCenter]
-             addObserver:self
-                selector:@selector(appearancePrefsChanged:)
-                    name:@"AppleScrollBarVariant"
-                  object:nil
-      suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
+  [distributedCenter addObserver:self
+                        selector:@selector(appearancePrefsChanged:)
+                            name:@"AppleScrollBarVariant"
+                          object:nil
+              suspensionBehavior:
+                  NSNotificationSuspensionBehaviorDeliverImmediately];
 
   // In single-process mode, renderers will catch these notifications
   // themselves and listening for them here may trigger the DCHECK in Observe().
-  if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] &&
-      !base::CommandLine::ForCurrentProcess()->HasSwitch(
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kSingleProcess)) {
-    [[NSNotificationCenter defaultCenter]
-        addObserver:self
-           selector:@selector(behaviorPrefsChanged:)
-               name:NSPreferredScrollerStyleDidChangeNotification
-             object:nil];
+    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+
+    if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)]) {
+      [center addObserver:self
+                 selector:@selector(behaviorPrefsChanged:)
+                     name:NSPreferredScrollerStyleDidChangeNotification
+                   object:nil];
+    }
+
+    [center addObserver:self
+               selector:@selector(systemColorsChanged:)
+                   name:NSSystemColorsDidChangeNotification
+                 object:nil];
   }
 }
 
@@ -117,17 +161,24 @@
   [self notifyPrefsChangedWithRedraw:NO];
 }
 
-+ (void)notifyPrefsChangedWithRedraw:(BOOL)redraw {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults synchronize];
++ (void)systemColorsChanged:(NSNotification*)notification {
+  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+       !it.IsAtEnd();
+       it.Advance()) {
+    it.GetCurrentValue()->Send(CreateSystemColorsChangedMessage());
+  }
+}
 
-  content::ThemeHelperMac::SendThemeChangeToAllRenderers(
-      [defaults floatForKey:@"NSScrollerButtonDelay"],
-      [defaults floatForKey:@"NSScrollerButtonPeriod"],
-      [defaults boolForKey:@"AppleScrollerPagingBehavior"],
-      content::ThemeHelperMac::GetPreferredScrollerStyle(), redraw,
-      GetScrollAnimationEnabled(), GetButtonPlacement());
++ (void)notifyPrefsChangedWithRedraw:(BOOL)redraw {
+  ViewMsg_UpdateScrollbarTheme_Params params;
+  FillScrollbarThemeParams(&params);
+  params.redraw = redraw;
+
+  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
+       !it.IsAtEnd();
+       it.Advance()) {
+    it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme(params));
+  }
 }
 
 @end
@@ -147,31 +198,6 @@
   return static_cast<blink::ScrollerStyle>([NSScroller preferredScrollerStyle]);
 }
 
-// static
-void ThemeHelperMac::SendThemeChangeToAllRenderers(
-    float initial_button_delay,
-    float autoscroll_button_delay,
-    bool jump_on_track_click,
-    blink::ScrollerStyle preferred_scroller_style,
-    bool redraw,
-    bool scroll_animation_enabled,
-    blink::ScrollbarButtonsPlacement button_placement) {
-  ViewMsg_UpdateScrollbarTheme_Params params;
-  params.initial_button_delay = initial_button_delay;
-  params.autoscroll_button_delay = autoscroll_button_delay;
-  params.jump_on_track_click = jump_on_track_click;
-  params.preferred_scroller_style = preferred_scroller_style;
-  params.redraw = redraw;
-  params.scroll_animation_enabled = scroll_animation_enabled;
-  params.button_placement = button_placement;
-
-  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
-       !it.IsAtEnd();
-       it.Advance()) {
-    it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme(params));
-  }
-}
-
 ThemeHelperMac::ThemeHelperMac() {
   [ScrollbarPrefsObserver registerAsObserver];
   registrar_.Add(this,
@@ -187,24 +213,15 @@
                              const NotificationDetails& details) {
   DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
 
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
-  [defaults synchronize];
+  // When a new RenderProcess is created, send it the initial preference
+  // parameters.
+  ViewMsg_UpdateScrollbarTheme_Params params;
+  FillScrollbarThemeParams(&params);
+  params.redraw = false;
 
   RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
-
-  ViewMsg_UpdateScrollbarTheme_Params params;
-  params.initial_button_delay = [defaults floatForKey:@"NSScrollerButtonDelay"];
-  params.autoscroll_button_delay =
-      [defaults floatForKey:@"NSScrollerButtonPeriod"];
-  params.jump_on_track_click =
-      [defaults boolForKey:@"AppleScrollerPagingBehavior"];
-  params.preferred_scroller_style = GetPreferredScrollerStyle();
-  params.redraw = false;
-  params.scroll_animation_enabled = GetScrollAnimationEnabled();
-  params.button_placement = GetButtonPlacement();
-
   rph->Send(new ViewMsg_UpdateScrollbarTheme(params));
+  rph->Send(CreateSystemColorsChangedMessage());
 }
 
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 31e5696..7c84d90 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -946,21 +946,19 @@
   // title.
   entry = controller_.GetLastCommittedEntry();
 
-  // We make an exception for initial navigations.
-  if (controller_.IsInitialNavigation()) {
-    // We only want to use the title from the visible entry in one of two cases:
-    // 1. There's already a committed entry for an initial navigation, in which
-    //    case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
-    // 2. The pending entry has been explicitly assigned a title to display.
-    //
-    // If there's no last committed entry and no assigned title, we should fall
-    // back to |page_title_when_no_navigation_entry_| rather than showing the
-    // URL.
-    if (entry ||
-        (controller_.GetVisibleEntry() &&
-         !controller_.GetVisibleEntry()->GetTitle().empty())) {
-      entry = controller_.GetVisibleEntry();
-    }
+  // We make an exception for initial navigations. We only want to use the title
+  // from the visible entry if:
+  // 1. The pending entry has been explicitly assigned a title to display.
+  // 2. The user is doing a history navigation in a new tab (e.g., Ctrl+Back),
+  //    which case there is a pending entry index other than -1.
+  //
+  // Otherwise, we want to stick with the last committed entry's title during
+  // new navigations, which have pending entries at index -1 with no title.
+  if (controller_.IsInitialNavigation() &&
+      ((controller_.GetVisibleEntry() &&
+        !controller_.GetVisibleEntry()->GetTitle().empty()) ||
+       controller_.GetPendingEntryIndex() != -1)) {
+    entry = controller_.GetVisibleEntry();
   }
 
   if (entry) {
@@ -3088,7 +3086,6 @@
                      base::CompareCase::INSENSITIVE_ASCII))
     RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
   controller_.ssl_manager()->DidRunInsecureContent(security_origin);
-  displayed_insecure_content_ = true;
   SSLManager::NotifySSLInternalStateChanged(
       GetController().GetBrowserContext());
 }
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 4ead8c1..7dabef2c 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -346,11 +346,25 @@
   EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
 }
 
+TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) {
+  ASSERT_TRUE(controller().IsInitialNavigation());
+  const base::string16 title = base::ASCIIToUTF16("Initial Entry Title");
+  contents()->UpdateTitle(contents()->GetMainFrame(), -1, title,
+                          base::i18n::LEFT_TO_RIGHT);
+  EXPECT_EQ(title, contents()->GetTitle());
+}
+
 TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
   const GURL kGURL("chrome://blah");
   controller().LoadURL(
       kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
   EXPECT_EQ(base::string16(), contents()->GetTitle());
+
+  // Also test setting title while the first navigation is still pending.
+  const base::string16 title = base::ASCIIToUTF16("Initial Entry Title");
+  contents()->UpdateTitle(contents()->GetMainFrame(), -1, title,
+                          base::i18n::LEFT_TO_RIGHT);
+  EXPECT_EQ(title, contents()->GetTitle());
 }
 
 TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
diff --git a/content/child/background_sync/background_sync_provider.cc b/content/child/background_sync/background_sync_provider.cc
index c9f5ab7..57f3d56 100644
--- a/content/child/background_sync/background_sync_provider.cc
+++ b/content/child/background_sync/background_sync_provider.cc
@@ -60,9 +60,7 @@
 }
 
 void BackgroundSyncProvider::unregisterBackgroundSync(
-    blink::WebSyncRegistration::Periodicity periodicity,
     int64_t handle_id,
-    const blink::WebString& tag,
     blink::WebServiceWorkerRegistration* service_worker_registration,
     blink::WebSyncUnregistrationCallbacks* callbacks) {
   DCHECK(service_worker_registration);
@@ -74,8 +72,7 @@
   // base::Unretained is safe here, as the mojo channel will be deleted (and
   // will wipe its callbacks) before 'this' is deleted.
   GetBackgroundSyncServicePtr()->Unregister(
-      mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity), handle_id,
-      service_worker_registration_id,
+      handle_id, service_worker_registration_id,
       base::Bind(&BackgroundSyncProvider::UnregisterCallback,
                  base::Unretained(this), base::Passed(callbacksPtr.Pass())));
 }
@@ -159,7 +156,7 @@
 }
 
 void BackgroundSyncProvider::DuplicateRegistrationHandle(
-    int handle_id,
+    int64_t handle_id,
     const BackgroundSyncService::DuplicateRegistrationHandleCallback&
         callback) {
   GetBackgroundSyncServicePtr()->DuplicateRegistrationHandle(handle_id,
diff --git a/content/child/background_sync/background_sync_provider.h b/content/child/background_sync/background_sync_provider.h
index 0dc6d6c..cb4f6af5 100644
--- a/content/child/background_sync/background_sync_provider.h
+++ b/content/child/background_sync/background_sync_provider.h
@@ -28,18 +28,13 @@
   ~BackgroundSyncProvider() override;
 
   // blink::WebSyncProvider implementation
-  // TODO(jkarlin) convert int64_t handle_id to int handle_id in all
-  // WebSyncProvider functions.
   void registerBackgroundSync(
       const blink::WebSyncRegistration* options,
       blink::WebServiceWorkerRegistration* service_worker_registration,
       bool requested_from_service_worker,
       blink::WebSyncRegistrationCallbacks* callbacks) override;
-  // TODO(jkarlin) remove |tag| parameter.
   void unregisterBackgroundSync(
-      blink::WebSyncRegistration::Periodicity periodicity,
       int64_t handle_id,
-      const blink::WebString& tag,
       blink::WebServiceWorkerRegistration* service_worker_registration,
       blink::WebSyncUnregistrationCallbacks* callbacks) override;
   void getRegistration(
@@ -62,7 +57,7 @@
       blink::WebSyncNotifyWhenDoneCallbacks* callbacks) override;
 
   void DuplicateRegistrationHandle(
-      int handle_id,
+      int64_t handle_id,
       const BackgroundSyncService::DuplicateRegistrationHandleCallback&
           callback);
 
diff --git a/content/child/background_sync/background_sync_provider_thread_proxy.cc b/content/child/background_sync/background_sync_provider_thread_proxy.cc
index ea5f8a41..021df27 100644
--- a/content/child/background_sync/background_sync_provider_thread_proxy.cc
+++ b/content/child/background_sync/background_sync_provider_thread_proxy.cc
@@ -137,9 +137,7 @@
 }
 
 void BackgroundSyncProviderThreadProxy::unregisterBackgroundSync(
-    blink::WebSyncRegistration::Periodicity periodicity,
-    int64_t id,
-    const blink::WebString& tag,
+    int64_t handle_id,
     blink::WebServiceWorkerRegistration* service_worker_registration,
     blink::WebSyncUnregistrationCallbacks* callbacks) {
   DCHECK(service_worker_registration);
@@ -148,10 +146,8 @@
       FROM_HERE,
       base::Bind(
           &BackgroundSyncProvider::unregisterBackgroundSync,
-          base::Unretained(sync_provider_), periodicity, id,
-          // We cast WebString to string16 before crossing threads
-          // for thread-safety.
-          static_cast<base::string16>(tag), service_worker_registration,
+          base::Unretained(sync_provider_), handle_id,
+          service_worker_registration,
           new CallbackThreadAdapter<blink::WebSyncUnregistrationCallbacks>(
               make_scoped_ptr(callbacks), WorkerThread::GetCurrentId())));
 }
@@ -228,7 +224,7 @@
 }
 
 void BackgroundSyncProviderThreadProxy::DuplicateRegistrationHandle(
-    int64 handle_id,
+    int64_t handle_id,
     const DuplicateRegistrationHandleCallback& callback) {
   main_thread_task_runner_->PostTask(
       FROM_HERE,
diff --git a/content/child/background_sync/background_sync_provider_thread_proxy.h b/content/child/background_sync/background_sync_provider_thread_proxy.h
index 482037b..f48a4795 100644
--- a/content/child/background_sync/background_sync_provider_thread_proxy.h
+++ b/content/child/background_sync/background_sync_provider_thread_proxy.h
@@ -43,9 +43,7 @@
       bool requested_from_service_worker,
       blink::WebSyncRegistrationCallbacks* callbacks) override;
   void unregisterBackgroundSync(
-      blink::WebSyncRegistration::Periodicity periodicity,
-      int64_t id,
-      const blink::WebString& tag,
+      int64_t handle_id,
       blink::WebServiceWorkerRegistration* service_worker_registration,
       blink::WebSyncUnregistrationCallbacks* callbacks) override;
   void getRegistration(
@@ -69,7 +67,7 @@
   // Given |handle_id|, ask the provider for a new handle with the same
   // underlying registration.
   void DuplicateRegistrationHandle(
-      int64 handle_id,
+      int64_t handle_id,
       const DuplicateRegistrationHandleCallback& callback);
 
   // WorkerThread::Observer implementation.
diff --git a/content/child/indexed_db/indexed_db_dispatcher_unittest.cc b/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
index e3b409b..1dd58485 100644
--- a/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
+++ b/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "content/child/indexed_db/indexed_db_dispatcher.h"
+#include "content/child/indexed_db/mock_webidbcallbacks.h"
 #include "content/child/indexed_db/webidbcursor_impl.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/common/indexed_db/indexed_db_key.h"
@@ -16,36 +17,21 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebBlobInfo.h"
 #include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
 #include "third_party/WebKit/public/web/WebHeap.h"
 
 using blink::WebBlobInfo;
 using blink::WebData;
-using blink::WebIDBCallbacks;
 using blink::WebIDBCursor;
-using blink::WebIDBDatabase;
-using blink::WebIDBDatabaseError;
 using blink::WebIDBKey;
-using blink::WebIDBValue;
 using blink::WebVector;
+using testing::_;
+using testing::Invoke;
+using testing::StrictMock;
+using testing::WithArgs;
 
 namespace content {
 namespace {
 
-class MockCallbacks : public WebIDBCallbacks {
- public:
-  MockCallbacks() : error_seen_(false) {}
-
-  void onError(const WebIDBDatabaseError&) override { error_seen_ = true; }
-
-  bool error_seen() const { return error_seen_; }
-
- private:
-  bool error_seen_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockCallbacks);
-};
-
 class MockDispatcher : public IndexedDBDispatcher {
  public:
   explicit MockDispatcher(ThreadSafeSender* sender)
@@ -99,7 +85,9 @@
   const int64 transaction_id = 1;
   const int64 object_store_id = 2;
 
-  MockCallbacks callbacks;
+  StrictMock<MockWebIDBCallbacks> callbacks;
+  EXPECT_CALL(callbacks, onError(_)).Times(1);
+
   IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
   dispatcher.max_put_value_size_ = kMaxValueSizeForTesting;
   IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
@@ -113,8 +101,6 @@
                                    &callbacks,
                                    WebVector<long long>(),
                                    WebVector<WebVector<WebIDBKey> >());
-
-  EXPECT_TRUE(callbacks.error_seen());
 }
 
 TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
@@ -133,7 +119,9 @@
   const int64 transaction_id = 1;
   const int64 object_store_id = 2;
 
-  MockCallbacks callbacks;
+  StrictMock<MockWebIDBCallbacks> callbacks;
+  EXPECT_CALL(callbacks, onError(_)).Times(1);
+
   IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
   dispatcher.max_put_value_size_ = kMaxValueSizeForTesting;
   dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
@@ -146,34 +134,8 @@
                                    &callbacks,
                                    WebVector<long long>(),
                                    WebVector<WebVector<WebIDBKey> >());
-
-  EXPECT_TRUE(callbacks.error_seen());
 }
 
-namespace {
-
-class CursorCallbacks : public WebIDBCallbacks {
- public:
-  explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor)
-      : cursor_(cursor) {}
-
-  void onSuccess(const WebIDBValue&) override {}
-  void onSuccess(WebIDBCursor* cursor,
-                 const WebIDBKey& key,
-                 const WebIDBKey& primaryKey,
-                 const WebData& value,
-                 const WebVector<WebBlobInfo>&) override {
-    cursor_->reset(cursor);
-  }
-
- private:
-  scoped_ptr<WebIDBCursor>* cursor_;
-
-  DISALLOW_COPY_AND_ASSIGN(CursorCallbacks);
-};
-
-}  // namespace
-
 TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
   const int32 ipc_database_id = -1;
   const int64 transaction_id = 1234;
@@ -190,16 +152,19 @@
     scoped_ptr<WebIDBCursor> cursor;
     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
 
+    auto callbacks = new StrictMock<MockWebIDBCallbacks>();
+    // Reference first param (cursor) to keep it alive.
+    // TODO(cmumford): Cleanup (and below) once std::addressof() is allowed.
+    ON_CALL(*callbacks, onSuccess(_, _, _, _, _))
+        .WillByDefault(WithArgs<0>(Invoke(&cursor.operator=(nullptr),
+                                          &scoped_ptr<WebIDBCursor>::reset)));
+    EXPECT_CALL(*callbacks, onSuccess(_, _, _, _, _)).Times(1);
+
     // Make a cursor request. This should record the transaction id.
-    dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
-                                            transaction_id,
-                                            object_store_id,
-                                            index_id,
-                                            IndexedDBKeyRange(),
-                                            direction,
-                                            key_only,
-                                            blink::WebIDBTaskTypeNormal,
-                                            new CursorCallbacks(&cursor));
+    dispatcher.RequestIDBDatabaseOpenCursor(
+        ipc_database_id, transaction_id, object_store_id, index_id,
+        IndexedDBKeyRange(), direction, key_only, blink::WebIDBTaskTypeNormal,
+        callbacks);
 
     // Verify that the transaction id was captured.
     EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
@@ -228,23 +193,20 @@
 
   // Second case: null cursor (no data in range)
   {
-    scoped_ptr<WebIDBCursor> cursor;
     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
 
+    auto callbacks = new StrictMock<MockWebIDBCallbacks>();
+    EXPECT_CALL(*callbacks, onSuccess(testing::A<const blink::WebIDBValue&>()))
+        .Times(1);
+
     // Make a cursor request. This should record the transaction id.
-    dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
-                                            transaction_id,
-                                            object_store_id,
-                                            index_id,
-                                            IndexedDBKeyRange(),
-                                            direction,
-                                            key_only,
-                                            blink::WebIDBTaskTypeNormal,
-                                            new CursorCallbacks(&cursor));
+    dispatcher.RequestIDBDatabaseOpenCursor(
+        ipc_database_id, transaction_id, object_store_id, index_id,
+        IndexedDBKeyRange(), direction, key_only, blink::WebIDBTaskTypeNormal,
+        callbacks);
 
     // Verify that the transaction id was captured.
     EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
-    EXPECT_FALSE(cursor.get());
 
     int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
 
@@ -256,7 +218,6 @@
 
     // Ensure the map result was deleted.
     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
-    EXPECT_FALSE(cursor.get());
   }
 }
 
@@ -315,45 +276,33 @@
   EXPECT_EQ(0, cursor2->reset_count());
 
   // Other transaction:
-  dispatcher.RequestIDBDatabaseGet(ipc_database_id,
-                                   other_transaction_id,
-                                   object_store_id,
-                                   index_id,
-                                   IndexedDBKeyRange(),
-                                   key_only,
-                                   new MockCallbacks());
+  dispatcher.RequestIDBDatabaseGet(
+      ipc_database_id, other_transaction_id, object_store_id, index_id,
+      IndexedDBKeyRange(), key_only, new StrictMock<MockWebIDBCallbacks>());
 
   EXPECT_EQ(0, cursor1->reset_count());
   EXPECT_EQ(0, cursor2->reset_count());
 
   // Same transaction:
-  dispatcher.RequestIDBDatabaseGet(ipc_database_id,
-                                   cursor1_transaction_id,
-                                   object_store_id,
-                                   index_id,
-                                   IndexedDBKeyRange(),
-                                   key_only,
-                                   new MockCallbacks());
+  dispatcher.RequestIDBDatabaseGet(
+      ipc_database_id, cursor1_transaction_id, object_store_id, index_id,
+      IndexedDBKeyRange(), key_only, new StrictMock<MockWebIDBCallbacks>());
 
   EXPECT_EQ(1, cursor1->reset_count());
   EXPECT_EQ(0, cursor2->reset_count());
 
   // Same transaction and same cursor:
-  dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
-                                      IndexedDBKey(),
-                                      new MockCallbacks(),
-                                      cursor1_ipc_id,
-                                      cursor1_transaction_id);
+  dispatcher.RequestIDBCursorContinue(IndexedDBKey(), IndexedDBKey(),
+                                      new StrictMock<MockWebIDBCallbacks>(),
+                                      cursor1_ipc_id, cursor1_transaction_id);
 
   EXPECT_EQ(1, cursor1->reset_count());
   EXPECT_EQ(0, cursor2->reset_count());
 
   // Same transaction and different cursor:
-  dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
-                                      IndexedDBKey(),
-                                      new MockCallbacks(),
-                                      other_cursor_ipc_id,
-                                      cursor1_transaction_id);
+  dispatcher.RequestIDBCursorContinue(
+      IndexedDBKey(), IndexedDBKey(), new StrictMock<MockWebIDBCallbacks>(),
+      other_cursor_ipc_id, cursor1_transaction_id);
 
   EXPECT_EQ(2, cursor1->reset_count());
   EXPECT_EQ(0, cursor2->reset_count());
diff --git a/content/child/indexed_db/mock_webidbcallbacks.cc b/content/child/indexed_db/mock_webidbcallbacks.cc
new file mode 100644
index 0000000..faa4113
--- /dev/null
+++ b/content/child/indexed_db/mock_webidbcallbacks.cc
@@ -0,0 +1,13 @@
+// Copyright 2015 The Chromium Authors. 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/indexed_db/mock_webidbcallbacks.h"
+
+namespace content {
+
+MockWebIDBCallbacks::MockWebIDBCallbacks() {}
+
+MockWebIDBCallbacks::~MockWebIDBCallbacks() {}
+
+}  // namespace content
diff --git a/content/child/indexed_db/mock_webidbcallbacks.h b/content/child/indexed_db/mock_webidbcallbacks.h
new file mode 100644
index 0000000..97a5188
--- /dev/null
+++ b/content/child/indexed_db/mock_webidbcallbacks.h
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium Authors. 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_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
+#define CONTENT_CHILD_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/WebKit/public/platform/WebBlobInfo.h"
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseError.h"
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBMetadata.h"
+#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBValue.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
+
+namespace blink {
+class WebData;
+}  // namespace blink
+
+namespace content {
+
+class MockWebIDBCallbacks : public blink::WebIDBCallbacks {
+ public:
+  MockWebIDBCallbacks();
+  ~MockWebIDBCallbacks();
+  MOCK_METHOD1(onError, void(const blink::WebIDBDatabaseError&));
+  MOCK_METHOD4(onSuccess,
+               void(const blink::WebIDBKey& key,
+                    const blink::WebIDBKey& primaryKey,
+                    const blink::WebData& value,
+                    const blink::WebVector<blink::WebBlobInfo>& webBlobInfo));
+  MOCK_METHOD1(onSuccess, void(const blink::WebVector<blink::WebString>&));
+  MOCK_METHOD5(onSuccess,
+               void(blink::WebIDBCursor*,
+                    const blink::WebIDBKey&,
+                    const blink::WebIDBKey& primaryKey,
+                    const blink::WebData&,
+                    const blink::WebVector<blink::WebBlobInfo>&));
+  MOCK_METHOD2(onSuccess,
+               void(blink::WebIDBDatabase*, const blink::WebIDBMetadata&));
+  MOCK_METHOD1(onSuccess, void(const blink::WebIDBKey&));
+  MOCK_METHOD2(onSuccess,
+               void(const blink::WebData&,
+                    const blink::WebVector<blink::WebBlobInfo>&));
+  MOCK_METHOD1(onSuccess, void(const blink::WebIDBValue&));
+  MOCK_METHOD1(onSuccess, void(const blink::WebVector<blink::WebIDBValue>&));
+  MOCK_METHOD4(onSuccess,
+               void(const blink::WebData&,
+                    const blink::WebVector<blink::WebBlobInfo>&,
+                    const blink::WebIDBKey&,
+                    const blink::WebIDBKeyPath&));
+  MOCK_METHOD1(onSuccess, void(long long));
+  MOCK_METHOD0(onSuccess, void());
+  MOCK_METHOD1(onBlocked, void(long long oldVersion));
+  MOCK_METHOD5(onUpgradeNeeded,
+               void(long long oldVersion,
+                    blink::WebIDBDatabase*,
+                    const blink::WebIDBMetadata&,
+                    unsigned short dataLoss,
+                    blink::WebString dataLossMessage));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockWebIDBCallbacks);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_CHILD_INDEXED_DB_MOCK_WEBIDBCALLBACKS_H_
diff --git a/content/child/indexed_db/webidbcursor_impl_unittest.cc b/content/child/indexed_db/webidbcursor_impl_unittest.cc
index 69fa803..2048285 100644
--- a/content/child/indexed_db/webidbcursor_impl_unittest.cc
+++ b/content/child/indexed_db/webidbcursor_impl_unittest.cc
@@ -7,21 +7,21 @@
 #include "base/values.h"
 #include "content/child/indexed_db/indexed_db_dispatcher.h"
 #include "content/child/indexed_db/indexed_db_key_builders.h"
+#include "content/child/indexed_db/mock_webidbcallbacks.h"
 #include "content/child/indexed_db/webidbcursor_impl.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/common/indexed_db/indexed_db_key.h"
 #include "ipc/ipc_sync_message_filter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
 
 using blink::WebBlobInfo;
 using blink::WebData;
 using blink::WebIDBCallbacks;
-using blink::WebIDBDatabase;
 using blink::WebIDBKey;
 using blink::WebIDBKeyTypeNumber;
 using blink::WebVector;
+using testing::StrictMock;
 
 namespace content {
 
@@ -94,7 +94,7 @@
   scoped_ptr<WebIDBCallbacks> callbacks_;
 };
 
-class MockContinueCallbacks : public WebIDBCallbacks {
+class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> {
  public:
   MockContinueCallbacks(IndexedDBKey* key = 0,
                         WebVector<WebBlobInfo>* webBlobInfo = 0)
@@ -326,8 +326,8 @@
   EXPECT_EQ(0, dispatcher_->reset_calls());
 
   // The real dispatcher would call cursor->CachedContinue(), so do that:
-  scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
-  cursor.CachedContinue(callbacks.get());
+  MockContinueCallbacks callbacks;
+  cursor.CachedContinue(&callbacks);
 
   // Now the cursor should have reset the rest of the cache.
   EXPECT_EQ(1, dispatcher_->reset_calls());
diff --git a/content/child/memory/child_memory_message_filter.cc b/content/child/memory/child_memory_message_filter.cc
index 1f35159..9306e7c 100644
--- a/content/child/memory/child_memory_message_filter.cc
+++ b/content/child/memory/child_memory_message_filter.cc
@@ -4,7 +4,6 @@
 
 #include "content/child/memory/child_memory_message_filter.h"
 
-#include "base/memory/memory_pressure_listener.h"
 #include "content/common/memory_messages.h"
 
 namespace content {
@@ -18,6 +17,8 @@
   IPC_BEGIN_MESSAGE_MAP(ChildMemoryMessageFilter, message)
     IPC_MESSAGE_HANDLER(MemoryMsg_SetPressureNotificationsSuppressed,
                         OnSetPressureNotificationsSuppressed)
+    IPC_MESSAGE_HANDLER(MemoryMsg_SimulatePressureNotification,
+                        OnSimulatePressureNotification)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -29,4 +30,9 @@
   base::MemoryPressureListener::SetNotificationsSuppressed(suppressed);
 }
 
+void ChildMemoryMessageFilter::OnSimulatePressureNotification(
+    base::MemoryPressureListener::MemoryPressureLevel level) {
+  base::MemoryPressureListener::SimulatePressureNotification(level);
+}
+
 }  // namespace content
diff --git a/content/child/memory/child_memory_message_filter.h b/content/child/memory/child_memory_message_filter.h
index 32e2a2a1..bc1e665 100644
--- a/content/child/memory/child_memory_message_filter.h
+++ b/content/child/memory/child_memory_message_filter.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_CHILD_MEMORY_CHILD_MEMORY_MESSAGE_FILTER_H_
 #define CONTENT_CHILD_MEMORY_CHILD_MEMORY_MESSAGE_FILTER_H_
 
+#include "base/memory/memory_pressure_listener.h"
 #include "ipc/message_filter.h"
 
 namespace content {
@@ -23,6 +24,8 @@
 
  private:
   void OnSetPressureNotificationsSuppressed(bool suppressed);
+  void OnSimulatePressureNotification(
+      base::MemoryPressureListener::MemoryPressureLevel level);
 
   DISALLOW_COPY_AND_ASSIGN(ChildMemoryMessageFilter);
 };
diff --git a/content/child/push_messaging/push_provider.cc b/content/child/push_messaging/push_provider.cc
index ba82b0f9..ab33df4 100644
--- a/content/child/push_messaging/push_provider.cc
+++ b/content/child/push_messaging/push_provider.cc
@@ -148,14 +148,14 @@
 void PushProvider::OnSubscribeFromWorkerSuccess(
     int request_id,
     const GURL& endpoint,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   blink::WebPushSubscriptionCallbacks* callbacks =
       subscription_callbacks_.Lookup(request_id);
   if (!callbacks)
     return;
 
   callbacks->onSuccess(blink::adoptWebPtr(
-      new blink::WebPushSubscription(endpoint, curve25519dh)));
+      new blink::WebPushSubscription(endpoint, p256dh)));
 
   subscription_callbacks_.Remove(request_id);
 }
@@ -208,14 +208,14 @@
 void PushProvider::OnGetRegistrationSuccess(
     int request_id,
     const GURL& endpoint,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   blink::WebPushSubscriptionCallbacks* callbacks =
       subscription_callbacks_.Lookup(request_id);
   if (!callbacks)
     return;
 
   callbacks->onSuccess(blink::adoptWebPtr(
-      new blink::WebPushSubscription(endpoint, curve25519dh)));
+      new blink::WebPushSubscription(endpoint, p256dh)));
 
   subscription_callbacks_.Remove(request_id);
 }
diff --git a/content/child/push_messaging/push_provider.h b/content/child/push_messaging/push_provider.h
index 546dfe7..c01796b 100644
--- a/content/child/push_messaging/push_provider.h
+++ b/content/child/push_messaging/push_provider.h
@@ -67,7 +67,7 @@
   // IPC message handlers.
   void OnSubscribeFromWorkerSuccess(int request_id,
                                     const GURL& endpoint,
-                                    const std::vector<uint8_t>& curve25519dh);
+                                    const std::vector<uint8_t>& p256dh);
   void OnSubscribeFromWorkerError(int request_id,
                                   PushRegistrationStatus status);
   void OnUnsubscribeSuccess(int request_id, bool did_unsubscribe);
@@ -76,7 +76,7 @@
                           const std::string& error_message);
   void OnGetRegistrationSuccess(int request_id,
                                 const GURL& endpoint,
-                                const std::vector<uint8_t>& curve25519dh);
+                                const std::vector<uint8_t>& p256dh);
   void OnGetRegistrationError(int request_id, PushGetRegistrationStatus status);
   void OnGetPermissionStatusSuccess(int request_id,
                                     blink::WebPushPermissionStatus status);
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index aeb1cbe..e96efec 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -180,6 +180,9 @@
                                          base::SharedMemoryHandle shm_handle,
                                          int shm_size,
                                          base::ProcessId renderer_pid) {
+  // TODO(erikchen): Temporary debugging to help track down crash.
+  // http://crbug.com/527588.
+  CHECK_LE(shm_size, 512 * 1024);
   TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer");
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
diff --git a/content/child/web_memory_dump_provider_adapter.cc b/content/child/web_memory_dump_provider_adapter.cc
index 7210a7e..ef2cab81 100644
--- a/content/child/web_memory_dump_provider_adapter.cc
+++ b/content/child/web_memory_dump_provider_adapter.cc
@@ -33,7 +33,7 @@
       NOTREACHED();
       return false;
   }
-  WebProcessMemoryDumpImpl web_pmd_impl(pmd);
+  WebProcessMemoryDumpImpl web_pmd_impl(args.level_of_detail, pmd);
 
   return web_memory_dump_provider_->onMemoryDump(level, &web_pmd_impl);
 }
diff --git a/content/child/web_process_memory_dump_impl.cc b/content/child/web_process_memory_dump_impl.cc
index 688b6c1..ec7c47b 100644
--- a/content/child/web_process_memory_dump_impl.cc
+++ b/content/child/web_process_memory_dump_impl.cc
@@ -6,19 +6,21 @@
 
 #include "base/trace_event/process_memory_dump.h"
 #include "content/child/web_memory_allocator_dump_impl.h"
+#include "skia/ext/SkTraceMemoryDump_chrome.h"
 
 namespace content {
 
 WebProcessMemoryDumpImpl::WebProcessMemoryDumpImpl()
     : owned_process_memory_dump_(
           new base::trace_event::ProcessMemoryDump(nullptr)),
-      process_memory_dump_(owned_process_memory_dump_.get()) {
-}
+      process_memory_dump_(owned_process_memory_dump_.get()),
+      level_of_detail_(base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {}
 
 WebProcessMemoryDumpImpl::WebProcessMemoryDumpImpl(
+    base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
     base::trace_event::ProcessMemoryDump* process_memory_dump)
-    : process_memory_dump_(process_memory_dump) {
-}
+    : process_memory_dump_(process_memory_dump),
+      level_of_detail_(level_of_detail) {}
 
 WebProcessMemoryDumpImpl::~WebProcessMemoryDumpImpl() {
 }
@@ -132,4 +134,19 @@
       base::trace_event::MemoryAllocatorDumpGuid(target));
 }
 
+void WebProcessMemoryDumpImpl::AddSuballocation(
+    blink::WebMemoryAllocatorDumpGuid source,
+    const blink::WebString& targetNodeName) {
+  process_memory_dump_->AddSuballocation(
+      base::trace_event::MemoryAllocatorDumpGuid(source),
+      targetNodeName.utf8());
+}
+
+SkTraceMemoryDump* WebProcessMemoryDumpImpl::CreateDumpAdapterForSkia(
+    const blink::WebString& dumpNamePrefix) {
+  sk_trace_dump_list_.push_back(new skia::SkTraceMemoryDump_Chrome(
+      dumpNamePrefix.utf8(), level_of_detail_, process_memory_dump_));
+  return sk_trace_dump_list_.back();
+}
+
 }  // namespace content
diff --git a/content/child/web_process_memory_dump_impl.h b/content/child/web_process_memory_dump_impl.h
index 2042d258..8533242d 100644
--- a/content/child/web_process_memory_dump_impl.h
+++ b/content/child/web_process_memory_dump_impl.h
@@ -8,6 +8,8 @@
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/trace_event/memory_dump_request_args.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebProcessMemoryDump.h"
 
@@ -18,6 +20,10 @@
 }  // namespace base
 }  // namespace trace_event
 
+namespace skia {
+class SkTraceMemoryDump_Chrome;
+}  // namespace skia
+
 namespace content {
 
 class WebMemoryAllocatorDumpImpl;
@@ -34,6 +40,7 @@
 
   // Wraps (without owning) an existing ProcessMemoryDump.
   explicit WebProcessMemoryDumpImpl(
+      base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
       base::trace_event::ProcessMemoryDump* process_memory_dump);
 
   ~WebProcessMemoryDumpImpl() override;
@@ -53,6 +60,10 @@
                         int importance) override;
   void AddOwnershipEdge(blink::WebMemoryAllocatorDumpGuid source,
                         blink::WebMemoryAllocatorDumpGuid target) override;
+  void AddSuballocation(blink::WebMemoryAllocatorDumpGuid source,
+                        const blink::WebString& targetNodeName) override;
+  SkTraceMemoryDump* CreateDumpAdapterForSkia(
+      const blink::WebString& dumpNamePrefix) override;
 
   const base::trace_event::ProcessMemoryDump* process_memory_dump() const {
     return process_memory_dump_;
@@ -71,6 +82,9 @@
   // createMemoryAllocatorDump() calls will be proxied to.
   base::trace_event::ProcessMemoryDump* process_memory_dump_;  // Not owned.
 
+  // TODO(ssid): Remove it once this information is added to ProcessMemoryDump.
+  base::trace_event::MemoryDumpLevelOfDetail level_of_detail_;
+
   // Reverse index of MemoryAllocatorDump -> WebMemoryAllocatorDumpImpl wrapper.
   // By design WebMemoryDumpProvider(s) are not supposed to hold the pointer
   // to the WebProcessMemoryDump passed as argument of the onMemoryDump() call.
@@ -80,6 +94,9 @@
                          scoped_ptr<WebMemoryAllocatorDumpImpl>>
       memory_allocator_dumps_;
 
+  // Stores SkTraceMemoryDump for the current ProcessMemoryDump.
+  ScopedVector<skia::SkTraceMemoryDump_Chrome> sk_trace_dump_list_;
+
   DISALLOW_COPY_AND_ASSIGN(WebProcessMemoryDumpImpl);
 };
 
diff --git a/content/common/background_sync_service.mojom b/content/common/background_sync_service.mojom
index b4c9b93..b0bb88c 100644
--- a/content/common/background_sync_service.mojom
+++ b/content/common/background_sync_service.mojom
@@ -36,19 +36,19 @@
   GetRegistrations(BackgroundSyncPeriodicity periodicity,
                    int64 service_worker_registration_id)
       => (BackgroundSyncError err, array<SyncRegistration> registrations);
-  Unregister(BackgroundSyncPeriodicity periodicity, int32 handle_id,
-             int64 service_worker_registration_id) => (BackgroundSyncError err);
+  Unregister(int64 handle_id, int64 service_worker_registration_id) 
+      => (BackgroundSyncError err);
   GetPermissionStatus(BackgroundSyncPeriodicity periodicity,
                       int64 service_worker_registration_id)
       => (BackgroundSyncError err, PermissionStatus status);
-  DuplicateRegistrationHandle(int32 handle_id) 
+  DuplicateRegistrationHandle(int64 handle_id) 
       => (BackgroundSyncError err, SyncRegistration? registration);  
-  ReleaseRegistration(int32 handle_id);
-  NotifyWhenDone(int32 handle_id) => (BackgroundSyncError err, BackgroundSyncState final_status);
+  ReleaseRegistration(int64 handle_id);
+  NotifyWhenDone(int64 handle_id) => (BackgroundSyncError err, BackgroundSyncState final_status);
 };
 
 interface BackgroundSyncServiceClient {
-  Sync(int32 handle_id)
+  Sync(int64 handle_id)
       => (ServiceWorkerEventStatus status);
 };
 
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc
index 0c1fab2..071d96d 100644
--- a/content/common/child_process_host_impl.cc
+++ b/content/common/child_process_host_impl.cc
@@ -111,14 +111,6 @@
 #if defined(OS_WIN)
   AddFilter(new FontCacheDispatcher());
 #endif
-#if USE_ATTACHMENT_BROKER
-  // Ensure that the privileged attachment broker gets constructed early in the
-  // life cycle of a child process. This ensures that when a test is being run
-  // in one of the single process modes, the global attachment broker is the
-  // privileged attachment broker, rather than an unprivileged attachment
-  // broker.
-  GetAttachmentBroker();
-#endif
 }
 
 ChildProcessHostImpl::~ChildProcessHostImpl() {
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc
index aa34ca18..c97af030 100644
--- a/content/common/content_switches_internal.cc
+++ b/content/common/content_switches_internal.cc
@@ -70,11 +70,10 @@
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
 
   std::string mime_types =
-      cmd_line->GetSwitchValueASCII(switches::kEnableWin32kLockDownMimeTypes);
-
-  if (mime_types.empty()) {
+      base::FieldTrialList::FindFullName("EnableWin32kLockDownMimeTypes");
+  if (cmd_line->HasSwitch(switches::kEnableWin32kLockDownMimeTypes)) {
     mime_types =
-        base::FieldTrialList::FindFullName("EnableWin32kLockDownMimeTypes");
+        cmd_line->GetSwitchValueASCII(switches::kEnableWin32kLockDownMimeTypes);
   }
 
   // Consider the value * to enable all mime types for lockdown.
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 5e02c04..468dffc 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -671,6 +671,13 @@
 // Note: this covers only the immediate frame / doesn't cover subframes.
 IPC_MESSAGE_ROUTED0(FrameMsg_GetSavableResourceLinks)
 
+// Get html data by serializing the target frame and replacing all resource
+// links with a path to the local copy passed in the message payload.
+IPC_MESSAGE_ROUTED3(FrameMsg_GetSerializedHtmlWithLocalLinks,
+                    std::vector<GURL> /* urls that have local copy */,
+                    std::vector<base::FilePath> /* paths of local copy */,
+                    base::FilePath /* local directory path */)
+
 #if defined(ENABLE_PLUGINS)
 // Notifies the renderer of updates to the Plugin Power Saver origin whitelist.
 IPC_MESSAGE_ROUTED1(FrameMsg_UpdatePluginContentOriginWhitelist,
@@ -1167,6 +1174,12 @@
 // errors gathering the links.
 IPC_MESSAGE_ROUTED0(FrameHostMsg_SavableResourceLinksError)
 
+// Response to FrameMsg_GetSerializedHtmlWithLocalLinks.
+IPC_MESSAGE_ROUTED3(FrameHostMsg_SerializedHtmlWithLocalLinksResponse,
+                    GURL /* frame URL */,
+                    std::string /* data buffer */,
+                    int32 /* complete status */)
+
 // Sent when the renderer updates hint for importance of a tab.
 IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdatePageImportanceSignals,
                     content::PageImportanceSignals)
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index fc931b36..20977f2 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -397,10 +397,11 @@
   DVLOG(4) << "Notifying output picture id " << output_id
            << " for input "<< input_id << " is ready";
   // TODO(posciak): Use visible size from decoder here instead
-  // (crbug.com/402760).
+  // (crbug.com/402760). Passing (0, 0) results in the client using the
+  // visible size extracted from the container instead.
   if (client_)
     client_->PictureReady(media::Picture(output_id, input_id,
-                                         gfx::Rect(picture->size()),
+                                         gfx::Rect(0, 0),
                                          picture->AllowOverlay()));
 }
 
diff --git a/content/common/media/audio_messages.h b/content/common/media/audio_messages.h
index ce26bca..a8d4ab032 100644
--- a/content/common/media/audio_messages.h
+++ b/content/common/media/audio_messages.h
@@ -28,8 +28,8 @@
 IPC_ENUM_TRAITS_MAX_VALUE(media::AudioOutputIPCDelegateState,
                           media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_LAST)
 
-IPC_ENUM_TRAITS_MAX_VALUE(media::SwitchOutputDeviceResult,
-                          media::SWITCH_OUTPUT_DEVICE_RESULT_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(media::OutputDeviceStatus,
+                          media::OUTPUT_DEVICE_STATUS_LAST)
 
 IPC_ENUM_TRAITS_MAX_VALUE(media::AudioParameters::Format,
                           media::AudioParameters::AUDIO_FORMAT_LAST)
@@ -49,7 +49,7 @@
 // authorized device.
 IPC_MESSAGE_CONTROL3(AudioMsg_NotifyDeviceAuthorized,
                      int /* stream id */,
-                     bool /* success */,
+                     media::OutputDeviceStatus /* device_status */,
                      media::AudioParameters /* output parameters */)
 
 // Tell the renderer process that an audio stream has been created.
@@ -94,7 +94,7 @@
 // update after the renderer has requested a SwitchOutputDevice.
 IPC_MESSAGE_CONTROL2(AudioMsg_NotifyOutputDeviceSwitched,
                      int /* stream id */,
-                     media::SwitchOutputDeviceResult /* result */)
+                     media::OutputDeviceStatus /* result */)
 
 // Messages sent from the renderer to the browser.
 
diff --git a/content/common/media/video_capture.h b/content/common/media/video_capture.h
index d3fb7ae..3631273 100644
--- a/content/common/media/video_capture.h
+++ b/content/common/media/video_capture.h
@@ -23,8 +23,10 @@
 // browser process and renderer process. Browser process sends information about
 // the current capture state and error to the renderer process using this type.
 enum VideoCaptureState {
+  VIDEO_CAPTURE_STATE_STARTING,
   VIDEO_CAPTURE_STATE_STARTED,
   VIDEO_CAPTURE_STATE_PAUSED,
+  VIDEO_CAPTURE_STATE_STOPPING,
   VIDEO_CAPTURE_STATE_STOPPED,
   VIDEO_CAPTURE_STATE_ERROR,
   VIDEO_CAPTURE_STATE_ENDED,
diff --git a/content/common/memory_messages.h b/content/common/memory_messages.h
index a81eaf8..6ae158a 100644
--- a/content/common/memory_messages.h
+++ b/content/common/memory_messages.h
@@ -8,6 +8,7 @@
 
 // Multiply-included message header, no traditional include guard.
 
+#include "base/memory/memory_pressure_listener.h"
 #include "ipc/ipc_message_macros.h"
 #include "content/common/content_export.h"
 
@@ -16,7 +17,17 @@
 
 #define IPC_MESSAGE_START MemoryMsgStart
 
-// Sent to all child processes to enable/disable suppressing memory
+IPC_ENUM_TRAITS_VALIDATE(
+    base::MemoryPressureListener::MemoryPressureLevel,
+    (value == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE ||
+     value == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL))
+
+// Sent to all child processes to enable/disable suppressing memory pressure
 // notifications.
 IPC_MESSAGE_CONTROL1(MemoryMsg_SetPressureNotificationsSuppressed,
                      bool /* suppressed */)
+
+// Sent to all child processes to simulate a memory pressure notification.
+IPC_MESSAGE_CONTROL1(
+    MemoryMsg_SimulatePressureNotification,
+    base::MemoryPressureListener::MemoryPressureLevel /* level */)
diff --git a/content/common/push_messaging_messages.h b/content/common/push_messaging_messages.h
index 0578c24..4e591861 100644
--- a/content/common/push_messaging_messages.h
+++ b/content/common/push_messaging_messages.h
@@ -34,12 +34,12 @@
 IPC_MESSAGE_ROUTED3(PushMessagingMsg_SubscribeFromDocumentSuccess,
                     int32_t /* request_id */,
                     GURL /* push_endpoint */,
-                    std::vector<uint8_t> /* curve25519dh */)
+                    std::vector<uint8_t> /* p256dh */)
 
 IPC_MESSAGE_CONTROL3(PushMessagingMsg_SubscribeFromWorkerSuccess,
                      int32_t /* request_id */,
                      GURL /* push_endpoint */,
-                     std::vector<uint8_t> /* curve25519dh */)
+                     std::vector<uint8_t> /* p256dh */)
 
 IPC_MESSAGE_ROUTED2(PushMessagingMsg_SubscribeFromDocumentError,
                     int32_t /* request_id */,
@@ -61,7 +61,7 @@
 IPC_MESSAGE_CONTROL3(PushMessagingMsg_GetRegistrationSuccess,
                      int32_t /* request_id */,
                      GURL /* push_endpoint */,
-                     std::vector<uint8_t> /* curve25519dh */)
+                     std::vector<uint8_t> /* p256dh */)
 
 IPC_MESSAGE_CONTROL2(PushMessagingMsg_GetRegistrationError,
                      int32_t /* request_id */,
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index c4d5983e..be4dd59 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -556,13 +556,6 @@
 
 #endif
 
-// Get html data by serializing all frames of current page with lists
-// which contain all resource links that have local copy.
-IPC_MESSAGE_ROUTED3(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
-                    std::vector<GURL> /* urls that have local copy */,
-                    std::vector<base::FilePath> /* paths of local copy */,
-                    base::FilePath /* local directory path */)
-
 // Tells the render side that a ViewHostMsg_LockMouse message has been
 // processed. |succeeded| indicates whether the mouse has been successfully
 // locked or not.
@@ -880,6 +873,12 @@
 // Notification of a change in scrollbar appearance and/or behavior.
 IPC_MESSAGE_CONTROL1(ViewMsg_UpdateScrollbarTheme,
                      ViewMsg_UpdateScrollbarTheme_Params /* params */)
+
+// Notification that the OS X Aqua color preferences changed.
+IPC_MESSAGE_CONTROL3(ViewMsg_SystemColorsChanged,
+                     int /* AppleAquaColorVariant */,
+                     std::string /* AppleHighlightedTextColor */,
+                     std::string /* AppleHighlightColor */);
 #endif
 
 #if defined(OS_ANDROID)
@@ -1273,11 +1272,6 @@
                      int /* job_id */,
                      int64 /* size of the MHTML file, -1 if error */)
 
-IPC_MESSAGE_ROUTED3(ViewHostMsg_SendSerializedHtmlData,
-                    GURL /* frame's url */,
-                    std::string /* data buffer */,
-                    int32 /* complete status */)
-
 // Notifies the browser of an event occurring in the media pipeline.
 IPC_MESSAGE_CONTROL1(ViewHostMsg_MediaLogEvents,
                      std::vector<media::MediaLogEvent> /* events */)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 992d6a4..0f43540 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -181,7 +181,10 @@
       'public/browser/navigation_details.cc',
       'public/browser/navigation_details.h',
       'public/browser/navigation_entry.h',
+      'public/browser/navigation_handle.cc',
       'public/browser/navigation_handle.h',
+      'public/browser/navigation_throttle.cc',
+      'public/browser/navigation_throttle.h',
       'public/browser/navigation_type.h',
       'public/browser/navigator_connect_context.h',
       'public/browser/navigator_connect_service_factory.h',
@@ -343,8 +346,6 @@
       'browser/android/animation_utils.h',
       'browser/android/background_sync_launcher_android.cc',
       'browser/android/background_sync_launcher_android.h',
-      'browser/android/background_sync_network_observer_android.cc',
-      'browser/android/background_sync_network_observer_android.h',
       'browser/android/browser_jni_registrar.cc',
       'browser/android/browser_jni_registrar.h',
       'browser/android/browser_startup_controller.cc',
@@ -975,6 +976,8 @@
       'browser/loader/mime_type_resource_handler.h',
       'browser/loader/navigation_resource_handler.cc',
       'browser/loader/navigation_resource_handler.h',
+      'browser/loader/navigation_resource_throttle.cc',
+      'browser/loader/navigation_resource_throttle.h',
       'browser/loader/navigation_url_loader.cc',
       'browser/loader/navigation_url_loader.h',
       'browser/loader/navigation_url_loader_delegate.h',
@@ -1370,8 +1373,6 @@
       'browser/service_worker/embedded_worker_instance.h',
       'browser/service_worker/embedded_worker_registry.cc',
       'browser/service_worker/embedded_worker_registry.h',
-      'browser/service_worker/service_worker_cache_writer.cc',
-      'browser/service_worker/service_worker_cache_writer.h',
       'browser/service_worker/service_worker_context_core.cc',
       'browser/service_worker/service_worker_context_core.h',
       'browser/service_worker/service_worker_context_observer.h',
diff --git a/content/content_jni.gypi b/content/content_jni.gypi
index 3a154d4..c93e4efd 100644
--- a/content/content_jni.gypi
+++ b/content/content_jni.gypi
@@ -12,7 +12,6 @@
     'public/android/java/src/org/chromium/content/app/ContentMain.java',
     'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java',
     'public/android/java/src/org/chromium/content/browser/BackgroundSyncLauncher.java',
-    'public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java',
     'public/android/java/src/org/chromium/content/browser/BrowserStartupController.java',
     'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java',
     'public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index b311054..2f0be33 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -419,6 +419,8 @@
       'renderer/stats_collection_observer.h',
       'renderer/text_input_client_observer.cc',
       'renderer/text_input_client_observer.h',
+      'renderer/theme_helper_mac.mm',
+      'renderer/theme_helper_mac.h',
       'renderer/usb/type_converters.cc',
       'renderer/usb/type_converters.h',
       'renderer/usb/web_usb_client_impl.cc',
@@ -701,6 +703,10 @@
       'renderer/media/webrtc_logging.h',
       'renderer/media/webrtc_uma_histograms.cc',
       'renderer/media/webrtc_uma_histograms.h',
+      'renderer/p2p/empty_network_manager.cc',
+      'renderer/p2p/empty_network_manager.h',
+      'renderer/p2p/filtering_network_manager.cc',
+      'renderer/p2p/filtering_network_manager.h',
       'renderer/p2p/host_address_request.cc',
       'renderer/p2p/host_address_request.h',
       'renderer/p2p/ipc_network_manager.cc',
@@ -708,6 +714,8 @@
       'renderer/p2p/ipc_socket_factory.cc',
       'renderer/p2p/ipc_socket_factory.h',
       'renderer/p2p/network_list_observer.h',
+      'renderer/p2p/network_manager_uma.cc',
+      'renderer/p2p/network_manager_uma.h',
       'renderer/p2p/port_allocator.cc',
       'renderer/p2p/port_allocator.h',
       'renderer/p2p/socket_client_impl.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index d4c3b441..7876515 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -192,6 +192,7 @@
       'browser/accessibility/dump_accessibility_tree_browsertest.cc',
       'browser/accessibility/site_per_process_accessibility_browsertest.cc',
       'browser/accessibility/snapshot_ax_tree_browsertest.cc',
+      'browser/accessibility/touch_accessibility_aura_browsertest.cc',
       'browser/background_sync/background_sync_browsertest.cc',
       'browser/battery_status/battery_monitor_impl_browsertest.cc',
       'browser/battery_status/battery_monitor_integration_browsertest.cc',
@@ -384,6 +385,7 @@
       'browser/download/file_metadata_unittest_linux.cc',
       'browser/download/rate_estimator_unittest.cc',
       'browser/download/save_package_unittest.cc',
+      'browser/fileapi/blob_reader_unittest.cc',
       'browser/fileapi/blob_storage_context_unittest.cc',
       'browser/fileapi/blob_url_request_job_unittest.cc',
       'browser/fileapi/copy_or_move_file_validator_unittest.cc',
@@ -555,7 +557,6 @@
       'browser/service_worker/embedded_worker_instance_unittest.cc',
       'browser/service_worker/embedded_worker_test_helper.cc',
       'browser/service_worker/embedded_worker_test_helper.h',
-      'browser/service_worker/service_worker_cache_writer_unittest.cc',
       'browser/service_worker/service_worker_context_request_handler_unittest.cc',
       'browser/service_worker/service_worker_context_unittest.cc',
       'browser/service_worker/service_worker_controllee_request_handler_unittest.cc',
@@ -601,6 +602,8 @@
       'child/blob_storage/blob_consolidation_unittest.cc',
       'child/fileapi/webfilewriter_base_unittest.cc',
       'child/indexed_db/indexed_db_dispatcher_unittest.cc',
+      'child/indexed_db/mock_webidbcallbacks.cc',
+      'child/indexed_db/mock_webidbcallbacks.h',
       'child/indexed_db/webidbcursor_impl_unittest.cc',
       'child/multipart_response_delegate_unittest.cc',
       'child/notifications/notification_data_conversions_unittest.cc',
@@ -769,6 +772,7 @@
       'renderer/media/webrtc_local_audio_source_provider_unittest.cc',
       'renderer/media/webrtc_local_audio_track_unittest.cc',
       'renderer/media/webrtc_uma_histograms_unittest.cc',
+      'renderer/p2p/filtering_network_manager_unittest.cc',
       'renderer/p2p/ipc_network_manager_unittest.cc',
     ],
     'content_unittests_plugin_webrtc_sources': [
@@ -1883,10 +1887,6 @@
                   '<(PRODUCT_DIR)/content_unittests_apk/assets/natives_blob.bin',
                   '<(PRODUCT_DIR)/content_unittests_apk/assets/snapshot_blob.bin',
                 ],
-                'inputs': [
-                  '<(PRODUCT_DIR)/natives_blob.bin',
-                  '<(PRODUCT_DIR)/snapshot_blob.bin',
-                ],
               }],
             ],
           },
diff --git a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java b/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
deleted file mode 100644
index b459b255..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser;
-
-import android.content.Context;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeClassQualifiedName;
-import org.chromium.net.NetworkChangeNotifierAutoDetect;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Contains the Java code used by the BackgroundSyncNetworkObserverAndroid C++ class.
- *
- * The purpose of this class is to listen for and forward network connectivity events to the
- * BackgroundSyncNetworkObserverAndroid objects even when the application is paused. The standard
- * NetworkChangeNotifier does not listen for connectivity events when the application is paused.
- *
- * This class maintains a NetworkChangeNotifierAutoDetect, which exists for as long as any
- * BackgroundSyncNetworkObserverAndroid objects are registered.
- *
- * This class lives on the main thread.
- */
-@JNINamespace("content")
-class BackgroundSyncNetworkObserver implements NetworkChangeNotifierAutoDetect.Observer {
-    private static final String TAG = "cr_BgSyncNetObserver";
-
-    private NetworkChangeNotifierAutoDetect mNotifier;
-    private Context mContext;
-
-    // The singleton instance.
-    private static BackgroundSyncNetworkObserver sInstance = null;
-
-    // List of native observers. These are each called when the network state changes.
-    private List<Long> mNativePtrs;
-
-    private BackgroundSyncNetworkObserver(Context ctx) {
-        ThreadUtils.assertOnUiThread();
-        mContext = ctx;
-        mNativePtrs = new ArrayList<Long>();
-    }
-
-    @CalledByNative
-    private static BackgroundSyncNetworkObserver createObserver(Context ctx, long nativePtr) {
-        ThreadUtils.assertOnUiThread();
-        if (sInstance == null) {
-            sInstance = new BackgroundSyncNetworkObserver(ctx);
-        }
-        sInstance.registerObserver(nativePtr);
-        return sInstance;
-    }
-
-    private void registerObserver(final long nativePtr) {
-        ThreadUtils.assertOnUiThread();
-        // Create the NetworkChangeNotifierAutoDetect if it does not exist already.
-        if (mNotifier == null) {
-            mNotifier =
-                    new NetworkChangeNotifierAutoDetect(this, mContext, true /* always listen */);
-        }
-        mNativePtrs.add(nativePtr);
-
-        nativeNotifyConnectionTypeChanged(
-                nativePtr, mNotifier.getCurrentConnectionType(mNotifier.getCurrentNetworkState()));
-    }
-
-    @CalledByNative
-    private void removeObserver(long nativePtr) {
-        ThreadUtils.assertOnUiThread();
-        mNativePtrs.remove(nativePtr);
-        // Destroy the NetworkChangeNotifierAutoDetect if there are no more observers.
-        if (mNativePtrs.size() == 0 && mNotifier != null) {
-            mNotifier.destroy();
-            mNotifier = null;
-        }
-    }
-
-    @Override
-    public void onConnectionTypeChanged(int newConnectionType) {
-        ThreadUtils.assertOnUiThread();
-        for (Long nativePtr : mNativePtrs) {
-            nativeNotifyConnectionTypeChanged(nativePtr, newConnectionType);
-        }
-    }
-
-    @Override
-    public void onMaxBandwidthChanged(double maxBandwidthMbps) {}
-
-    @NativeClassQualifiedName("BackgroundSyncNetworkObserverAndroid::Observer")
-    private native void nativeNotifyConnectionTypeChanged(long nativePtr, int newConnectionType);
-}
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 24a09e3..dfc6e8a 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
@@ -2985,8 +2985,7 @@
         return null;
     }
 
-    // @TargetApi(Build.VERSION_CODES.M) TODO(sgurun) add method document once API is public
-    // crbug/512264
+    @TargetApi(Build.VERSION_CODES.M)
     public void onProvideVirtualStructure(final ViewStructure structure) {
         // Do not collect accessibility tree in incognito mode
         if (getWebContents().isIncognito()) {
@@ -3015,6 +3014,7 @@
     // When creating the View structure, the left and top are relative to the parent node.
     // The X scroll is not used, rather compensated through X-position, while the Y scroll
     // is provided.
+    @TargetApi(Build.VERSION_CODES.M)
     private void createVirtualStructure(ViewStructure viewNode, AccessibilitySnapshotNode node,
             int parentX, int parentY) {
         viewNode.setClassName(node.className);
diff --git a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
index 8060453..399eb255 100644
--- a/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
+++ b/content/public/android/java/src/org/chromium/content/common/ContentSwitches.java
@@ -43,9 +43,6 @@
     // Native switch - chrome_switches::kEnableInstantExtendedAPI
     public static final String ENABLE_INSTANT_EXTENDED_API = "enable-instant-extended-api";
 
-    // Native switch - shell_switches::kDumpRenderTree
-    public static final String DUMP_RENDER_TREE = "dump-render-tree";
-
     // Native switch - shell_switches::kRunLayoutTest
     public static final String RUN_LAYOUT_TEST = "run-layout-test";
 
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 725ab34..e710ed2 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -363,6 +363,12 @@
   callback.Run(nullptr);
 }
 
+ScopedVector<NavigationThrottle>
+ContentBrowserClient::CreateThrottlesForNavigation(
+    NavigationHandle* navigation_handle) {
+  return ScopedVector<NavigationThrottle>();
+}
+
 #if defined(OS_WIN)
 const wchar_t* ContentBrowserClient::GetResourceDllName() {
   return nullptr;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 55bb9e0..d01fe152 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -16,6 +16,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/values.h"
 #include "content/public/browser/certificate_request_result_type.h"
+#include "content/public/browser/navigation_throttle.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/media_stream_request.h"
 #include "content/public/common/resource_type.h"
@@ -96,6 +97,7 @@
 class ExternalVideoSurfaceContainer;
 class LocationProvider;
 class MediaObserver;
+class NavigationHandle;
 class NavigatorConnectContext;
 class NavigatorConnectServiceFactory;
 class PlatformNotificationService;
@@ -674,6 +676,14 @@
   // Allows the embedder to record |metric| for a specific |url|.
   virtual void RecordURLMetric(const std::string& metric, const GURL& url) {}
 
+  // Allows the embedder to register one or more NavigationThrottles for the
+  // navigation indicated by |navigation_handle|.  A NavigationThrottle is used
+  // to control the flow of a navigation on the UI thread. The embedder is
+  // guaranteed that the throttles will be executed in the order they were
+  // provided.
+  virtual ScopedVector<NavigationThrottle> CreateThrottlesForNavigation(
+      NavigationHandle* navigation_handle);
+
   // Populates |mappings| with all files that need to be mapped before launching
   // a child process.
 #if defined(OS_ANDROID)
diff --git a/content/public/browser/media_device_id.cc b/content/public/browser/media_device_id.cc
index aefe67a..876e12ac 100644
--- a/content/public/browser/media_device_id.cc
+++ b/content/public/browser/media_device_id.cc
@@ -3,39 +3,24 @@
 // found in the LICENSE file.
 #include "content/public/browser/media_device_id.h"
 
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "crypto/hmac.h"
 
 namespace content {
 
 std::string GetHMACForMediaDeviceID(const ResourceContext::SaltCallback& sc,
                                     const GURL& security_origin,
                                     const std::string& raw_unique_id) {
-  DCHECK(security_origin.is_valid());
-  DCHECK(!raw_unique_id.empty());
-  crypto::HMAC hmac(crypto::HMAC::SHA256);
-  const size_t digest_length = hmac.DigestLength();
-  std::vector<uint8> digest(digest_length);
-  std::string salt = sc.Run();
-  bool result = hmac.Init(security_origin.spec()) &&
-      hmac.Sign(raw_unique_id + salt, &digest[0], digest.size());
-  DCHECK(result);
-  return base::ToLowerASCII(base::HexEncode(&digest[0], digest.size()));
+  return MediaStreamManager::GetHMACForMediaDeviceID(sc, security_origin,
+                                                     raw_unique_id);
 }
 
 bool DoesMediaDeviceIDMatchHMAC(const ResourceContext::SaltCallback& sc,
                                 const GURL& security_origin,
                                 const std::string& device_guid,
                                 const std::string& raw_unique_id) {
-  DCHECK(security_origin.is_valid());
-  DCHECK(!raw_unique_id.empty());
-  std::string guid_from_raw_device_id =
-      GetHMACForMediaDeviceID(sc, security_origin, raw_unique_id);
-  return guid_from_raw_device_id == device_guid;
+  return MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+      sc, security_origin, device_guid, raw_unique_id);
 }
 
 bool GetMediaDeviceIDForHMAC(MediaStreamType stream_type,
diff --git a/content/public/browser/navigation_handle.cc b/content/public/browser/navigation_handle.cc
new file mode 100644
index 0000000..f5eaa118
--- /dev/null
+++ b/content/public/browser/navigation_handle.cc
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. 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/browser/navigation_handle.h"
+
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+
+namespace content {
+
+WebContents* NavigationHandle::GetWebContents() {
+  // The NavigationHandleImpl cannot access the WebContentsImpl as it would be
+  // a layering violation, hence the cast here.
+  return static_cast<WebContentsImpl*>(
+      static_cast<NavigationHandleImpl*>(this)->delegate());
+}
+
+// static
+scoped_ptr<NavigationHandle> NavigationHandle::CreateNavigationHandleForTesting(
+    const GURL& url,
+    bool is_main_frame,
+    WebContents* web_contents) {
+  scoped_ptr<NavigationHandleImpl> handle_impl = NavigationHandleImpl::Create(
+      url, is_main_frame, static_cast<WebContentsImpl*>(web_contents));
+  return scoped_ptr<NavigationHandle>(handle_impl.Pass());
+}
+
+}  // namespace content
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h
index 18183736..2a12cb63 100644
--- a/content/public/browser/navigation_handle.h
+++ b/content/public/browser/navigation_handle.h
@@ -6,28 +6,71 @@
 #define CONTENT_PUBLIC_BROWSER_NAVIGATION_HANDLE_H_
 
 #include "content/common/content_export.h"
+#include "content/public/browser/navigation_throttle.h"
+#include "content/public/common/referrer.h"
 #include "net/base/net_errors.h"
+#include "ui/base/page_transition_types.h"
 
 class GURL;
 
 namespace content {
+class NavigationThrottle;
 class RenderFrameHost;
+class WebContents;
 
 // A NavigationHandle tracks information related to a single navigation.
 class CONTENT_EXPORT NavigationHandle {
  public:
   virtual ~NavigationHandle() {}
 
+  // Parameters available at navigation start time -----------------------------
+  //
+  // These parameters are always available during the navigation. Note that
+  // some may change during navigation (e.g. due to server redirects).
+
   // The URL the frame is navigating to. This may change during the navigation
   // when encountering a server redirect.
-  virtual const GURL& GetURL() const = 0;
+  virtual const GURL& GetURL() = 0;
+
+  // Whether the navigation is taking place in the main frame or in a subframe.
+  // This remains constant over the navigation lifetime.
+  virtual bool IsInMainFrame() = 0;
+
+  // The WebContents the navigation is taking place in.
+  WebContents* GetWebContents();
+
+  // Parameters available at network request start time ------------------------
+  //
+  // The following parameters are only available when the network request is
+  // made for the navigation (or at commit time if no network request is made).
+  // This corresponds to NavigationThrottle::WillSendRequest. They should not
+  // be queried before that.
+
+  // Whether the navigation is a POST or a GET. This may change during the
+  // navigation when encountering a server redirect.
+  virtual bool IsPost() = 0;
+
+  // Returns a sanitized version of the referrer for this request.
+  virtual const Referrer& GetReferrer() = 0;
+
+  // Whether the navigation was initiated by a user gesture. Note that this
+  // will return false for browser-initiated navigations.
+  // TODO(clamy): when PlzNavigate launches, this should return true for
+  // browser-initiated navigations.
+  virtual bool HasUserGesture() = 0;
+
+  // Returns the page transition type.
+  virtual ui::PageTransition GetPageTransition() = 0;
+
+  // Whether the target URL cannot be handled by the browser's internal protocol
+  // handlers.
+  virtual bool IsExternalProtocol() = 0;
+
+  // Navigation control flow --------------------------------------------------
 
   // The net error code if an error happened prior to commit. Otherwise it will
   // be net::OK.
-  virtual net::Error GetNetErrorCode() const = 0;
-
-  // Whether the navigation is taking place in the main frame or in a subframe.
-  virtual bool IsInMainFrame() const = 0;
+  virtual net::Error GetNetErrorCode() = 0;
 
   // Returns the RenderFrameHost this navigation is taking place in. This can
   // only be accessed after the navigation is ready to commit.
@@ -46,6 +89,40 @@
 
   // Whether the navigation resulted in an error page.
   virtual bool IsErrorPage() = 0;
+
+  // Testing methods ----------------------------------------------------------
+  //
+  // The following methods should be used exclusively for writing unit tests.
+
+  static scoped_ptr<NavigationHandle> CreateNavigationHandleForTesting(
+      const GURL& url,
+      bool is_main_frame,
+      WebContents* web_contents);
+
+  // Registers a NavigationThrottle for tests. The throttle can
+  // modify the request, pause the request or cancel the request. This will
+  // take ownership of the NavigationThrottle.
+  // Note: in non-test cases, NavigationThrottles should not be added directly
+  // but returned by the implementation of
+  // ContentBrowserClient::CreateThrottlesForNavigation. This ensures proper
+  // ordering of the throttles.
+  virtual void RegisterThrottleForTesting(
+      scoped_ptr<NavigationThrottle> navigation_throttle) = 0;
+
+  // Simulates the network request starting.
+  virtual NavigationThrottle::ThrottleCheckResult
+  CallWillStartRequestForTesting(bool is_post,
+                                 const Referrer& sanitized_referrer,
+                                 bool has_user_gesture,
+                                 ui::PageTransition transition,
+                                 bool is_external_protocol) = 0;
+
+  // Simulates the network request being redirected.
+  virtual NavigationThrottle::ThrottleCheckResult
+  CallWillRedirectRequestForTesting(const GURL& new_url,
+                                    bool new_method_is_post,
+                                    const GURL& new_referrer_url,
+                                    bool new_is_external_protocol) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/navigation_throttle.cc b/content/public/browser/navigation_throttle.cc
new file mode 100644
index 0000000..ac3b3aa
--- /dev/null
+++ b/content/public/browser/navigation_throttle.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. 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/browser/navigation_throttle.h"
+
+namespace content {
+
+NavigationThrottle::NavigationThrottle(NavigationHandle* navigation_handle)
+    : navigation_handle_(navigation_handle) {}
+
+NavigationThrottle::~NavigationThrottle() {}
+
+NavigationThrottle::ThrottleCheckResult NavigationThrottle::WillStartRequest() {
+  return NavigationThrottle::PROCEED;
+}
+
+NavigationThrottle::ThrottleCheckResult
+NavigationThrottle::WillRedirectRequest() {
+  return NavigationThrottle::PROCEED;
+}
+
+}  // namespace content
diff --git a/content/public/browser/navigation_throttle.h b/content/public/browser/navigation_throttle.h
new file mode 100644
index 0000000..ae5883b
--- /dev/null
+++ b/content/public/browser/navigation_throttle.h
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
+#define CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+class NavigationHandle;
+
+// A NavigationThrottle tracks and allows interaction with a navigation on the
+// UI thread.
+class CONTENT_EXPORT NavigationThrottle {
+ public:
+  // This is returned to the NavigationHandle to allow the navigation to
+  // proceed, or to cancel it.
+  enum ThrottleCheckResult {
+    PROCEED,
+    CANCEL_AND_IGNORE,
+  };
+
+  NavigationThrottle(NavigationHandle* navigation_handle);
+  virtual ~NavigationThrottle();
+
+  // Called when a network request is about to be made for this navigation.
+  virtual ThrottleCheckResult WillStartRequest();
+
+  // Called when a server redirect is received by the navigation.
+  virtual ThrottleCheckResult WillRedirectRequest();
+
+  // The NavigationHandle that is tracking the information related to this
+  // navigation.
+  NavigationHandle* navigation_handle() const { return navigation_handle_; }
+
+ private:
+  NavigationHandle* navigation_handle_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_NAVIGATION_THROTTLE_H_
diff --git a/content/public/browser/push_messaging_service.h b/content/public/browser/push_messaging_service.h
index 4e533d1..e7d7f7f 100644
--- a/content/public/browser/push_messaging_service.h
+++ b/content/public/browser/push_messaging_service.h
@@ -26,13 +26,13 @@
  public:
   using RegisterCallback =
       base::Callback<void(const std::string& registration_id,
-                          const std::vector<uint8_t>& curve25519dh,
+                          const std::vector<uint8_t>& p256dh,
                           PushRegistrationStatus status)>;
   using UnregisterCallback = base::Callback<void(PushUnregistrationStatus)>;
 
   using PublicKeyCallback = base::Callback<void(
       bool success,
-      const std::vector<uint8_t>& curve25519dh)>;
+      const std::vector<uint8_t>& p256dh)>;
 
   using StringCallback = base::Callback<void(const std::string& data,
                                              bool success,
diff --git a/content/public/common/background_sync.mojom b/content/public/common/background_sync.mojom
index 0f8b18a..6b5b95d 100644
--- a/content/public/common/background_sync.mojom
+++ b/content/public/common/background_sync.mojom
@@ -24,7 +24,7 @@
 };
 
 struct SyncRegistration {
-  int32 handle_id = -1;
+  int64 handle_id = -1;
   BackgroundSyncPeriodicity periodicity = ONE_SHOT;
   string tag = "";
   uint64 min_period_ms = 0;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index d1983cd..2cb4a2f 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -104,6 +104,9 @@
 // Disable experimental WebGL support.
 const char kDisableExperimentalWebGL[]      = "disable-webgl";
 
+// Comma-separated list of feature names to disable. See also kEnableFeatures.
+const char kDisableFeatures[]               = "disable-features";
+
 // Disable FileSystem API.
 const char kDisableFileSystem[]             = "disable-file-system";
 
@@ -319,9 +322,6 @@
 // PlzNavigate: Use the experimental browser-side navigation path.
 const char kEnableBrowserSideNavigation[]   = "enable-browser-side-navigation";
 
-// Enables Delay Agnostic AEC in WebRTC.
-const char kEnableDelayAgnosticAec[]        = "enable-delay-agnostic-aec";
-
 // Enables display list based 2d canvas implementation. Options:
 //  1. Enable: allow browser to use display list for 2d canvas (browser makes
 //     decision).
@@ -344,6 +344,9 @@
 const char kEnableExperimentalWebPlatformFeatures[] =
     "enable-experimental-web-platform-features";
 
+// Comma-separated list of feature names to enable. See also kDisableFeatures.
+const char kEnableFeatures[] = "enable-features";
+
 // Enable Web Bluetooth.
 const char kEnableWebBluetooth[] = "enable-web-bluetooth";
 
@@ -488,16 +491,6 @@
 // Load NPAPI plugins from the specified directory.
 const char kExtraPluginDir[]                = "extra-plugin-dir";
 
-// This option can be used to force field trials when testing changes locally.
-// The argument is a list of name and value pairs, separated by slashes. If a
-// trial name is prefixed with an asterisk, that trial will start activated.
-// For example, the following argument defines two trials, with the second one
-// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/"
-// This option is also used by the browser to send the list of trials to
-// renderers, using the same format. See
-// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
-const char kForceFieldTrials[]              = "force-fieldtrials";
-
 // Always use the Skia GPU backend for drawing layer tiles. Only valid with GPU
 // accelerated compositing + impl-side painting. Overrides the
 // kEnableGpuRasterization flag.
@@ -929,6 +922,9 @@
 #endif
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
+// Disables the bootstrap sandbox entirely.
+const char kDisableBootstrapSandbox[] = "disable-bootstrap-sandbox";
+
 // Disables support for Core Animation plugins. This is triggered when
 // accelerated compositing is disabled. See http://crbug.com/122430.
 const char kDisableCoreAnimationPlugins[] =
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 6ed87b8..06cd0847 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -43,6 +43,7 @@
 extern const char kDisableDomainBlockingFor3DAPIs[];
 CONTENT_EXPORT extern const char kDisableEncryptedMedia[];
 CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
+CONTENT_EXPORT extern const char kDisableFeatures[];
 CONTENT_EXPORT extern const char kDisableFileSystem[];
 CONTENT_EXPORT extern const char kDisableFlash3d[];
 CONTENT_EXPORT extern const char kDisableFlashStage3d[];
@@ -100,12 +101,12 @@
 CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[];
 CONTENT_EXPORT extern const char kEnableBlinkFeatures[];
 CONTENT_EXPORT extern const char kEnableBrowserSideNavigation[];
-CONTENT_EXPORT extern const char kEnableDelayAgnosticAec[];
 CONTENT_EXPORT extern const char kEnableDisplayList2dCanvas[];
 CONTENT_EXPORT extern const char kEnableDistanceFieldText[];
 CONTENT_EXPORT extern const char kEnableDownloadResumption[];
 CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
 CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
+CONTENT_EXPORT extern const char kEnableFeatures[];
 CONTENT_EXPORT extern const char kEnableWebBluetooth[];
 extern const char kEnableGpuClientTracing[];
 CONTENT_EXPORT extern const char kEnableGpuMemoryBufferVideoFrames[];
@@ -146,7 +147,6 @@
 CONTENT_EXPORT extern const char kExplicitlyAllowedPorts[];
 CONTENT_EXPORT extern const char kExtraPluginDir[];
 CONTENT_EXPORT extern const char kForceDisplayList2dCanvas[];
-CONTENT_EXPORT extern const char kForceFieldTrials[];
 CONTENT_EXPORT extern const char kForceGpuRasterization[];
 CONTENT_EXPORT extern const char kForceOverlayFullscreenVideo[];
 CONTENT_EXPORT extern const char kForceRendererAccessibility[];
@@ -277,6 +277,7 @@
 #endif
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
+extern const char kDisableBootstrapSandbox[];
 extern const char kDisableCoreAnimationPlugins[];
 extern const char kDisableThreadedEventHandlingMac[];
 #endif
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 4757bbf9..e09e803 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -211,4 +211,8 @@
   return nullptr;
 }
 
+bool ContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() {
+  return true;
+}
+
 }  // namespace content
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 7cf0667..df8d501 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -304,6 +304,10 @@
   virtual void WillDestroyServiceWorkerContextOnWorkerThread(
       v8::Local<v8::Context> context,
       const GURL& url) {}
+
+  // Whether this renderer should enforce preferences related to the WebRTC
+  // routing logic, i.e. allowing multiple routes and non-proxied UDP.
+  virtual bool ShouldEnforceWebRTCRoutingPreferences();
 };
 
 }  // namespace content
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc
index e5e7e0b..ba6709a3 100644
--- a/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -358,6 +358,8 @@
       return ui::AX_EVENT_CHILDREN_CHANGED;
     case blink::WebAXEventFocus:
       return ui::AX_EVENT_FOCUS;
+    case blink::WebAXEventHover:
+      return ui::AX_EVENT_HOVER;
     case blink::WebAXEventInvalidStatusChanged:
       return ui::AX_EVENT_INVALID_STATUS_CHANGED;
     case blink::WebAXEventLayoutComplete:
diff --git a/content/renderer/background_sync/background_sync_client_impl.cc b/content/renderer/background_sync/background_sync_client_impl.cc
index 29d288f..9ba8af3 100644
--- a/content/renderer/background_sync/background_sync_client_impl.cc
+++ b/content/renderer/background_sync/background_sync_client_impl.cc
@@ -30,7 +30,7 @@
       binding_(this, request.Pass()),
       callback_seq_num_(0) {}
 
-void BackgroundSyncClientImpl::Sync(int handle_id,
+void BackgroundSyncClientImpl::Sync(int64_t handle_id,
                                     const SyncCallback& callback) {
   DCHECK(!blink::Platform::current()->mainThread()->isCurrentThread());
   // Get a registration for the given handle_id from the provider. This way
diff --git a/content/renderer/background_sync/background_sync_client_impl.h b/content/renderer/background_sync/background_sync_client_impl.h
index 22931a9..b442d087 100644
--- a/content/renderer/background_sync/background_sync_client_impl.h
+++ b/content/renderer/background_sync/background_sync_client_impl.h
@@ -31,7 +31,7 @@
       mojo::InterfaceRequest<BackgroundSyncServiceClient> request);
 
   // BackgroundSyncServiceClient methods:
-  void Sync(int handle_id, const SyncCallback& callback) override;
+  void Sync(int64_t handle_id, const SyncCallback& callback) override;
   void SyncDidGetRegistration(int64_t callback_id,
                               BackgroundSyncError error,
                               SyncRegistrationPtr registration);
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc
index 0989009..781fee0f 100644
--- a/content/renderer/dom_serializer_browsertest.cc
+++ b/content/renderer/dom_serializer_browsertest.cc
@@ -259,23 +259,19 @@
     runner->Run();
   }
 
-  // Serialize page DOM according to specific page URL. The parameter
-  // recursive_serialization indicates whether we will serialize all
-  // sub-frames.
-  void SerializeDomForURL(const GURL& page_url,
-                          bool recursive_serialization) {
-    // Find corresponding WebFrame according to page_url.
-    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), page_url);
+  // Serialize DOM belonging to a frame with the specified |frame_url|.
+  void SerializeDomForURL(const GURL& frame_url) {
+    // Find corresponding WebFrame according to frame_url.
+    WebFrame* web_frame = FindSubFrameByURL(GetWebView(), frame_url);
     ASSERT_TRUE(web_frame != NULL);
     WebVector<WebURL> links;
-    links.assign(&page_url, 1);
+    links.assign(&frame_url, 1);
     WebString file_path =
         base::FilePath(FILE_PATH_LITERAL("c:\\dummy.htm")).AsUTF16Unsafe();
     WebVector<WebString> local_paths;
     local_paths.assign(&file_path, 1);
     // Start serializing DOM.
     bool result = WebPageSerializer::serialize(web_frame->toWebLocalFrame(),
-       recursive_serialization,
        static_cast<WebPageSerializerClient*>(this),
        links,
        local_paths,
@@ -291,7 +287,7 @@
     WebDocument doc = web_frame->document();
     ASSERT_TRUE(HasDocType(doc));
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Load the serialized contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -311,7 +307,7 @@
     WebDocument doc = web_frame->document();
     ASSERT_TRUE(!HasDocType(doc));
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Load the serialized contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -327,7 +323,7 @@
   void SerializeXMLDocWithBuiltInEntitiesOnRenderer(
       const GURL& xml_file_url, const std::string& original_contents) {
     // Do serialization.
-    SerializeDomForURL(xml_file_url, false);
+    SerializeDomForURL(xml_file_url);
     // Compare the serialized contents with original contents.
     ASSERT_TRUE(HasSerializedFrame(xml_file_url));
     const std::string& serialized_contents =
@@ -346,7 +342,7 @@
     ASSERT_TRUE(std::string::npos == original_contents.find(motw_declaration));
 
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Make sure the serialized contents have MOTW ;
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -372,7 +368,7 @@
         ASSERT_TRUE(charset_info.empty());
     }
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
 
     // Load the serialized contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
@@ -428,7 +424,7 @@
     ASSERT_TRUE(charset_declaration_count > 1);
 
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
 
     // Load the serialized contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
@@ -486,7 +482,7 @@
     ASSERT_TRUE(text_node.isTextNode());
     ASSERT_TRUE(std::string(text_node.nodeValue().utf8()) == "&<>\"\'");
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Compare the serialized contents with original contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -539,7 +535,7 @@
     WebString value = body_ele.getAttribute("title");
     ASSERT_TRUE(std::string(value.utf8()) == "&<>\"\'");
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Compare the serialized contents with original contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -580,7 +576,7 @@
     ASSERT_TRUE(base::UTF16ToWide(content) == parsed_value);
 
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Check the serialized string.
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -633,7 +629,7 @@
     ASSERT_NE(original_base_url, path_dir_url);
 
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
 
     // Load the serialized contents.
     ASSERT_TRUE(HasSerializedFrame(file_url));
@@ -703,7 +699,7 @@
     ASSERT_TRUE(head_element.childNodes().length() == 0);
 
     // Do serialization.
-    SerializeDomForURL(file_url, false);
+    SerializeDomForURL(file_url);
     // Make sure the serialized contents have META ;
     ASSERT_TRUE(HasSerializedFrame(file_url));
     const std::string& serialized_contents =
@@ -739,11 +735,6 @@
     ASSERT_TRUE(std::string(text_node_contents.utf8()) == "hello world");
   }
 
-  void SerializeDocumentWithDownloadedIFrameOnRenderer(const GURL& file_url) {
-    // Do a recursive serialization. We pass if we don't crash.
-    SerializeDomForURL(file_url, true);
-  }
-
   void SubResourceForElementsInNonHTMLNamespaceOnRenderer(
       const GURL& file_url) {
     WebFrame* web_frame = FindSubFrameByURL(GetWebView(), file_url);
@@ -1002,24 +993,6 @@
                    base::Unretained(this)));
 }
 
-// Test that we don't crash when the page contains an iframe that
-// was handled as a download (http://crbug.com/42212).
-IN_PROC_BROWSER_TEST_F(DomSerializerTests,
-                       SerializeDocumentWithDownloadedIFrame) {
-  base::FilePath page_file_path = GetTestFilePath(
-      "dom_serializer", "iframe-src-is-exe.htm");
-  GURL file_url = net::FilePathToFileURL(page_file_path);
-  ASSERT_TRUE(file_url.SchemeIsFile());
-  // Load the test file.
-  NavigateToURL(shell(), file_url);
-
-  PostTaskToInProcessRendererAndWait(
-        base::Bind(
-            &DomSerializerTests::
-                SerializeDocumentWithDownloadedIFrameOnRenderer,
-            base::Unretained(this), file_url));
-}
-
 IN_PROC_BROWSER_TEST_F(DomSerializerTests,
                        SubResourceForElementsInNonHTMLNamespace) {
   base::FilePath page_file_path = GetTestFilePath(
diff --git a/content/renderer/media/DEPS b/content/renderer/media/DEPS
index e8f1ace..19fad4be 100644
--- a/content/renderer/media/DEPS
+++ b/content/renderer/media/DEPS
@@ -3,5 +3,5 @@
   # For video copying, cropping and scaling.
   # TODO(wuchengli): remove this when RTCVideoEncoder supports zero copy.
   "+third_party/libyuv",
+  '+third_party/webrtc_overrides',
 ]
-
diff --git a/content/renderer/media/audio_message_filter.cc b/content/renderer/media/audio_message_filter.cc
index 0b0916d..ca0ecf0 100644
--- a/content/renderer/media/audio_message_filter.cc
+++ b/content/renderer/media/audio_message_filter.cc
@@ -198,14 +198,14 @@
 
 void AudioMessageFilter::OnDeviceAuthorized(
     int stream_id,
-    bool success,
+    media::OutputDeviceStatus device_status,
     const media::AudioParameters& output_params) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
   if (!delegate)
     return;
 
-  delegate->OnDeviceAuthorized(success, output_params);
+  delegate->OnDeviceAuthorized(device_status, output_params);
 }
 
 void AudioMessageFilter::OnStreamCreated(
@@ -247,7 +247,7 @@
 
 void AudioMessageFilter::OnOutputDeviceSwitched(
     int stream_id,
-    media::SwitchOutputDeviceResult result) {
+    media::OutputDeviceStatus result) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
   if (!delegate) {
diff --git a/content/renderer/media/audio_message_filter.h b/content/renderer/media/audio_message_filter.h
index ddbf78c..43431658 100644
--- a/content/renderer/media/audio_message_filter.h
+++ b/content/renderer/media/audio_message_filter.h
@@ -69,7 +69,7 @@
   // Received when the browser process has checked authorization to use an
   // audio output device.
   void OnDeviceAuthorized(int stream_id,
-                          bool success,
+                          media::OutputDeviceStatus device_status,
                           const media::AudioParameters& output_params);
 
   // Received when browser process has created an audio output stream.
@@ -84,8 +84,7 @@
 
   // Received when the browser process has finished processing a
   // SwitchOutputDevice request
-  void OnOutputDeviceSwitched(int stream_id,
-                              media::SwitchOutputDeviceResult result);
+  void OnOutputDeviceSwitched(int stream_id, media::OutputDeviceStatus result);
 
   // IPC sender for Send(); must only be accessed on |io_task_runner_|.
   IPC::Sender* sender_;
diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc
index ebcb1d3d..2b93cd1 100644
--- a/content/renderer/media/audio_message_filter_unittest.cc
+++ b/content/renderer/media/audio_message_filter_unittest.cc
@@ -26,9 +26,10 @@
   }
 
   void OnDeviceAuthorized(
-      bool success,
+      media::OutputDeviceStatus device_status,
       const media::AudioParameters& output_params) override {
     device_authorized_received_ = true;
+    device_status_ = device_status;
     output_params_ = output_params;
   }
 
@@ -40,9 +41,9 @@
     length_ = length;
   }
 
-  void OnOutputDeviceSwitched(media::SwitchOutputDeviceResult result) override {
+  void OnOutputDeviceSwitched(media::OutputDeviceStatus result) override {
     output_device_switched_received_ = true;
-    switch_output_device_result_ = result;
+    device_status_ = result;
   }
 
   void OnIPCClosed() override {}
@@ -53,6 +54,7 @@
 
     device_authorized_received_ = false;
     output_params_ = media::AudioParameters();
+    device_status_ = media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
 
     created_received_ = false;
     handle_ = base::SharedMemory::NULLHandle();
@@ -62,8 +64,6 @@
     volume_ = 0;
 
     output_device_switched_received_ = false;
-    switch_output_device_result_ =
-        media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL;
   }
 
   bool state_changed_received() { return state_changed_received_; }
@@ -71,6 +71,7 @@
 
   bool device_authorized_received() { return device_authorized_received_; }
   media::AudioParameters output_params() { return output_params_; }
+  media::OutputDeviceStatus device_status() { return device_status_; }
 
   bool created_received() { return created_received_; }
   base::SharedMemoryHandle handle() { return handle_; }
@@ -79,9 +80,6 @@
   bool output_device_switched_received() {
     return output_device_switched_received_;
   }
-  media::SwitchOutputDeviceResult switch_output_device_result() {
-    return switch_output_device_result_;
-  }
 
  private:
   bool state_changed_received_;
@@ -89,6 +87,7 @@
 
   bool device_authorized_received_;
   media::AudioParameters output_params_;
+  media::OutputDeviceStatus device_status_;
 
   bool created_received_;
   base::SharedMemoryHandle handle_;
@@ -98,7 +97,6 @@
   double volume_;
 
   bool output_device_switched_received_;
-  media::SwitchOutputDeviceResult switch_output_device_result_;
 
   DISALLOW_COPY_AND_ASSIGN(MockAudioDelegate);
 };
@@ -132,8 +130,8 @@
 
   // AudioMsg_NotifyDeviceAuthorized
   EXPECT_FALSE(delegate.device_authorized_received());
-  filter->OnMessageReceived(
-      AudioMsg_NotifyDeviceAuthorized(kStreamId, true, MockOutputParams()));
+  filter->OnMessageReceived(AudioMsg_NotifyDeviceAuthorized(
+      kStreamId, media::OUTPUT_DEVICE_STATUS_OK, MockOutputParams()));
   EXPECT_TRUE(delegate.device_authorized_received());
   EXPECT_TRUE(delegate.output_params().Equals(MockOutputParams()));
   delegate.Reset();
@@ -160,11 +158,9 @@
 
   // AudioMsg_NotifyOutputDeviceSwitched
   EXPECT_FALSE(delegate.output_device_switched_received());
-  filter->OnOutputDeviceSwitched(kStreamId,
-                                 media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+  filter->OnOutputDeviceSwitched(kStreamId, media::OUTPUT_DEVICE_STATUS_OK);
   EXPECT_TRUE(delegate.output_device_switched_received());
-  EXPECT_EQ(media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS,
-            delegate.switch_output_device_result());
+  EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_OK, delegate.device_status());
   message_loop.RunUntilIdle();
 
   ipc->CloseStream();
diff --git a/content/renderer/media/audio_renderer_mixer_manager.cc b/content/renderer/media/audio_renderer_mixer_manager.cc
index be12932..7ce87ae8 100644
--- a/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -16,11 +16,8 @@
 
 namespace content {
 
-AudioRendererMixerManager::AudioRendererMixerManager(
-    media::AudioHardwareConfig* hardware_config)
-    : hardware_config_(hardware_config),
-      sink_for_testing_(NULL) {
-}
+AudioRendererMixerManager::AudioRendererMixerManager()
+    : sink_for_testing_(nullptr) {}
 
 AudioRendererMixerManager::~AudioRendererMixerManager() {
   // References to AudioRendererMixers may be owned by garbage collected
@@ -54,7 +51,8 @@
     int source_render_frame_id,
     const media::AudioParameters& params,
     const std::string& device_id,
-    const url::Origin& security_origin) {
+    const url::Origin& security_origin,
+    media::OutputDeviceStatus* device_status) {
   // Effects are not passed through to output creation, so ensure none are set.
   DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS);
 
@@ -64,6 +62,9 @@
 
   AudioRendererMixerMap::iterator it = mixers_.find(key);
   if (it != mixers_.end()) {
+    if (device_status)
+      *device_status = media::OUTPUT_DEVICE_STATUS_OK;
+
     it->second.ref_count++;
     return it->second.mixer;
   }
@@ -74,6 +75,16 @@
           : AudioDeviceFactory::NewOutputDevice(source_render_frame_id, 0,
                                                 device_id, security_origin)
                 .get();
+
+  media::OutputDeviceStatus new_device_status =
+      sink->GetOutputDevice()->GetDeviceStatus();
+  if (device_status)
+    *device_status = new_device_status;
+  if (new_device_status != media::OUTPUT_DEVICE_STATUS_OK) {
+    sink->Stop();
+    return nullptr;
+  }
+
   media::AudioParameters hardware_params =
       sink->GetOutputDevice()->GetOutputParameters();
 
diff --git a/content/renderer/media/audio_renderer_mixer_manager.h b/content/renderer/media/audio_renderer_mixer_manager.h
index 7592ea5..53f29306 100644
--- a/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/content/renderer/media/audio_renderer_mixer_manager.h
@@ -12,6 +12,7 @@
 #include "base/synchronization/lock.h"
 #include "content/common/content_export.h"
 #include "media/audio/audio_parameters.h"
+#include "media/base/output_device.h"
 #include "url/origin.h"
 
 namespace media {
@@ -38,11 +39,7 @@
 // via the shared memory.  See http://crbug.com/114700.
 class CONTENT_EXPORT AudioRendererMixerManager {
  public:
-  // Construct an instance using the given audio hardware configuration.  The
-  // provided |hardware_config| is not owned by AudioRendererMixerManager and
-  // must outlive it.
-  explicit AudioRendererMixerManager(
-      media::AudioHardwareConfig* hardware_config);
+  AudioRendererMixerManager();
   ~AudioRendererMixerManager();
 
   // Creates an AudioRendererMixerInput with the proper callbacks necessary to
@@ -70,7 +67,8 @@
   media::AudioRendererMixer* GetMixer(int source_render_frame_id,
                                       const media::AudioParameters& params,
                                       const std::string& device_id,
-                                      const url::Origin& security_origin);
+                                      const url::Origin& security_origin,
+                                      media::OutputDeviceStatus* device_status);
 
   // Remove a mixer instance given a mixer if the only other reference is held
   // by AudioRendererMixerManager.  Every AudioRendererMixer owner must call
@@ -137,10 +135,6 @@
   AudioRendererMixerMap mixers_;
   base::Lock mixers_lock_;
 
-  // Audio hardware configuration.  Used to construct output AudioParameters for
-  // each AudioRendererMixer instance.
-  media::AudioHardwareConfig* const hardware_config_;
-
   media::AudioRendererSink* sink_for_testing_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManager);
diff --git a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
index 72a82f8..25afa99 100644
--- a/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
+++ b/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
@@ -22,7 +22,7 @@
 static const int kSampleRate = 48000;
 static const int kBufferSize = 8192;
 static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
-static const std::string kDeviceId;
+static const std::string kDefaultDeviceId;
 static const url::Origin kSecurityOrigin;
 
 static const int kRenderFrameId = 124;
@@ -32,17 +32,8 @@
 
 class AudioRendererMixerManagerTest : public testing::Test {
  public:
-  AudioRendererMixerManagerTest()
-      : fake_config_(AudioParameters(), AudioParameters()) {
-    AudioParameters output_params(
-        AudioParameters::AUDIO_PCM_LOW_LATENCY,
-        media::CHANNEL_LAYOUT_STEREO,
-        kSampleRate,
-        16,
-        kBufferSize);
-    fake_config_.UpdateOutputConfig(output_params);
-
-    manager_.reset(new AudioRendererMixerManager(&fake_config_));
+  AudioRendererMixerManagerTest() {
+    manager_.reset(new AudioRendererMixerManager());
 
     // We don't want to deal with instantiating a real AudioOutputDevice since
     // it's not important to our testing, so we inject a mock.
@@ -50,12 +41,14 @@
     manager_->SetAudioRendererSinkForTesting(mock_sink_.get());
   }
 
-  media::AudioRendererMixer* GetMixer(int source_render_frame_id,
-                                      const media::AudioParameters& params,
-                                      const std::string& device_id,
-                                      const url::Origin& security_origin) {
+  media::AudioRendererMixer* GetMixer(
+      int source_render_frame_id,
+      const media::AudioParameters& params,
+      const std::string& device_id,
+      const url::Origin& security_origin,
+      media::OutputDeviceStatus* device_status) {
     return manager_->GetMixer(source_render_frame_id, params, device_id,
-                              security_origin);
+                              security_origin, device_status);
   }
 
   void RemoveMixer(int source_render_frame_id,
@@ -66,13 +59,18 @@
                                  security_origin);
   }
 
+  void UseNonexistentSink() {
+    mock_sink_ = new media::MockAudioRendererSink(
+        media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND);
+    manager_->SetAudioRendererSinkForTesting(mock_sink_.get());
+  }
+
   // Number of instantiated mixers.
   int mixer_count() {
     return manager_->mixers_.size();
   }
 
  protected:
-  media::AudioHardwareConfig fake_config_;
   scoped_ptr<AudioRendererMixerManager> manager_;
   scoped_refptr<media::MockAudioRendererSink> mock_sink_;
 
@@ -95,25 +93,25 @@
       AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
       kBitsPerChannel, kBufferSize);
 
-  media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin);
+  media::AudioRendererMixer* mixer1 = GetMixer(
+      kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(mixer_count(), 1);
 
   // The same parameters should return the same mixer1.
-  EXPECT_EQ(mixer1,
-            GetMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin));
+  EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params1, kDefaultDeviceId,
+                             kSecurityOrigin, nullptr));
   EXPECT_EQ(mixer_count(), 1);
 
   // Remove the extra mixer we just acquired.
-  RemoveMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 1);
 
   media::AudioParameters params2(
       AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2,
       kBitsPerChannel, kBufferSize * 2);
-  media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params2, kDeviceId, kSecurityOrigin);
+  media::AudioRendererMixer* mixer2 = GetMixer(
+      kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin, nullptr);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(mixer_count(), 2);
 
@@ -121,9 +119,9 @@
   EXPECT_NE(mixer1, mixer2);
 
   // Remove both outstanding mixers.
-  RemoveMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 1);
-  RemoveMixer(kRenderFrameId, params2, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 0);
 }
 
@@ -139,8 +137,8 @@
                                  kSampleRate,
                                  kBitsPerChannel,
                                  kBufferSize);
-  media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin);
+  media::AudioRendererMixer* mixer1 = GetMixer(
+      kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(mixer_count(), 1);
 
@@ -149,10 +147,10 @@
   media::AudioParameters params2(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                  kChannelLayout, kSampleRate,
                                  kBitsPerChannel * 2, kBufferSize * 2);
-  EXPECT_EQ(mixer1,
-            GetMixer(kRenderFrameId, params2, kDeviceId, kSecurityOrigin));
+  EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId,
+                             kSecurityOrigin, nullptr));
   EXPECT_EQ(mixer_count(), 1);
-  RemoveMixer(kRenderFrameId, params2, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 1);
 
   // Modify some parameters that do matter.
@@ -161,14 +159,14 @@
                                  kBitsPerChannel, kBufferSize);
   ASSERT_NE(params3.channel_layout(), params1.channel_layout());
 
-  EXPECT_NE(mixer1,
-            GetMixer(kRenderFrameId, params3, kDeviceId, kSecurityOrigin));
+  EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId,
+                             kSecurityOrigin, nullptr));
   EXPECT_EQ(mixer_count(), 2);
-  RemoveMixer(kRenderFrameId, params3, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 1);
 
   // Remove final mixer.
-  RemoveMixer(kRenderFrameId, params1, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 0);
 }
 
@@ -225,31 +223,50 @@
   media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                                 kChannelLayout, kSampleRate, kBitsPerChannel,
                                 kBufferSize);
-  media::AudioRendererMixer* mixer1 =
-      GetMixer(kRenderFrameId, params, kDeviceId, kSecurityOrigin);
+  media::AudioRendererMixer* mixer1 = GetMixer(
+      kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr);
   ASSERT_TRUE(mixer1);
   EXPECT_EQ(mixer_count(), 1);
 
   std::string device_id2("fake-device-id");
   media::AudioRendererMixer* mixer2 =
-      GetMixer(kRenderFrameId, params, device_id2, kSecurityOrigin);
+      GetMixer(kRenderFrameId, params, device_id2, kSecurityOrigin, nullptr);
   ASSERT_TRUE(mixer2);
   EXPECT_EQ(mixer_count(), 2);
   EXPECT_NE(mixer1, mixer2);
 
   url::Origin security_origin2(GURL("http://localhost"));
-  media::AudioRendererMixer* mixer3 =
-      GetMixer(kRenderFrameId, params, kDeviceId, security_origin2);
+  media::AudioRendererMixer* mixer3 = GetMixer(
+      kRenderFrameId, params, kDefaultDeviceId, security_origin2, nullptr);
   ASSERT_TRUE(mixer3);
   EXPECT_EQ(mixer_count(), 3);
   EXPECT_NE(mixer1, mixer3);
   EXPECT_NE(mixer2, mixer3);
 
-  RemoveMixer(kRenderFrameId, params, kDeviceId, kSecurityOrigin);
+  RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 2);
   RemoveMixer(kRenderFrameId, params, device_id2, kSecurityOrigin);
   EXPECT_EQ(mixer_count(), 1);
-  RemoveMixer(kRenderFrameId, params, kDeviceId, security_origin2);
+  RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, security_origin2);
+  EXPECT_EQ(mixer_count(), 0);
+}
+
+// Verify that GetMixer() correctly returns a null mixer and an appropriate
+// status code when a nonexistent device is requested.
+TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
+  EXPECT_EQ(mixer_count(), 0);
+  UseNonexistentSink();
+  media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
+                                kChannelLayout, kSampleRate, kBitsPerChannel,
+                                kBufferSize);
+  std::string nonexistent_device_id("nonexistent-device-id");
+  media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK;
+  EXPECT_CALL(*mock_sink_.get(), Stop());
+  media::AudioRendererMixer* mixer =
+      GetMixer(kRenderFrameId, params, nonexistent_device_id, kSecurityOrigin,
+               &device_status);
+  EXPECT_FALSE(mixer);
+  EXPECT_EQ(device_status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND);
   EXPECT_EQ(mixer_count(), 0);
 }
 
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index 56d95707..23547d1 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -75,8 +75,6 @@
   const std::string group_name =
       base::FieldTrialList::FindFullName("UseDelayAgnosticAEC");
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kEnableDelayAgnosticAec))
-    return true;
   if (command_line->HasSwitch(switches::kDisableDelayAgnosticAec))
     return false;
 
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index b136a0e..ebc7784 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -25,7 +25,7 @@
 // MediaStreams are used by WebKit to open media devices such as Video Capture
 // and Audio input devices.
 // It's the complement of MediaStreamDispatcherHost (owned by
-// BrowserRenderProcessHost).
+// RenderProcessHostImpl).
 class CONTENT_EXPORT MediaStreamDispatcher
     : public RenderFrameObserver,
       public base::SupportsWeakPtr<MediaStreamDispatcher> {
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc
index 8dd7be9..902627a 100644
--- a/content/renderer/media/user_media_client_impl.cc
+++ b/content/renderer/media/user_media_client_impl.cc
@@ -654,11 +654,26 @@
            << "{request_id = " << request->request_id << "} "
            << "{result = " << result << "})";
 
-  if (result == content::MEDIA_DEVICE_OK)
+  if (result == content::MEDIA_DEVICE_OK) {
     GetUserMediaRequestSucceeded(request->web_stream, request->request);
-  else
+  } else {
     GetUserMediaRequestFailed(request->request, result, result_name);
 
+    blink::WebVector<blink::WebMediaStreamTrack> tracks;
+    request->web_stream.audioTracks(tracks);
+    for (auto& web_track : tracks) {
+      MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track);
+      if (track)
+        track->Stop();
+    }
+    request->web_stream.videoTracks(tracks);
+    for (auto& web_track : tracks) {
+      MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track);
+      if (track)
+        track->Stop();
+    }
+  }
+
   DeleteUserMediaRequestInfo(request);
 }
 
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
index ac2bbfd2..28ac649 100644
--- a/content/renderer/media/video_capture_impl.cc
+++ b/content/renderer/media/video_capture_impl.cc
@@ -25,8 +25,6 @@
 
 namespace {
 
-const int kUndefinedDeviceId = 0;
-
 // This is called on an unknown thread when the VideoFrame destructor executes.
 // As of this writing, this callback mechanism is the only interface in
 // VideoFrame to provide the final value for |release_sync_point|.
@@ -113,12 +111,16 @@
   DISALLOW_COPY_AND_ASSIGN(ClientBuffer2);
 };
 
+VideoCaptureImpl::ClientInfo::ClientInfo() {}
+VideoCaptureImpl::ClientInfo::~ClientInfo() {}
+
 VideoCaptureImpl::VideoCaptureImpl(
     const media::VideoCaptureSessionId session_id,
     VideoCaptureMessageFilter* filter)
     : message_filter_(filter),
-      device_id_(kUndefinedDeviceId),
+      device_id_(0),
       session_id_(session_id),
+      suspended_(false),
       state_(VIDEO_CAPTURE_STATE_STOPPED),
       weak_factory_(this) {
   DCHECK(filter);
@@ -150,62 +152,79 @@
   Send(suspend ? static_cast<IPC::Message*>(
                      new VideoCaptureHostMsg_Pause(device_id_))
                : static_cast<IPC::Message*>(new VideoCaptureHostMsg_Resume(
-                     device_id_, session_id_, client_params_)));
+                     device_id_, session_id_, params_)));
 }
 
 void VideoCaptureImpl::StartCapture(
+    int client_id,
     const media::VideoCaptureParams& params,
     const VideoCaptureStateUpdateCB& state_update_cb,
     const VideoCaptureDeliverFrameCB& deliver_frame_cb) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  if (state_update_cb.is_null() || deliver_frame_cb.is_null()) {
-    DVLOG(1) << "StartCapture: Passed null callbacks.";
-    return;
-  }
+  ClientInfo client_info;
+  client_info.params = params;
+  client_info.state_update_cb = state_update_cb;
+  client_info.deliver_frame_cb = deliver_frame_cb;
+
   if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
     state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
-    return;
+  } else if (clients_pending_on_filter_.count(client_id) ||
+             clients_pending_on_restart_.count(client_id) ||
+             clients_.count(client_id)) {
+    LOG(FATAL) << "This client has already started.";
+  } else if (!device_id_) {
+    clients_pending_on_filter_[client_id] = client_info;
+  } else {
+    // Note: |state_| might not be started at this point. But we tell
+    // client that we have started.
+    state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED);
+    if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
+      clients_[client_id] = client_info;
+      // TODO(sheu): Allowing resolution change will require that all
+      // outstanding clients of a capture session support resolution change.
+      DCHECK_EQ(params_.resolution_change_policy,
+                params.resolution_change_policy);
+    } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
+      clients_pending_on_restart_[client_id] = client_info;
+      DVLOG(1) << "StartCapture: Got new resolution "
+               << params.requested_format.frame_size.ToString()
+               << " during stopping.";
+    } else {
+      clients_[client_id] = client_info;
+      if (state_ == VIDEO_CAPTURE_STATE_STARTED)
+        return;
+      params_ = params;
+      if (params_.requested_format.frame_rate >
+          media::limits::kMaxFramesPerSecond) {
+        params_.requested_format.frame_rate =
+            media::limits::kMaxFramesPerSecond;
+      }
+      DVLOG(1) << "StartCapture: starting with first resolution "
+               << params_.requested_format.frame_size.ToString();
+      first_frame_timestamp_ = base::TimeTicks();
+      StartCaptureInternal();
+    }
   }
-
-  // Save client info regardless of whether we're actually starting capture
-  // now or not, in case a delegate hasn't yet been added.
-  client_params_ = params;
-  state_update_cb_ = state_update_cb;
-  deliver_frame_cb_ = deliver_frame_cb;
-  client_params_.requested_format.frame_rate =
-      std::min(client_params_.requested_format.frame_rate,
-               static_cast<float>(media::limits::kMaxFramesPerSecond));
-
-  // Postpone starting capture until OnDelegateAdded(). Do this after saving
-  // |client_params_|, etc. as StartCapture will be called with these saved
-  // values as soon as a delegate has been added
-  if (device_id_ == kUndefinedDeviceId) {
-    DVLOG(1) << "StartCapture: Not starting, device_id_ is undefined.";
-    return;
-  }
-
-  // Finally, we can start (assuming we haven't started already).
-  // Notify the client that we have started regardless of |state_|.
-  state_update_cb.Run(VIDEO_CAPTURE_STATE_STARTED);
-  if (state_ == VIDEO_CAPTURE_STATE_STARTED)
-    return;
-  DVLOG(1) << "StartCapture: starting with resolution "
-           << client_params_.requested_format.frame_size.ToString();
-  StartCaptureInternal();
 }
 
-void VideoCaptureImpl::StopCapture() {
+void VideoCaptureImpl::StopCapture(int client_id) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  if (state_ == VIDEO_CAPTURE_STATE_STOPPED || !IsInitialized())
-    return;
+  // A client ID can be in only one client list.
+  // If this ID is in any client list, we can just remove it from
+  // that client list and don't have to run the other following RemoveClient().
+  if (!RemoveClient(client_id, &clients_pending_on_filter_)) {
+    if (!RemoveClient(client_id, &clients_pending_on_restart_)) {
+      RemoveClient(client_id, &clients_);
+    }
+  }
 
-  DVLOG(1) << "StopCapture: Stopping capture.";
-  state_update_cb_.Run(VIDEO_CAPTURE_STATE_STOPPED);
-  StopDevice();
-  client_buffers_.clear();
-  client_buffer2s_.clear();
-  ResetClient();
-  weak_factory_.InvalidateWeakPtrs();
+  if (clients_.empty()) {
+    DVLOG(1) << "StopCapture: No more client, stopping ...";
+    StopDevice();
+    client_buffers_.clear();
+    client_buffer2s_.clear();
+    weak_factory_.InvalidateWeakPtrs();
+  }
 }
 
 void VideoCaptureImpl::GetDeviceSupportedFormats(
@@ -296,7 +315,7 @@
     const gfx::Rect& visible_rect,
     const std::vector<gpu::MailboxHolder>& mailbox_holders) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  if (state_ != VIDEO_CAPTURE_STATE_STARTED) {
+  if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
     Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0, -1.0));
     return;
   }
@@ -372,11 +391,13 @@
   frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
                                   timestamp);
   frame->AddDestructionObserver(
-      base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame,
-                 frame->metadata(), release_sync_point_storage,
-                 buffer_finished_callback));
+      base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(),
+                 release_sync_point_storage, buffer_finished_callback));
+
   frame->metadata()->MergeInternalValuesFrom(metadata);
-  deliver_frame_cb_.Run(frame, timestamp);
+
+  for (const auto& client : clients_)
+    client.second.deliver_frame_cb.Run(frame, timestamp);
 }
 
 void VideoCaptureImpl::OnClientBufferFinished(
@@ -399,33 +420,45 @@
 }
 
 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
-  // TODO(ajose): http://crbug.com/522155 improve this state machine.
   DCHECK(io_task_runner_->BelongsToCurrentThread());
-  state_ = state;
 
-  if (state == VIDEO_CAPTURE_STATE_STOPPED) {
-    DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
-    client_buffers_.clear();
-    client_buffer2s_.clear();
-    weak_factory_.InvalidateWeakPtrs();
-    return;
+  switch (state) {
+    case VIDEO_CAPTURE_STATE_STARTED:
+      // Camera has started in the browser process. Since we have already
+      // told all clients that we have started there's nothing to do.
+      break;
+    case VIDEO_CAPTURE_STATE_STOPPED:
+      state_ = VIDEO_CAPTURE_STATE_STOPPED;
+      DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
+      client_buffers_.clear();
+      client_buffer2s_.clear();
+      weak_factory_.InvalidateWeakPtrs();
+      if (!clients_.empty() || !clients_pending_on_restart_.empty())
+        RestartCapture();
+      break;
+    case VIDEO_CAPTURE_STATE_PAUSED:
+      for (const auto& client : clients_)
+        client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_PAUSED);
+      break;
+    case VIDEO_CAPTURE_STATE_ERROR:
+      DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_;
+      for (const auto& client : clients_)
+        client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR);
+      clients_.clear();
+      state_ = VIDEO_CAPTURE_STATE_ERROR;
+      break;
+    case VIDEO_CAPTURE_STATE_ENDED:
+      DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_;
+      for (const auto& client : clients_) {
+        // We'll only notify the client that the stream has stopped.
+        client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
+      }
+      clients_.clear();
+      state_ = VIDEO_CAPTURE_STATE_ENDED;
+      break;
+    default:
+      break;
   }
-  if (state == VIDEO_CAPTURE_STATE_ERROR) {
-    DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_;
-    if (!state_update_cb_.is_null())
-      state_update_cb_.Run(VIDEO_CAPTURE_STATE_ERROR);
-    ResetClient();
-    return;
-  }
-  if (state == VIDEO_CAPTURE_STATE_ENDED) {
-    DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_;
-    // We'll only notify the client that the stream has stopped.
-    if (!state_update_cb_.is_null())
-      state_update_cb_.Run(VIDEO_CAPTURE_STATE_STOPPED);
-    ResetClient();
-    return;
-  }
-  NOTREACHED();
 }
 
 void VideoCaptureImpl::OnDeviceSupportedFormatsEnumerated(
@@ -449,15 +482,23 @@
   DVLOG(1) << "OnDelegateAdded: device_id " << device_id;
 
   device_id_ = device_id;
-  StartCapture(client_params_, state_update_cb_, deliver_frame_cb_);
+  ClientInfoMap::iterator it = clients_pending_on_filter_.begin();
+  while (it != clients_pending_on_filter_.end()) {
+    const int client_id = it->first;
+    const ClientInfo client_info = it->second;
+    clients_pending_on_filter_.erase(it++);
+    StartCapture(client_id, client_info.params, client_info.state_update_cb,
+                 client_info.deliver_frame_cb);
+  }
 }
 
 void VideoCaptureImpl::StopDevice() {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
   if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
+    state_ = VIDEO_CAPTURE_STATE_STOPPING;
     Send(new VideoCaptureHostMsg_Stop(device_id_));
-    client_params_.requested_format.frame_size.SetSize(0, 0);
+    params_.requested_format.frame_size.SetSize(0, 0);
   }
 }
 
@@ -465,7 +506,20 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED);
 
-  DVLOG(1) << "RestartCapture, restarting capture.";
+  int width = 0;
+  int height = 0;
+  clients_.insert(clients_pending_on_restart_.begin(),
+                  clients_pending_on_restart_.end());
+  clients_pending_on_restart_.clear();
+  for (const auto& client : clients_) {
+    width = std::max(width,
+                     client.second.params.requested_format.frame_size.width());
+    height = std::max(
+        height, client.second.params.requested_format.frame_size.height());
+  }
+  params_.requested_format.frame_size.SetSize(width, height);
+  DVLOG(1) << "RestartCapture, "
+           << params_.requested_format.frame_size.ToString();
   StartCaptureInternal();
 }
 
@@ -473,7 +527,7 @@
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   DCHECK(device_id_);
 
-  Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, client_params_));
+  Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_));
   state_ = VIDEO_CAPTURE_STATE_STARTED;
 }
 
@@ -482,6 +536,19 @@
   message_filter_->Send(message);
 }
 
+bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  bool found = false;
+
+  const ClientInfoMap::iterator it = clients->find(client_id);
+  if (it != clients->end()) {
+    it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED);
+    clients->erase(it);
+    found = true;
+  }
+  return found;
+}
+
 // static
 void VideoCaptureImpl::DidFinishConsumingFrame(
     const media::VideoFrameMetadata* metadata,
@@ -505,18 +572,4 @@
   callback_to_io_thread.Run(release_sync_point, consumer_resource_utilization);
 }
 
-bool VideoCaptureImpl::IsInitialized() const {
-  return !(state_update_cb_.is_null() || deliver_frame_cb_.is_null()) &&
-         device_id_ != kUndefinedDeviceId;
-}
-
-void VideoCaptureImpl::ResetClient() {
-  client_params_ = media::VideoCaptureParams();
-  state_update_cb_.Reset();
-  deliver_frame_cb_.Reset();
-  first_frame_timestamp_ = base::TimeTicks();
-  device_id_ = kUndefinedDeviceId;
-  state_ = VIDEO_CAPTURE_STATE_STOPPED;
-}
-
 }  // namespace content
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h
index b46f4a62..c1d9f22 100644
--- a/content/renderer/media/video_capture_impl.h
+++ b/content/renderer/media/video_capture_impl.h
@@ -24,11 +24,15 @@
 struct MailboxHolder;
 }  // namespace gpu
 
+namespace media {
+class VideoFrame;
+}  // namespace media
+
 namespace content {
 
 // VideoCaptureImpl represents a capture device in renderer process. It provides
-// an interface for a single client to Start/Stop capture. It also communicates
-// to the client when buffer is ready, when state of capture device is changed.
+// interfaces for clients to Start/Stop capture. It also communicates to clients
+// when buffer is ready, state of capture device is changed.
 
 // VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which relays
 // operation of a capture device to the browser process and receives responses
@@ -58,14 +62,17 @@
   void SuspendCapture(bool suspend);
 
   // Start capturing using the provided parameters.
+  // |client_id| must be unique to this object in the render process. It is
+  // used later to stop receiving video frames.
   // |state_update_cb| will be called when state changes.
   // |deliver_frame_cb| will be called when a frame is ready.
-  void StartCapture(const media::VideoCaptureParams& params,
+  void StartCapture(int client_id,
+                    const media::VideoCaptureParams& params,
                     const VideoCaptureStateUpdateCB& state_update_cb,
                     const VideoCaptureDeliverFrameCB& deliver_frame_cb);
 
-  // Stop capturing.
-  void StopCapture();
+  // Stop capturing. |client_id| is the identifier used to call StartCapture.
+  void StopCapture(int client_id);
 
   // Get capturing formats supported by this device.
   // |callback| will be invoked with the results.
@@ -86,6 +93,17 @@
   class ClientBuffer;
   class ClientBuffer2;
 
+  // Contains information for a video capture client. Including parameters
+  // for capturing and callbacks to the client.
+  struct ClientInfo {
+    ClientInfo();
+    ~ClientInfo();
+    media::VideoCaptureParams params;
+    VideoCaptureStateUpdateCB state_update_cb;
+    VideoCaptureDeliverFrameCB deliver_frame_cb;
+  };
+  typedef std::map<int, ClientInfo> ClientInfoMap;
+
   // VideoCaptureMessageFilter::Delegate interface.
   void OnBufferCreated(base::SharedMemoryHandle handle,
                        int length,
@@ -130,6 +148,8 @@
   virtual void Send(IPC::Message* message);
 
   // Helpers.
+  bool RemoveClient(int client_id, ClientInfoMap* clients);
+
   // Called (by an unknown thread) when all consumers are done with a VideoFrame
   // and its ref-count has gone to zero.  This helper function grabs the
   // RESOURCE_UTILIZATION value from the |metadata| and then runs the given
@@ -139,13 +159,6 @@
     uint32* release_sync_point_storage,  // Takes ownership.
     const base::Callback<void(uint32, double)>& callback_to_io_thread);
 
-  // Use |state_update_cb_| and |deliver_frame_cb_| to determine whether
-  // the VideoCaptureImpl has been initialized.
-  bool IsInitialized() const;
-
-  // Reset to a "fresh" client state.
-  void ResetClient();
-
   const scoped_refptr<VideoCaptureMessageFilter> message_filter_;
   int device_id_;
   const int session_id_;
@@ -163,16 +176,18 @@
   typedef std::map<int32, scoped_refptr<ClientBuffer2>> ClientBuffer2Map;
   ClientBuffer2Map client_buffer2s_;
 
-  // Track information for the video capture client, consisting of parameters
-  // for capturing and callbacks to the client.
-  media::VideoCaptureParams client_params_;
-  VideoCaptureStateUpdateCB state_update_cb_;
-  VideoCaptureDeliverFrameCB deliver_frame_cb_;
+  ClientInfoMap clients_;
+  ClientInfoMap clients_pending_on_filter_;
+  ClientInfoMap clients_pending_on_restart_;
+
+  // Member params_ represents the video format requested by the
+  // client to this class via StartCapture().
+  media::VideoCaptureParams params_;
 
   // The device's first captured frame timestamp sent from browser process side.
   base::TimeTicks first_frame_timestamp_;
 
-  // State of this VideoCaptureImpl.
+  bool suspended_;
   VideoCaptureState state_;
 
   // IO message loop reference for checking correct class operation.
diff --git a/content/renderer/media/video_capture_impl_manager.cc b/content/renderer/media/video_capture_impl_manager.cc
index ec102bc3..1ce78d6 100644
--- a/content/renderer/media/video_capture_impl_manager.cc
+++ b/content/renderer/media/video_capture_impl_manager.cc
@@ -36,7 +36,8 @@
 namespace content {
 
 VideoCaptureImplManager::VideoCaptureImplManager()
-    : filter_(new VideoCaptureMessageFilter()),
+    : next_client_id_(0),
+      filter_(new VideoCaptureMessageFilter()),
       render_main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       weak_factory_(this) {}
 
@@ -46,7 +47,7 @@
     return;
   // Forcibly release all video capture resources.
   for (const auto& device : devices_) {
-    VideoCaptureImpl* const impl = device.second;
+    VideoCaptureImpl* const impl = device.second.second;
     ChildProcess::current()->io_task_runner()->PostTask(
         FROM_HERE,
         base::Bind(&VideoCaptureImpl::DeInit, base::Unretained(impl)));
@@ -58,19 +59,18 @@
 base::Closure VideoCaptureImplManager::UseDevice(
     media::VideoCaptureSessionId id) {
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
-  VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
-  DCHECK(it == devices_.end())
-      << "UseDevice: This VideoCaptureSessionId is already in use.";
-  if (it != devices_.end())
-    return base::Closure();
-
-  VideoCaptureImpl* impl = CreateVideoCaptureImplForTesting(id, filter_.get());
-  if (!impl)
-    impl = new VideoCaptureImpl(id, filter_.get());
-  devices_[id] = impl;
-  ChildProcess::current()->io_task_runner()->PostTask(
-      FROM_HERE, base::Bind(&VideoCaptureImpl::Init, base::Unretained(impl)));
-
+  VideoCaptureImpl* impl = NULL;
+  const VideoCaptureDeviceMap::iterator it = devices_.find(id);
+  if (it == devices_.end()) {
+    impl = CreateVideoCaptureImplForTesting(id, filter_.get());
+    if (!impl)
+      impl = new VideoCaptureImpl(id, filter_.get());
+    devices_[id] = std::make_pair(1, impl);
+    ChildProcess::current()->io_task_runner()->PostTask(
+        FROM_HERE, base::Bind(&VideoCaptureImpl::Init, base::Unretained(impl)));
+  } else {
+    ++it->second.first;
+  }
   return base::Bind(&VideoCaptureImplManager::UnrefDevice,
                     weak_factory_.GetWeakPtr(), id);
 }
@@ -83,14 +83,17 @@
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
   DCHECK(it != devices_.end());
-  VideoCaptureImpl* const impl = it->second;
+  VideoCaptureImpl* const impl = it->second.second;
+
+  // This ID is used to identify a client of VideoCaptureImpl.
+  const int client_id = ++next_client_id_;
 
   ChildProcess::current()->io_task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&VideoCaptureImpl::StartCapture, base::Unretained(impl),
-                 params, state_update_cb, deliver_frame_cb));
+                 client_id, params, state_update_cb, deliver_frame_cb));
   return base::Bind(&VideoCaptureImplManager::StopCapture,
-                    weak_factory_.GetWeakPtr(), id);
+                    weak_factory_.GetWeakPtr(), client_id, id);
 }
 
 void VideoCaptureImplManager::GetDeviceSupportedFormats(
@@ -99,7 +102,7 @@
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
   DCHECK(it != devices_.end());
-  VideoCaptureImpl* const impl = it->second;
+  VideoCaptureImpl* const impl = it->second.second;
   ChildProcess::current()->io_task_runner()->PostTask(
       FROM_HERE, base::Bind(&VideoCaptureImpl::GetDeviceSupportedFormats,
                             base::Unretained(impl), callback));
@@ -111,7 +114,7 @@
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
   DCHECK(it != devices_.end());
-  VideoCaptureImpl* const impl = it->second;
+  VideoCaptureImpl* const impl = it->second.second;
   ChildProcess::current()->io_task_runner()->PostTask(
       FROM_HERE, base::Bind(&VideoCaptureImpl::GetDeviceFormatsInUse,
                             base::Unretained(impl), callback));
@@ -124,14 +127,15 @@
   return NULL;
 }
 
-void VideoCaptureImplManager::StopCapture(media::VideoCaptureSessionId id) {
+void VideoCaptureImplManager::StopCapture(int client_id,
+                                          media::VideoCaptureSessionId id) {
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
   DCHECK(it != devices_.end());
-  VideoCaptureImpl* const impl = it->second;
+  VideoCaptureImpl* const impl = it->second.second;
   ChildProcess::current()->io_task_runner()->PostTask(
-      FROM_HERE,
-      base::Bind(&VideoCaptureImpl::StopCapture, base::Unretained(impl)));
+      FROM_HERE, base::Bind(&VideoCaptureImpl::StopCapture,
+                            base::Unretained(impl), client_id));
 }
 
 void VideoCaptureImplManager::UnrefDevice(
@@ -139,19 +143,24 @@
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   const VideoCaptureDeviceMap::iterator it = devices_.find(id);
   DCHECK(it != devices_.end());
-  VideoCaptureImpl* const impl = it->second;
+  VideoCaptureImpl* const impl = it->second.second;
 
   // Unref and destroy on the IO thread if there's no more client.
-  devices_.erase(id);
-  ChildProcess::current()->io_task_runner()->PostTask(
-      FROM_HERE, base::Bind(&VideoCaptureImpl::DeInit, base::Unretained(impl)));
-  ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE, impl);
+  DCHECK(it->second.first);
+  --it->second.first;
+  if (!it->second.first) {
+    devices_.erase(id);
+    ChildProcess::current()->io_task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(&VideoCaptureImpl::DeInit, base::Unretained(impl)));
+    ChildProcess::current()->io_task_runner()->DeleteSoon(FROM_HERE, impl);
+  }
 }
 
 void VideoCaptureImplManager::SuspendDevices(bool suspend) {
   DCHECK(render_main_task_runner_->BelongsToCurrentThread());
   for (const auto& device : devices_) {
-    VideoCaptureImpl* const impl = device.second;
+    VideoCaptureImpl* const impl = device.second.second;
     ChildProcess::current()->io_task_runner()->PostTask(
         FROM_HERE, base::Bind(&VideoCaptureImpl::SuspendCapture,
                               base::Unretained(impl), suspend));
diff --git a/content/renderer/media/video_capture_impl_manager.h b/content/renderer/media/video_capture_impl_manager.h
index e701233f..12b4d05b 100644
--- a/content/renderer/media/video_capture_impl_manager.h
+++ b/content/renderer/media/video_capture_impl_manager.h
@@ -97,16 +97,21 @@
       VideoCaptureMessageFilter* filter) const;
 
  private:
-  void StopCapture(media::VideoCaptureSessionId id);
+  void StopCapture(int client_id, media::VideoCaptureSessionId id);
   void UnrefDevice(media::VideoCaptureSessionId id);
 
+  // The int is used to count clients of the corresponding VideoCaptureImpl.
   // VideoCaptureImpl objects are owned by this object. But they are
   // destroyed on the IO thread. These are raw pointers because we destroy
   // them manually.
-  typedef std::map<media::VideoCaptureSessionId, VideoCaptureImpl*>
-      VideoCaptureDeviceMap;
+  typedef std::map<media::VideoCaptureSessionId,
+                   std::pair<int, VideoCaptureImpl*>> VideoCaptureDeviceMap;
   VideoCaptureDeviceMap devices_;
 
+  // This is an internal ID for identifying clients of VideoCaptureImpl.
+  // The ID is global for the render process.
+  int next_client_id_;
+
   const scoped_refptr<VideoCaptureMessageFilter> filter_;
 
   // Hold a pointer to the Render Main message loop to check we operate on the
diff --git a/content/renderer/media/video_capture_impl_manager_unittest.cc b/content/renderer/media/video_capture_impl_manager_unittest.cc
index 2193d931..bec544a 100644
--- a/content/renderer/media/video_capture_impl_manager_unittest.cc
+++ b/content/renderer/media/video_capture_impl_manager_unittest.cc
@@ -108,11 +108,10 @@
     }
   }
 
-  base::Closure StartCapture(const media::VideoCaptureSessionId id,
-                             const media::VideoCaptureParams& params) {
+  base::Closure StartCapture(const media::VideoCaptureParams& params) {
     return manager_->StartCapture(
-        id, params, base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate,
-                               base::Unretained(this)),
+        0, params, base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate,
+                              base::Unretained(this)),
         base::Bind(&VideoCaptureImplManagerTest::OnFrameReady,
                    base::Unretained(this)));
   }
@@ -127,17 +126,19 @@
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest);
 };
 
-TEST_F(VideoCaptureImplManagerTest, MultipleImpls) {
+// Multiple clients with the same session id. There is only one
+// media::VideoCapture object.
+TEST_F(VideoCaptureImplManagerTest, MultipleClients) {
   base::Closure release_cb1 = manager_->UseDevice(0);
-  base::Closure release_cb2 = manager_->UseDevice(1);
+  base::Closure release_cb2 = manager_->UseDevice(0);
   base::Closure stop_cb1, stop_cb2;
   {
     base::RunLoop run_loop;
     base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
     EXPECT_CALL(*this, OnStarted()).WillOnce(RunClosure(quit_closure));
     EXPECT_CALL(*this, OnStarted()).RetiresOnSaturation();
-    stop_cb1 = StartCapture(0, params_);
-    stop_cb2 = StartCapture(1, params_);
+    stop_cb1 = StartCapture(params_);
+    stop_cb2 = StartCapture(params_);
     FakeChannelSetup();
     run_loop.Run();
   }
@@ -157,17 +158,6 @@
   cleanup_run_loop_.Run();
 }
 
-TEST_F(VideoCaptureImplManagerTest, RefusesMultipleClients) {
-  // TODO(ajose): EXPECT_DEATH is unsafe in a threaded context - what to use
-  // instead?
-  base::Closure release_cb1 = manager_->UseDevice(0);
-// Use DCHECK_IS_ON rather than EXPECT_DEBUG_DEATH or similar to avoid
-// issues on release builds that include DCHECKs.
-#if DCHECK_IS_ON()
-  EXPECT_DEATH(manager_->UseDevice(0), "");
-#endif
-}
-
 TEST_F(VideoCaptureImplManagerTest, NoLeak) {
   manager_->UseDevice(0).Reset();
   manager_.reset();
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc
index 37c2c505..1e9b68f 100644
--- a/content/renderer/media/video_capture_impl_unittest.cc
+++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -19,8 +19,6 @@
 
 namespace content {
 
-// TODO(ajose): http://crbug.com/522145 Improve and expand these tests.
-// In particular, exercise VideoCaptureHostMsg_BufferReady.
 class MockVideoCaptureMessageFilter : public VideoCaptureMessageFilter {
  public:
   MockVideoCaptureMessageFilter() : VideoCaptureMessageFilter() {}
@@ -91,8 +89,8 @@
     void DeviceStartCapture(int device_id,
                             media::VideoCaptureSessionId session_id,
                             const media::VideoCaptureParams& params) {
-      // Do not call OnStateChanged(VIDEO_CAPTURE_STATE_STARTED) here, as this
-      // does not accurately reflect the behavior of the VideoCaptureHost.
+      OnStateChanged(VIDEO_CAPTURE_STATE_STARTED);
+      capture_params_ = params;
     }
 
     void DevicePauseCapture(int device_id) {}
@@ -126,8 +124,13 @@
 
     int received_buffer_count() const { return received_buffer_count_; }
 
+    const media::VideoCaptureParams& capture_params() const {
+      return capture_params_;
+    }
+
    private:
     int received_buffer_count_;
+    media::VideoCaptureParams capture_params_;
   };
 
   VideoCaptureImplTest() {
@@ -164,15 +167,17 @@
     video_capture_impl_->Init();
   }
 
-  void StartCapture(const media::VideoCaptureParams& params) {
+  void StartCapture(int client_id, const media::VideoCaptureParams& params) {
     video_capture_impl_->StartCapture(
-        params, base::Bind(&VideoCaptureImplTest::OnStateUpdate,
-                           base::Unretained(this)),
+        client_id, params, base::Bind(&VideoCaptureImplTest::OnStateUpdate,
+                                      base::Unretained(this)),
         base::Bind(&VideoCaptureImplTest::OnFrameReady,
                    base::Unretained(this)));
   }
 
-  void StopCapture() { video_capture_impl_->StopCapture(); }
+  void StopCapture(int client_id) {
+    video_capture_impl_->StopCapture(client_id);
+  }
 
   void NewBuffer(int buffer_id, const base::SharedMemory& shm) {
     video_capture_impl_->OnBufferCreated(
@@ -225,14 +230,50 @@
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest);
 };
 
-// Execute SetCapture() and StopCapture() for one client.
 TEST_F(VideoCaptureImplTest, Simple) {
+  // Execute SetCapture() and StopCapture() for one client.
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED));
 
   Init();
-  StartCapture(params_small_);
-  StopCapture();
+  StartCapture(0, params_small_);
+  StopCapture(0);
+  DeInit();
+}
+
+TEST_F(VideoCaptureImplTest, TwoClientsInSequence) {
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2);
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2);
+
+  Init();
+  StartCapture(0, params_small_);
+  StopCapture(0);
+  StartCapture(1, params_small_);
+  StopCapture(1);
+  DeInit();
+}
+
+TEST_F(VideoCaptureImplTest, LargeAndSmall) {
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2);
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2);
+
+  Init();
+  StartCapture(0, params_large_);
+  StopCapture(0);
+  StartCapture(1, params_small_);
+  StopCapture(1);
+  DeInit();
+}
+
+TEST_F(VideoCaptureImplTest, SmallAndLarge) {
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2);
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2);
+
+  Init();
+  StartCapture(0, params_small_);
+  StopCapture(0);
+  StartCapture(1, params_large_);
+  StopCapture(1);
   DeInit();
 }
 
@@ -267,6 +308,7 @@
   DeInit();
 }
 
+// NEW TEST
 TEST_P(VideoCaptureImplTest, BufferReceivedWithFormat) {
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(1);
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(1);
@@ -286,10 +328,10 @@
       size, 30, buffer_arg.pixel_format);
 
   Init();
-  StartCapture(params);
+  StartCapture(0, params);
   NewBuffer(0, shm);
   BufferReceived(0, size, buffer_arg.pixel_format, buffer_arg.mailbox_holders);
-  StopCapture();
+  StopCapture(0);
   BufferDestroyed(0);
   DeInit();
 }
@@ -298,6 +340,7 @@
                         VideoCaptureImplTest,
                         testing::ValuesIn(kBufferFormats));
 
+// NEW TEST
 TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop) {
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(1);
   EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(1);
@@ -310,9 +353,9 @@
   ASSERT_TRUE(shm.CreateAndMapAnonymous(i420_frame_size));
 
   Init();
-  StartCapture(params_large_);
+  StartCapture(0, params_large_);
   NewBuffer(0, shm);
-  StopCapture();
+  StopCapture(0);
   BufferReceived(0, params_large_.requested_format.frame_size,
                  media::PIXEL_FORMAT_I420, std::vector<gpu::MailboxHolder>());
   BufferDestroyed(0);
@@ -321,17 +364,31 @@
   EXPECT_EQ(this->video_capture_impl_->received_buffer_count(), 1);
 }
 
+TEST_F(VideoCaptureImplTest, AlreadyStarted) {
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED)).Times(2);
+  EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED)).Times(2);
+
+  Init();
+  StartCapture(0, params_small_);
+  StartCapture(1, params_large_);
+  StopCapture(0);
+  StopCapture(1);
+  DeInit();
+  DCHECK(video_capture_impl_->capture_params().requested_format.frame_size ==
+         params_small_.requested_format.frame_size);
+}
+
 TEST_F(VideoCaptureImplTest, EndedBeforeStop) {
    EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED));
    EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_STOPPED));
 
    Init();
-   StartCapture(params_small_);
+   StartCapture(0, params_small_);
 
    // Receive state change message from browser.
    video_capture_impl_->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ENDED);
 
-   StopCapture();
+   StopCapture(0);
    DeInit();
 }
 
@@ -340,12 +397,12 @@
    EXPECT_CALL(*this, OnStateUpdate(VIDEO_CAPTURE_STATE_ERROR));
 
    Init();
-   StartCapture(params_small_);
+   StartCapture(0, params_small_);
 
    // Receive state change message from browser.
    video_capture_impl_->ReceiveStateChangeMessage(VIDEO_CAPTURE_STATE_ERROR);
 
-   StopCapture();
+   StopCapture(0);
    DeInit();
 }
 
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc
index ab7dd71..b8286e3d 100644
--- a/content/renderer/media/webmediaplayer_ms.cc
+++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -9,6 +9,8 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/command_line.h"
+#include "base/hash.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "cc/blink/context_provider_web_context.h"
@@ -23,15 +25,20 @@
 #include "content/renderer/render_thread_impl.h"
 #include "gpu/blink/webgraphicscontext3d_impl.h"
 #include "media/base/media_log.h"
+#include "media/base/media_switches.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_rotation.h"
 #include "media/base/video_util.h"
 #include "media/blink/webmediaplayer_delegate.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
+#include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/platform/WebSize.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -146,7 +153,21 @@
   // LoadTypeMediaStream) once Blink-side changes land.
   DCHECK_NE(load_type, LoadTypeMediaSource);
 
-  GURL gurl(url);
+  blink::WebMediaStream web_stream(
+      blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
+  blink::WebVector<blink::WebMediaStreamTrack> tracks;
+  web_stream.videoTracks(tracks);
+
+  bool remote = tracks.size() && tracks[0].source().remote();
+
+  bool algorithm_enabled = remote &&
+                           base::CommandLine::ForCurrentProcess()->HasSwitch(
+                               switches::kEnableRTCSmoothnessAlgorithm);
+
+  compositor_->SetAlgorithmEnabled(algorithm_enabled);
+
+  uint32 hash_value = base::Hash(url.string().utf8());
+  compositor_->SetSerial(((hash_value & 0x7FFFFFFF) << 1) | (remote ? 1 : 0));
 
   SetNetworkState(WebMediaPlayer::NetworkStateLoading);
   SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
@@ -183,7 +204,6 @@
 void WebMediaPlayerMS::play() {
   DVLOG(1) << "WebMediaPlayerMS::play";
   DCHECK(thread_checker_.CalledOnValidThread());
-
   if (paused_) {
     if (video_frame_provider_.get())
       video_frame_provider_->Play();
@@ -267,7 +287,7 @@
       return;
     }
   }
-  callback.Run(media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+  callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
 }
 
 void WebMediaPlayerMS::setPreload(WebMediaPlayer::Preload preload) {
@@ -446,6 +466,7 @@
   base::TimeTicks render_time;
   if (!frame->metadata()->GetTimeTicks(
           media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
+    DCHECK(!compositor_->GetAlgorithmEnabled() || !received_first_frame_);
     render_time = base::TimeTicks();
   }
   TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable",
@@ -464,6 +485,14 @@
       video_weblayer_->SetContentsOpaqueIsFixed(true);
       GetClient()->setWebLayer(video_weblayer_.get());
     }
+
+    // REFERENCE_TIME isn't prepared for this stream. VideoRendererAlgorithm
+    // cannot work in this case, force it off.
+    if (render_time.is_null() && compositor_->GetAlgorithmEnabled()) {
+      LOG(DFATAL) << "REFERENCE_TIME is not prepared, so VideoRendererAlgorithm"
+                     " has been turned off.";
+      compositor_->SetAlgorithmEnabled(false);
+    }
   }
 
   bool size_changed = compositor_->GetCurrentSize() != frame->natural_size();
@@ -511,11 +540,13 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner)
     : compositor_task_runner_(compositor_task_runner),
       video_frame_provider_client_(NULL),
+      frame_pool_(nullptr),
       current_frame_used_(false),
       last_deadline_max_(base::TimeTicks()),
+      last_render_length_(base::TimeDelta::FromSecondsD(1.0 / 60.0)),
       total_frame_count_(0),
       dropped_frame_count_(0),
-      paused_(false) {}
+      paused_(true) {}
 
 WebMediaPlayerMS::Compositor::~Compositor() {
   DCHECK(compositor_task_runner_->BelongsToCurrentThread());
@@ -523,26 +554,76 @@
     video_frame_provider_client_->StopUsingProvider();
 }
 
+bool WebMediaPlayerMS::Compositor::GetWallClockTimes(
+    const std::vector<base::TimeDelta>& timestamps,
+    std::vector<base::TimeTicks>* wall_clock_times) {
+  auto iter = timestamps_to_clock_times_.begin();
+  auto end = timestamps_to_clock_times_.end();
+  for (const base::TimeDelta& timestamp : timestamps) {
+    while (iter != end && iter->first < timestamp)
+      ++iter;
+    DCHECK(iter != end && iter->first == timestamp);
+    wall_clock_times->push_back(iter->second);
+  }
+
+  return true;
+}
+
+void WebMediaPlayerMS::Compositor::Render(base::TimeTicks deadline_min,
+                                          base::TimeTicks deadline_max) {
+  last_deadline_max_ = deadline_max;
+  last_render_length_ = deadline_max - deadline_min;
+
+  size_t frames_dropped = 0;
+  scoped_refptr<media::VideoFrame> frame =
+      frame_pool_->Render(deadline_min, deadline_max, &frames_dropped);
+  dropped_frame_count_ += frames_dropped;
+
+  if (frame == current_frame_)
+    return;
+
+  SetCurrentFrame(frame);
+
+  while (!timestamps_to_clock_times_.empty() &&
+         timestamps_to_clock_times_.front().first < frame->timestamp())
+    timestamps_to_clock_times_.pop_front();
+}
+
 void WebMediaPlayerMS::Compositor::EnqueueFrame(
-    scoped_refptr<media::VideoFrame> const& frame) {
+    const scoped_refptr<media::VideoFrame>& frame) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   base::AutoLock auto_lock(current_frame_lock_);
   ++total_frame_count_;
 
-  if (base::TimeTicks::Now() > last_deadline_max_) {
-    // TODO(qiangchen): This shows vsyncs stops rendering frames. A probable
-    // cause is that the tab is not in the front. But we still have to let
-    // old frames go. Call VRA::RemoveExpiredFrames.
-
+  if (!frame_pool_) {
+    SetCurrentFrame(frame);
+    return;
   }
 
-  if (!current_frame_used_) {
-    ++dropped_frame_count_;
-  }
+  // This is a signal frame saying that the stream is stopped.
+  if (current_frame_ && frame->timestamp().is_zero())
+    return;
 
-  // TODO(qiangchen): Instead of using one variable to hold one frame, use
-  // VideoRendererAlgorithm.
-  current_frame_ = frame;
-  current_frame_used_ = false;
+  base::TimeTicks render_time;
+  const base::TimeTicks now = base::TimeTicks::Now();
+  CHECK(frame->metadata()->GetTimeTicks(
+      media::VideoFrameMetadata::REFERENCE_TIME, &render_time));
+  DCHECK(timestamps_to_clock_times_.empty() ||
+         frame->timestamp() > timestamps_to_clock_times_.rbegin()->first);
+  timestamps_to_clock_times_.push_back(
+      std::make_pair(frame->timestamp(), render_time));
+
+  frame_pool_->EnqueueFrame(frame);
+
+  if (now > last_deadline_max_) {
+    // This shows vsyncs stops rendering frames. A probable cause is that the
+    // tab is not in the front. But we still have to let old frames go.
+    base::TimeTicks deadline_max = last_deadline_max_ + last_render_length_;
+    if (deadline_max < now)
+      deadline_max = now;
+
+    Render(deadline_max - last_render_length_, deadline_max);
+  }
 }
 
 bool WebMediaPlayerMS::Compositor::UpdateCurrentFrame(
@@ -553,22 +634,22 @@
   TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
                      "Actual Render Begin", deadline_min.ToInternalValue(),
                      "Actual Render End", deadline_max.ToInternalValue());
-  last_deadline_max_ = deadline_max;
-
-  // TODO(dalecurtis): This should make use of the deadline interval to ensure
-  // the painted frame is correct for the given interval.
-
   if (paused_)
     return false;
 
+  if (frame_pool_)
+    Render(deadline_min, deadline_max);
 
   base::TimeTicks render_time;
   if (!current_frame_->metadata()->GetTimeTicks(
           media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
+    DCHECK(!frame_pool_);
     render_time = base::TimeTicks();
   }
-  TRACE_EVENT_END1("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
-                   "Ideal Render Instant", render_time.ToInternalValue());
+
+  TRACE_EVENT_END2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
+                   "Ideal Render Instant", render_time.ToInternalValue(),
+                   "Serial", serial_);
   return !current_frame_used_;
 }
 
@@ -591,6 +672,14 @@
   current_frame_used_ = true;
 }
 
+void WebMediaPlayerMS::Compositor::SetCurrentFrame(
+    const scoped_refptr<media::VideoFrame>& frame) {
+  if (!current_frame_used_)
+    ++dropped_frame_count_;
+  current_frame_used_ = false;
+  current_frame_ = frame;
+}
+
 void WebMediaPlayerMS::Compositor::SetVideoFrameProviderClient(
     cc::VideoFrameProvider::Client* client) {
   DCHECK(compositor_task_runner_->BelongsToCurrentThread());
@@ -598,13 +687,23 @@
     video_frame_provider_client_->StopUsingProvider();
 
   video_frame_provider_client_ = client;
-  if (video_frame_provider_client_)
+  if (video_frame_provider_client_ && !paused_)
     video_frame_provider_client_->StartRendering();
 }
 
 void WebMediaPlayerMS::Compositor::StartRendering() {
   DCHECK(compositor_task_runner_->BelongsToCurrentThread());
   paused_ = false;
+
+  // It is possible that the video gets paused and then resumed. We need to
+  // reset VideoRendererAlgorithm, otherwise, VideoRendererAlgorithm will think
+  // there is a very long frame in the queue and then make totally wrong
+  // frame selection.
+  if (frame_pool_) {
+    base::AutoLock auto_lock(current_frame_lock_);
+    frame_pool_->Reset();
+  }
+
   if (video_frame_provider_client_)
     video_frame_provider_client_->StartRendering();
 }
@@ -618,6 +717,7 @@
 
 void WebMediaPlayerMS::Compositor::ReplaceCurrentFrameWithACopy(
     media::SkCanvasVideoRenderer* renderer) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   base::AutoLock auto_lock(current_frame_lock_);
   if (!current_frame_.get())
     return;
@@ -649,4 +749,24 @@
 unsigned WebMediaPlayerMS::Compositor::GetDroppedFrameCount() {
   return dropped_frame_count_;
 }
+
+void WebMediaPlayerMS::Compositor::SetAlgorithmEnabled(bool enabled) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (enabled)
+    frame_pool_.reset(new media::VideoRendererAlgorithm(
+        base::Bind(&WebMediaPlayerMS::Compositor::GetWallClockTimes,
+                   base::Unretained(this))));
+  else
+    frame_pool_.reset();
+}
+
+bool WebMediaPlayerMS::Compositor::GetAlgorithmEnabled() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return !!frame_pool_;
+}
+
+void WebMediaPlayerMS::Compositor::SetSerial(uint32 serial) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  serial_ = serial;
+}
 }  // namespace content
diff --git a/content/renderer/media/webmediaplayer_ms.h b/content/renderer/media/webmediaplayer_ms.h
index 4a3689c..4493f07 100644
--- a/content/renderer/media/webmediaplayer_ms.h
+++ b/content/renderer/media/webmediaplayer_ms.h
@@ -13,6 +13,7 @@
 #include "cc/layers/video_frame_provider.h"
 #include "media/blink/skcanvas_video_renderer.h"
 #include "media/blink/webmediaplayer_util.h"
+#include "media/filters/video_renderer_algorithm.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayer.h"
 #include "url/gurl.h"
@@ -155,9 +156,33 @@
     void StopRendering();
     void ReplaceCurrentFrameWithACopy(media::SkCanvasVideoRenderer* renderer);
 
+    // If |enabled| is true, we are going to use VideoRendererAlgorithm for
+    // frame selection. Otherwise, we just submit the most recent frame if asked
+    // by the compositor.
+    void SetAlgorithmEnabled(bool enabled);
+    bool GetAlgorithmEnabled();
+
+    // The serial is used in the trace flags to identify different instances of
+    // WebMediaPlayerMS.
+    void SetSerial(uint32 serial);
+
    private:
+    bool GetWallClockTimes(const std::vector<base::TimeDelta>& timestamps,
+                           std::vector<base::TimeTicks>* wall_clock_times);
+
+    void SetCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
+
+    // For algorithm enabled case only: given the render interval, update
+    // current_frame_ and dropped_frame_count_.
+    void Render(base::TimeTicks deadline_min, base::TimeTicks deadline_max);
+
+    // Used for DCHECKs to ensure method calls executed in the correct thread.
+    base::ThreadChecker thread_checker_;
+
     scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
 
+    uint32 serial_;
+
     // A pointer back to the compositor to inform it about state changes. This
     // is not NULL while the compositor is actively using this webmediaplayer.
     cc::VideoFrameProvider::Client* video_frame_provider_client_;
@@ -169,17 +194,29 @@
     // around all modifications and all reads on the any thread.
     scoped_refptr<media::VideoFrame> current_frame_;
 
+    // |frame_pool_| serves as a frame pool, and provides a frame selection
+    // method which returns the best frame for the render interval.
+    scoped_ptr<media::VideoRendererAlgorithm> frame_pool_;
+
     // |current_frame_used_| is updated on compositor thread only.
     // It's used to track whether |current_frame_| was painted for detecting
     // when to increase |dropped_frame_count_|.
     bool current_frame_used_;
 
+    // Historical data about last rendering. These are for detecting whether
+    // rendering is paused (one reason is that the tab is not in the front), in
+    // which case we need to do background rendering.
     base::TimeTicks last_deadline_max_;
+    base::TimeDelta last_render_length_;
+
     unsigned total_frame_count_;
     unsigned dropped_frame_count_;
 
     bool paused_;
 
+    std::deque<std::pair<base::TimeDelta, base::TimeTicks>>
+        timestamps_to_clock_times_;
+
     // |current_frame_lock_| protects |current_frame_used_| and
     // |current_frame_|.
     base::Lock current_frame_lock_;
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 663f6186..802de16 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -8,11 +8,15 @@
 
 #include "base/command_line.h"
 #include "base/location.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "content/common/media/media_stream_messages.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/renderer/content_renderer_client.h"
 #include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_audio_processor.h"
 #include "content/renderer/media/media_stream_audio_processor_options.h"
@@ -32,12 +36,16 @@
 #include "content/renderer/media/webrtc_local_audio_track.h"
 #include "content/renderer/media/webrtc_logging.h"
 #include "content/renderer/media/webrtc_uma_histograms.h"
+#include "content/renderer/p2p/empty_network_manager.h"
+#include "content/renderer/p2p/filtering_network_manager.h"
 #include "content/renderer/p2p/ipc_network_manager.h"
 #include "content/renderer/p2p/ipc_socket_factory.h"
 #include "content/renderer/p2p/port_allocator.h"
+#include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "jingle/glue/thread_wrapper.h"
+#include "media/base/media_permission.h"
 #include "media/renderers/gpu_video_accelerator_factories.h"
 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
@@ -106,18 +114,24 @@
   }
 }
 
-class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
+class P2PPortAllocatorFactory
+    : public rtc::RefCountedObject<webrtc::PortAllocatorFactoryInterface> {
  public:
-  P2PPortAllocatorFactory(P2PSocketDispatcher* socket_dispatcher,
-                          rtc::NetworkManager* network_manager,
-                          rtc::PacketSocketFactory* socket_factory,
-                          const GURL& origin,
-                          const P2PPortAllocator::Config& config)
-      : socket_dispatcher_(socket_dispatcher),
+  P2PPortAllocatorFactory(
+      scoped_ptr<media::MediaPermission> media_permission,
+      const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+      rtc::NetworkManager* network_manager,
+      rtc::PacketSocketFactory* socket_factory,
+      const P2PPortAllocator::Config& config,
+      const GURL& origin,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+      : media_permission_(media_permission.Pass()),
+        socket_dispatcher_(socket_dispatcher),
         network_manager_(network_manager),
         socket_factory_(socket_factory),
+        config_(config),
         origin_(origin),
-        config_(config) {}
+        task_runner_(task_runner) {}
 
   cricket::PortAllocator* CreatePortAllocator(
       const std::vector<StunConfiguration>& stun_servers,
@@ -139,28 +153,46 @@
       config.relays.push_back(relay_config);
     }
 
-    return new P2PPortAllocator(
-        socket_dispatcher_.get(), network_manager_,
-        socket_factory_, config, origin_);
+    scoped_ptr<rtc::NetworkManager> network_manager;
+    if (config.enable_multiple_routes) {
+      media::MediaPermission* media_permission = media_permission_.get();
+      FilteringNetworkManager* filtering_network_manager =
+          new FilteringNetworkManager(network_manager_, origin_,
+                                      media_permission_.Pass());
+      if (media_permission) {
+        // Start permission check earlier to reduce any impact to call set up
+        // time. It's safe to use Unretained here since both destructor and
+        // Initialize can only be called on the worker thread.
+        task_runner_->PostTask(
+            FROM_HERE, base::Bind(&FilteringNetworkManager::Initialize,
+                                  base::Unretained(filtering_network_manager)));
+      }
+      network_manager.reset(filtering_network_manager);
+    } else {
+      network_manager.reset(new EmptyNetworkManager());
+    }
+
+    return new P2PPortAllocator(socket_dispatcher_, network_manager.Pass(),
+                                socket_factory_, config, origin_, task_runner_);
   }
 
  protected:
   ~P2PPortAllocatorFactory() override {}
 
  private:
+  // Ownership of |media_permission_| will be passed to FilteringNetworkManager
+  // during CreatePortAllocator.
+  scoped_ptr<media::MediaPermission> media_permission_;
+
   scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
-  // |network_manager_| and |socket_factory_| are a weak references, owned by
-  // PeerConnectionDependencyFactory.
   rtc::NetworkManager* network_manager_;
   rtc::PacketSocketFactory* socket_factory_;
-  // The origin URL of the WebFrame that created the
-  // P2PPortAllocatorFactory.
+  P2PPortAllocator::Config config_;
   GURL origin_;
 
-  // Keep track of configuration common to all PortAllocators created by this
-  // factory; additional, per-allocator configuration is passed into
-  // CreatePortAllocator.
-  P2PPortAllocator::Config config_;
+  // This is the worker thread where |media_permission_| and |network_manager_|
+  // live on.
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 };
 
 PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
@@ -403,24 +435,60 @@
           GURL(web_frame->document().firstPartyForCookies())));
 
   // Copy the flag from Preference associated with this WebFrame.
-  P2PPortAllocator::Config pref_config;
+  P2PPortAllocator::Config port_config;
   if (web_frame && web_frame->view()) {
     RenderViewImpl* renderer_view_impl =
         RenderViewImpl::FromWebView(web_frame->view());
     if (renderer_view_impl) {
-      pref_config.enable_multiple_routes =
+      // TODO(guoweis): |enable_multiple_routes| should be renamed to
+      // |request_multiple_routes|. Whether local IP addresses could be
+      // collected depends on if mic/camera permission is granted for this
+      // origin.
+      port_config.enable_multiple_routes =
           renderer_view_impl->renderer_preferences()
               .enable_webrtc_multiple_routes;
-      pref_config.enable_nonproxied_udp =
+      port_config.enable_nonproxied_udp =
           renderer_view_impl->renderer_preferences()
               .enable_webrtc_nonproxied_udp;
     }
   }
 
+  bool enforce_preferences =
+      GetContentClient()->renderer()->ShouldEnforceWebRTCRoutingPreferences();
+
+  // |media_permission| will be called to check mic/camera permission. If at
+  // least one of them is granted, P2PPortAllocator is allowed to gather local
+  // host IP addresses as ICE candidates. |media_permission| could be nullptr,
+  // which means the permission will be granted automatically. This could be the
+  // case when either the experiment is not enabled or the preference is not
+  // enforced.
+  scoped_ptr<media::MediaPermission> media_permission;
+  const std::string group_name =
+      base::FieldTrialList::FindFullName("WebRTC-LocalIPPermissionCheck");
+  if (enforce_preferences &&
+      StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE) &&
+      port_config.enable_multiple_routes) {
+    RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(web_frame);
+    if (render_frame) {
+      media_permission = render_frame->CreateMediaPermissionProxy(
+          chrome_worker_thread_.task_runner());
+      DCHECK(media_permission);
+    }
+  }
+
+  if (!enforce_preferences) {
+    port_config.enable_multiple_routes = true;
+    port_config.enable_nonproxied_udp = true;
+  }
+
+  const GURL& requesting_origin =
+      GURL(web_frame->document().url().spec()).GetOrigin();
+
   scoped_refptr<P2PPortAllocatorFactory> pa_factory =
-      new rtc::RefCountedObject<P2PPortAllocatorFactory>(
-          p2p_socket_dispatcher_.get(), network_manager_, socket_factory_.get(),
-          GURL(web_frame->document().url().spec()).GetOrigin(), pref_config);
+      new P2PPortAllocatorFactory(
+          media_permission.Pass(), p2p_socket_dispatcher_, network_manager_,
+          socket_factory_.get(), port_config, requesting_origin,
+          chrome_worker_thread_.task_runner());
 
   return GetPcFactory()->CreatePeerConnection(config,
                                               constraints,
diff --git a/content/renderer/media/webrtc_logging.cc b/content/renderer/media/webrtc_logging.cc
index 17e5c57..b3d13b9 100644
--- a/content/renderer/media/webrtc_logging.cc
+++ b/content/renderer/media/webrtc_logging.cc
@@ -6,7 +6,7 @@
 
 #include "base/time/time.h"
 #include "content/public/renderer/webrtc_log_message_delegate.h"
-#include "third_party/webrtc/overrides/webrtc/base/logging.h"
+#include "third_party/webrtc_overrides/webrtc/base/logging.h"
 
 namespace content {
 
diff --git a/content/renderer/p2p/empty_network_manager.cc b/content/renderer/p2p/empty_network_manager.cc
new file mode 100644
index 0000000..445f8777
--- /dev/null
+++ b/content/renderer/p2p/empty_network_manager.cc
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. 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/p2p/empty_network_manager.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/renderer/p2p/network_manager_uma.h"
+
+namespace content {
+
+EmptyNetworkManager::EmptyNetworkManager() : weak_ptr_factory_(this) {
+  thread_checker_.DetachFromThread();
+  set_enumeration_permission(ENUMERATION_BLOCKED);
+}
+
+EmptyNetworkManager::~EmptyNetworkManager() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void EmptyNetworkManager::StartUpdating() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  FireEvent();
+  updating_started_ = true;
+}
+
+void EmptyNetworkManager::StopUpdating() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void EmptyNetworkManager::GetNetworks(NetworkList* networks) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  networks->clear();
+}
+
+void EmptyNetworkManager::FireEvent() {
+  if (!updating_started_)
+    ReportIPPermissionStatus(PERMISSION_NOT_REQUESTED);
+
+  // Post a task to avoid reentrancy.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&EmptyNetworkManager::SendNetworksChangedSignal,
+                            weak_ptr_factory_.GetWeakPtr()));
+}
+
+void EmptyNetworkManager::SendNetworksChangedSignal() {
+  SignalNetworksChanged();
+}
+
+}  // namespace content
diff --git a/content/renderer/p2p/empty_network_manager.h b/content/renderer/p2p/empty_network_manager.h
new file mode 100644
index 0000000..4827d2ba
--- /dev/null
+++ b/content/renderer/p2p/empty_network_manager.h
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. 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_P2P_EMPTY_NETWORK_MANAGER_H_
+#define CONTENT_RENDERER_P2P_EMPTY_NETWORK_MANAGER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "third_party/webrtc/base/network.h"
+
+namespace content {
+
+// A NetworkManager implementation which handles the case where local address
+// enumeration is not requested and just returns empty network lists. This class
+// is not thread safe and should only be used by WebRTC's worker thread.
+class EmptyNetworkManager : public rtc::NetworkManagerBase {
+ public:
+  // This class is created by WebRTC's signaling thread but used by WebRTC's
+  // worker thread |task_runner|.
+  CONTENT_EXPORT EmptyNetworkManager();
+  CONTENT_EXPORT ~EmptyNetworkManager() override;
+
+  // rtc::NetworkManager:
+  void StartUpdating() override;
+  void StopUpdating() override;
+  void GetNetworks(NetworkList* networks) const override;
+
+ private:
+  void FireEvent();
+  void SendNetworksChangedSignal();
+
+  base::ThreadChecker thread_checker_;
+
+  // Track whether StartUpdating() has been called before.
+  bool updating_started_ = false;
+
+  base::WeakPtrFactory<EmptyNetworkManager> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmptyNetworkManager);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_P2P_EMPTY_NETWORK_MANAGER_H_
diff --git a/content/renderer/p2p/filtering_network_manager.cc b/content/renderer/p2p/filtering_network_manager.cc
new file mode 100644
index 0000000..64eafcb7
--- /dev/null
+++ b/content/renderer/p2p/filtering_network_manager.cc
@@ -0,0 +1,172 @@
+// Copyright 2015 The Chromium Authors. 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/p2p/filtering_network_manager.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/thread_task_runner_handle.h"
+#include "media/base/media_permission.h"
+
+namespace content {
+
+FilteringNetworkManager::FilteringNetworkManager(
+    rtc::NetworkManager* network_manager,
+    const GURL& requesting_origin,
+    scoped_ptr<media::MediaPermission> media_permission)
+    : network_manager_(network_manager),
+      media_permission_(media_permission.Pass()),
+      requesting_origin_(requesting_origin),
+      weak_ptr_factory_(this) {
+  thread_checker_.DetachFromThread();
+  set_enumeration_permission(ENUMERATION_BLOCKED);
+
+  // If the feature is not enabled, just return ALLOWED as it's requested.
+  if (!media_permission_) {
+    initialized_ = true;
+    set_enumeration_permission(ENUMERATION_ALLOWED);
+    return;
+  }
+}
+
+void FilteringNetworkManager::Initialize() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!initialized_);
+
+  initialized_ = true;
+  pending_permission_checks_ = 2;
+
+  // Request for media permission asynchronously.
+  media_permission_->HasPermission(
+      media::MediaPermission::AUDIO_CAPTURE, requesting_origin_,
+      base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+  media_permission_->HasPermission(
+      media::MediaPermission::VIDEO_CAPTURE, requesting_origin_,
+      base::Bind(&FilteringNetworkManager::OnPermissionStatus, GetWeakPtr()));
+}
+
+FilteringNetworkManager::~FilteringNetworkManager() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  // This helps to catch the case if permission never comes back.
+  if (!start_updating_time_.is_null())
+    ReportMetrics(false);
+}
+
+base::WeakPtr<FilteringNetworkManager> FilteringNetworkManager::GetWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+void FilteringNetworkManager::StartUpdating() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(initialized_);
+
+  if (start_updating_time_.is_null()) {
+    start_updating_time_ = base::TimeTicks::Now();
+    network_manager_->SignalNetworksChanged.connect(
+        this, &FilteringNetworkManager::OnNetworksChanged);
+  }
+
+  network_manager_->StartUpdating();
+  ++start_count_;
+
+  if (sent_first_update_ || should_fire_event())
+    FireEventIfStarted();
+}
+
+void FilteringNetworkManager::StopUpdating() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  network_manager_->StopUpdating();
+  DCHECK_GT(start_count_, 0);
+  --start_count_;
+}
+
+void FilteringNetworkManager::GetNetworks(NetworkList* networks) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  networks->clear();
+
+  if (enumeration_permission() == ENUMERATION_ALLOWED)
+    network_manager_->GetNetworks(networks);
+}
+
+void FilteringNetworkManager::OnPermissionStatus(bool granted) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_GT(pending_permission_checks_, 0);
+
+  --pending_permission_checks_;
+
+  if (granted)
+    set_enumeration_permission(ENUMERATION_ALLOWED);
+
+  if (should_fire_event())
+    FireEventIfStarted();
+}
+
+void FilteringNetworkManager::OnNetworksChanged() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  received_networks_changed_since_last_firing_ = true;
+  if (enumeration_permission() == ENUMERATION_ALLOWED)
+    FireEventIfStarted();
+}
+
+void FilteringNetworkManager::ReportMetrics(bool report_start_latency) {
+  if (sent_first_update_)
+    return;
+
+  if (report_start_latency)
+    ReportTimeToUpdateNetworkList(base::TimeTicks::Now() -
+                                  start_updating_time_);
+
+  ReportIPPermissionStatus(GetIPPermissionStatus());
+}
+
+IPPermissionStatus FilteringNetworkManager::GetIPPermissionStatus() const {
+  if (enumeration_permission() == ENUMERATION_ALLOWED) {
+    return media_permission_ ? PERMISSION_GRANTED_WITH_CHECKING
+                             : PERMISSION_GRANTED_WITHOUT_CHECKING;
+  }
+
+  if (!pending_permission_checks_ &&
+      enumeration_permission() == ENUMERATION_BLOCKED) {
+    return PERMISSION_DENIED;
+  }
+
+  return PERMISSION_UNKNOWN;
+}
+
+bool FilteringNetworkManager::should_fire_event() const {
+  // We should signal network changes when the permisison is denied and we have
+  // never fired any SignalNetworksChanged. Or 2) permission is granted and we
+  // have received new SignalNetworksChanged from |network_manager_| yet to
+  // be broadcast.
+  bool permission_blocked_but_never_fired =
+      (GetIPPermissionStatus() == PERMISSION_DENIED) && !sent_first_update_;
+  bool permission_allowed_pending_networks_update =
+      enumeration_permission() == ENUMERATION_ALLOWED &&
+      received_networks_changed_since_last_firing_;
+
+  return permission_blocked_but_never_fired ||
+         permission_allowed_pending_networks_update;
+}
+
+void FilteringNetworkManager::FireEventIfStarted() {
+  if (!start_count_)
+    return;
+
+  ReportMetrics(true);
+
+  // Post a task to avoid reentrancy.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&FilteringNetworkManager::SendNetworksChangedSignal,
+                            GetWeakPtr()));
+
+  sent_first_update_ = true;
+  received_networks_changed_since_last_firing_ = false;
+}
+
+void FilteringNetworkManager::SendNetworksChangedSignal() {
+  SignalNetworksChanged();
+}
+
+}  // namespace content
diff --git a/content/renderer/p2p/filtering_network_manager.h b/content/renderer/p2p/filtering_network_manager.h
new file mode 100644
index 0000000..14392f7
--- /dev/null
+++ b/content/renderer/p2p/filtering_network_manager.h
@@ -0,0 +1,126 @@
+// Copyright 2015 The Chromium Authors. 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_P2P_FILTERING_NETWORK_MANAGER_H_
+#define CONTENT_RENDERER_P2P_FILTERING_NETWORK_MANAGER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "content/renderer/p2p/network_manager_uma.h"
+#include "third_party/webrtc/base/network.h"
+#include "third_party/webrtc/base/sigslot.h"
+#include "url/gurl.h"
+
+namespace media {
+class MediaPermission;
+}  // namespace media
+
+namespace content {
+
+// FilteringNetworkManager exposes rtc::NetworkManager to
+// PeerConnectionDependencyFactory and wraps the IpcNetworkManager. It only
+// handles the case wher emultiple_routes is requested. It checks at least one
+// of mic/camera permissions is granted before allowing WebRTC to use the local
+// IP addresses as ICE candidates. The class handles asynchronous signals like
+// SignalNetworksChanged from IpcNetworkManager and permission status from
+// MediaPermission before it signals WebRTC that the network information is
+// ready. It is designed to fire the network change event at the earliest time
+// to reduce any extra call setup delay. This class is not thread safe and
+// should only be used by WebRTC's worker thread. It inherits from
+// rtc::NetworkManagerBase to have the same implementation of
+// GetAnyAddressNetworks(). We can't mark the whole class CONTENT_EXPORT as it
+// requires all super classes to be CONTENT_EXPORT as well.
+class FilteringNetworkManager : public rtc::NetworkManagerBase,
+                                public sigslot::has_slots<> {
+ public:
+  // This class is created by WebRTC's signaling thread but used by WebRTC's
+  // worker thread |task_runner|.
+  CONTENT_EXPORT FilteringNetworkManager(
+      rtc::NetworkManager* network_manager,
+      const GURL& requesting_origin,
+      scoped_ptr<media::MediaPermission> media_permission);
+
+  CONTENT_EXPORT ~FilteringNetworkManager() override;
+
+  // Check mic/camera permission. This is called by P2PPortAllocatorFactory.
+  CONTENT_EXPORT void Initialize();
+
+  // rtc::NetworkManager:
+  void StartUpdating() override;
+  void StopUpdating() override;
+  void GetNetworks(NetworkList* networks) const override;
+
+ private:
+  // Receive callback from MediaPermission when the permission status is
+  // available.
+  void OnPermissionStatus(bool granted);
+
+  base::WeakPtr<FilteringNetworkManager> GetWeakPtr();
+
+  // Receive callback from the wrapped IpcNetworkManager when the underneath
+  // network list is changed.
+  void OnNetworksChanged();
+
+  // Reporting the IPPermissionStatus and how long it takes to send
+  // SignalNetworksChanged. |report_start_latency| is false when called by the
+  // destructor to report no networks changed signal is ever fired and could
+  // potentially be a bug.
+  void ReportMetrics(bool report_start_latency);
+
+  // A tri-state permission checking status. It starts with UNKNOWN and will
+  // change to GRANTED if one of permissions is granted. Otherwise, DENIED will
+  // be returned.
+  IPPermissionStatus GetIPPermissionStatus() const;
+
+  // Indicate that we have new information worth to signal. This could mean that
+  // all pending checks denied and we have never signaled, or enumeration is
+  // allowed and we have new updates now.
+  bool should_fire_event() const;
+
+  void FireEventIfStarted();
+
+  void SendNetworksChangedSignal();
+
+  // |network_manager_| is just a reference, owned by
+  // PeerConnectionDependencyFactory.
+  rtc::NetworkManager* network_manager_;
+
+  // The class is created by the signaling thread but used by the worker thread.
+  base::ThreadChecker thread_checker_;
+
+  scoped_ptr<media::MediaPermission> media_permission_;
+
+  int pending_permission_checks_ = 0;
+
+  // Whether we have fired the first SignalNetworksChanged.
+  bool sent_first_update_ = false;
+
+  // Whether we have received new SignalNetworksChanged from |network_manager_|
+  // since last firing.
+  bool received_networks_changed_since_last_firing_ = false;
+
+  // SignalNetworksChanged will only be fired if there is any outstanding
+  // StartUpdating.
+  int start_count_ = 0;
+
+  // Track whether Initialize has been called before StartUpdating.
+  bool initialized_ = false;
+
+  // Track how long it takes for client to receive SignalNetworksChanged. This
+  // helps to identify if the signal is delayed by permission check and increase
+  // the setup time.
+  base::TimeTicks start_updating_time_;
+
+  GURL requesting_origin_;
+
+  base::WeakPtrFactory<FilteringNetworkManager> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FilteringNetworkManager);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_P2P_FILTERING_NETWORK_MANAGER_H_
diff --git a/content/renderer/p2p/filtering_network_manager_unittest.cc b/content/renderer/p2p/filtering_network_manager_unittest.cc
new file mode 100644
index 0000000..23e133f
--- /dev/null
+++ b/content/renderer/p2p/filtering_network_manager_unittest.cc
@@ -0,0 +1,357 @@
+// Copyright 2015 The Chromium Authors. 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/p2p/filtering_network_manager.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/renderer/p2p/empty_network_manager.h"
+#include "media/base/media_permission.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/base/ipaddress.h"
+
+using NetworkList = rtc::NetworkManager::NetworkList;
+
+namespace {
+
+enum EventType {
+  MIC_DENIED,      // Receive mic permission denied.
+  MIC_GRANTED,     // Receive mic permission granted.
+  CAMERA_DENIED,   // Receive camera permission denied.
+  CAMERA_GRANTED,  // Receive camera permission granted.
+  START_UPDATING,  // Client calls StartUpdating() on FilteringNetworkManager.
+  STOP_UPDATING,   // Client calls StopUpdating() on FilteringNetworkManager.
+  MOCK_NETWORKS_CHANGED,  // MockNetworkManager has signaled networks changed
+                          // event.
+};
+
+enum ResultType {
+  NO_SIGNAL,                   // Do not expect SignalNetworksChanged fired.
+  SIGNAL_ENUMERATION_BLOCKED,  // Expect SignalNetworksChanged and
+                               // ENUMERATION_BLOCKED.
+  SIGNAL_ENUMERATION_ALLOWED,  // Expect SignalNetworksChanged and
+                               // ENUMERATION_ALLOWED.
+};
+
+struct TestEntry {
+  EventType event;
+  ResultType expected_result;
+};
+
+class MockNetworkManager : public rtc::NetworkManager {
+ public:
+  MockNetworkManager() {
+    network_.reset(new rtc::Network("test_eth0", "Test Network Adapter 1",
+                                    rtc::IPAddress(0x12345600U), 24,
+                                    rtc::ADAPTER_TYPE_ETHERNET));
+  }
+  // Mimic the current behavior that once the first signal is sent, any future
+  // StartUpdating() will trigger another one.
+  void StartUpdating() override {
+    if (sent_first_update_)
+      SignalNetworksChanged();
+  }
+  void StopUpdating() override {}
+  void GetNetworks(NetworkList* networks) const override {
+    networks->push_back(network_.get());
+  }
+
+  void SendNetworksChanged() {
+    sent_first_update_ = true;
+    SignalNetworksChanged();
+  }
+
+ private:
+  bool sent_first_update_ = false;
+  scoped_ptr<rtc::Network> network_;
+};
+
+class MockMediaPermission : public media::MediaPermission {
+ public:
+  MockMediaPermission() {}
+  ~MockMediaPermission() override {}
+
+  void RequestPermission(
+      Type type,
+      const GURL& security_origin,
+      const PermissionStatusCB& permission_status_cb) override {
+    NOTIMPLEMENTED();
+  }
+
+  void HasPermission(Type type,
+                     const GURL& security_origin,
+                     const PermissionStatusCB& permission_status_cb) override {
+    if (type == MediaPermission::AUDIO_CAPTURE) {
+      DCHECK(mic_callback_.is_null());
+      mic_callback_ = permission_status_cb;
+    } else {
+      DCHECK(type == MediaPermission::VIDEO_CAPTURE);
+      DCHECK(camera_callback_.is_null());
+      camera_callback_ = permission_status_cb;
+    }
+  }
+
+  void SetMicPermission(bool granted) {
+    if (mic_callback_.is_null())
+      return;
+
+    mic_callback_.Run(granted);
+    mic_callback_ = PermissionStatusCB();
+  }
+
+  void SetCameraPermission(bool granted) {
+    if (camera_callback_.is_null())
+      return;
+
+    camera_callback_.Run(granted);
+    camera_callback_ = PermissionStatusCB();
+  }
+
+ private:
+  PermissionStatusCB mic_callback_;
+  PermissionStatusCB camera_callback_;
+};
+
+}  // namespace
+
+namespace content {
+
+class FilteringNetworkManagerTest : public testing::Test,
+                                    public sigslot::has_slots<> {
+ public:
+  FilteringNetworkManagerTest()
+      : task_runner_(new base::TestSimpleTaskRunner()),
+        task_runner_handle_(task_runner_) {}
+  void SetupNetworkManager(bool multiple_routes_requested) {
+    mock_network_manager_.reset(new MockNetworkManager());
+
+    scoped_ptr<MockMediaPermission> media_permission(new MockMediaPermission());
+    media_permission_ = media_permission.get();
+    if (multiple_routes_requested) {
+      FilteringNetworkManager* filtering_network_manager =
+          new FilteringNetworkManager(mock_network_manager_.get(), GURL(),
+                                      media_permission.Pass());
+      filtering_network_manager->Initialize();
+      network_manager_.reset(filtering_network_manager);
+    } else {
+      network_manager_.reset(new EmptyNetworkManager());
+    }
+    network_manager_->SignalNetworksChanged.connect(
+        this, &FilteringNetworkManagerTest::OnNetworksChanged);
+  }
+
+  void RunTests(TestEntry* tests, size_t size) {
+    for (size_t i = 0; i < size; ++i) {
+      EXPECT_EQ(tests[i].expected_result, ProcessEvent(tests[i].event))
+          << " in step: " << i;
+    }
+  }
+
+  ResultType ProcessEvent(EventType event) {
+    clear_callback_called();
+    switch (event) {
+      case MIC_DENIED:
+      case MIC_GRANTED:
+        media_permission_->SetMicPermission(event == MIC_GRANTED);
+        break;
+      case CAMERA_DENIED:
+      case CAMERA_GRANTED:
+        media_permission_->SetCameraPermission(event == CAMERA_GRANTED);
+        break;
+      case START_UPDATING:
+        network_manager_->StartUpdating();
+        break;
+      case STOP_UPDATING:
+        network_manager_->StopUpdating();
+        break;
+      case MOCK_NETWORKS_CHANGED:
+        mock_network_manager_->SendNetworksChanged();
+        break;
+    }
+
+    task_runner_->RunUntilIdle();
+
+    if (!callback_called_)
+      return NO_SIGNAL;
+
+    if (network_manager_->enumeration_permission() ==
+        rtc::NetworkManager::ENUMERATION_BLOCKED) {
+      EXPECT_EQ(0u, GetP2PNetworkList().size());
+      return SIGNAL_ENUMERATION_BLOCKED;
+    }
+    EXPECT_EQ(1u, GetP2PNetworkList().size());
+    return SIGNAL_ENUMERATION_ALLOWED;
+  }
+
+ protected:
+  const NetworkList& GetP2PNetworkList() {
+    network_list_.clear();
+    network_manager_->GetNetworks(&network_list_);
+    return network_list_;
+  }
+
+  void OnNetworksChanged() { callback_called_ = true; }
+  void clear_callback_called() { callback_called_ = false; }
+
+  bool callback_called_ = false;
+  scoped_ptr<rtc::NetworkManager> network_manager_;
+  scoped_ptr<MockNetworkManager> mock_network_manager_;
+
+  // Raw pointer to MockMediaPermission. It's owned by FilteringNetworkManager.
+  MockMediaPermission* media_permission_ = nullptr;
+
+  NetworkList network_list_;
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle task_runner_handle_;
+};
+
+// Test that when multiple routes is not requested, SignalNetworksChanged is
+// fired right after the StartUpdating().
+TEST_F(FilteringNetworkManagerTest, MultipleRoutesNotRequested) {
+  SetupNetworkManager(false);
+  TestEntry tests[] = {
+      // Underneath network manager signals, no callback as StartUpdating() is
+      // not called.
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      // StartUpdating() is called, should receive callback as the multiple
+      // routes is not requested.
+      {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+      // Further network signal shouldn't trigger callback in
+      // ENUMERATION_BLOCKED mode.
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      // New StartUpdating() should trigger callback.
+      {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+// Test that multiple routes request is blocked and signaled right after
+// StartUpdating() since mic/camera permissions are denied.
+TEST_F(FilteringNetworkManagerTest, BlockMultipleRoutesByStartUpdating) {
+  SetupNetworkManager(true);
+
+  TestEntry tests[] = {
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      // Both mic and camera are denied.
+      {MIC_DENIED, NO_SIGNAL},
+      {CAMERA_DENIED, NO_SIGNAL},
+      // Once StartUpdating() is called, signal network changed event with
+      // ENUMERATION_BLOCKED.
+      {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+      // Further network signal shouldn't trigger callback.
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      // New StartUpdating() should trigger callback.
+      {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+// Test that multiple routes request is blocked and signaled right after
+// last pending permission check is denied since StartUpdating() has been called
+// previously.
+TEST_F(FilteringNetworkManagerTest, BlockMultipleRoutesByPermissionsDenied) {
+  SetupNetworkManager(true);
+
+  TestEntry tests[] = {
+      {START_UPDATING, NO_SIGNAL},
+      {MIC_DENIED, NO_SIGNAL},
+      // Once camera is denied, no need to wait for networkchanged event from
+      // network_manager_.
+      {CAMERA_DENIED, SIGNAL_ENUMERATION_BLOCKED},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// a pending permission check is granted since StartUpdating() has been called
+// previously.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByPermissionsGranted) {
+  SetupNetworkManager(true);
+
+  TestEntry tests[] = {
+      {START_UPDATING, NO_SIGNAL},
+      {MIC_DENIED, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      // Once one media type is granted, signal networkschanged with
+      // ENUMERATION_ALLOWED.
+      {CAMERA_GRANTED, SIGNAL_ENUMERATION_ALLOWED},
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      // If there is any outstanding StartUpdating(), new event from underneath
+      // network manger should trigger SignalNetworksChanged.
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      // No outstanding StartUpdating(), no more signal.
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// StartUpdating() since there is at least one media permission granted.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByStartUpdating) {
+  SetupNetworkManager(true);
+
+  TestEntry tests[] = {
+      {MIC_DENIED, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+      {CAMERA_GRANTED, NO_SIGNAL},
+      // StartUpdating() should trigger the event since at least one media is
+      // granted and network information is populated.
+      {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// underneath NetworkManager's SignalNetworksChanged() as at least one
+// permission is granted and StartUpdating() has been called.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByNetworksChanged) {
+  SetupNetworkManager(true);
+
+  TestEntry tests[] = {
+      {START_UPDATING, NO_SIGNAL},
+      {CAMERA_GRANTED, NO_SIGNAL},
+      // Underneath network manager's signal networks changed should trigger
+      // SignalNetworksChanged with ENUMERATION_ALLOWED.
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {MIC_DENIED, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, SIGNAL_ENUMERATION_ALLOWED},
+      {STOP_UPDATING, NO_SIGNAL},
+      {MOCK_NETWORKS_CHANGED, NO_SIGNAL},
+  };
+
+  RunTests(tests, arraysize(tests));
+}
+
+}  // namespace content
diff --git a/content/renderer/p2p/network_manager_uma.cc b/content/renderer/p2p/network_manager_uma.cc
new file mode 100644
index 0000000..40f91a21
--- /dev/null
+++ b/content/renderer/p2p/network_manager_uma.cc
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. 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/p2p/network_manager_uma.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+
+namespace content {
+
+void ReportTimeToUpdateNetworkList(const base::TimeDelta& ticks) {
+  UMA_HISTOGRAM_TIMES("WebRTC.PeerConnection.TimeToNetworkUpdated", ticks);
+}
+
+void ReportIPPermissionStatus(IPPermissionStatus status) {
+  UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPPermissionStatus", status,
+                            PERMISSION_MAX);
+}
+
+}  // namespace content
diff --git a/content/renderer/p2p/network_manager_uma.h b/content/renderer/p2p/network_manager_uma.h
new file mode 100644
index 0000000..370acf9
--- /dev/null
+++ b/content/renderer/p2p/network_manager_uma.h
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. 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_P2P_NETWORK_MANAGER_UMA_H_
+#define CONTENT_RENDERER_P2P_NETWORK_MANAGER_UMA_H_
+
+namespace base {
+class TimeDelta;
+}  // namespace
+
+namespace content {
+
+// Need to be kept the same order as in histograms.xml
+enum IPPermissionStatus {
+  PERMISSION_UNKNOWN,  // Requested but have never fired SignalNetworksChanged.
+  PERMISSION_NOT_REQUESTED,             // Multiple routes is not requested.
+  PERMISSION_DENIED,                    // Requested but denied.
+  PERMISSION_GRANTED_WITH_CHECKING,     // Requested and granted after checking
+                                        // mic/camera permission.
+  PERMISSION_GRANTED_WITHOUT_CHECKING,  // Requested and granted without
+                                        // checking mic/camera permission.
+  PERMISSION_MAX,
+};
+
+void ReportIPPermissionStatus(IPPermissionStatus status);
+void ReportTimeToUpdateNetworkList(const base::TimeDelta& ticks);
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_P2P_NETWORK_MANAGER_UMA_H_
diff --git a/content/renderer/p2p/port_allocator.cc b/content/renderer/p2p/port_allocator.cc
index 73112dd..56876ba 100644
--- a/content/renderer/p2p/port_allocator.cc
+++ b/content/renderer/p2p/port_allocator.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "content/public/common/content_switches.h"
+#include "content/renderer/p2p/socket_dispatcher.h"
 
 namespace content {
 
@@ -23,16 +24,18 @@
 }
 
 P2PPortAllocator::P2PPortAllocator(
-    P2PSocketDispatcher* socket_dispatcher,
-    rtc::NetworkManager* network_manager,
+    const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+    scoped_ptr<rtc::NetworkManager> network_manager,
     rtc::PacketSocketFactory* socket_factory,
     const Config& config,
-    const GURL& origin)
-    : cricket::BasicPortAllocator(network_manager, socket_factory),
+    const GURL& origin,
+    const scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+    : cricket::BasicPortAllocator(network_manager.get(), socket_factory),
+      network_manager_(network_manager.Pass()),
       socket_dispatcher_(socket_dispatcher),
       config_(config),
-      origin_(origin)
-  {
+      origin_(origin),
+      network_manager_task_runner_(task_runner) {
   uint32 flags = 0;
   if (!config_.enable_multiple_routes)
     flags |= cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION;
@@ -47,11 +50,17 @@
   bool enable_webrtc_stun_origin =
       cmd_line->HasSwitch(switches::kEnableWebRtcStunOrigin);
   if (enable_webrtc_stun_origin) {
-    set_origin(origin.spec());
+    set_origin(origin_.spec());
   }
 }
 
+// TODO(guoweis): P2PPortAllocator is also deleted in the wrong thread
+// here. It's created in signaling thread, and held by webrtc::PeerConnection,
+// only used on worker thread. The destructor is invoked on signaling thread
+// again. crbug.com/535761. DeleteSoon can be removed once the bug is fixed.
 P2PPortAllocator::~P2PPortAllocator() {
+  network_manager_task_runner_->DeleteSoon(FROM_HERE,
+                                           network_manager_.release());
 }
 
 cricket::PortAllocatorSession* P2PPortAllocator::CreateSessionInternal(
diff --git a/content/renderer/p2p/port_allocator.h b/content/renderer/p2p/port_allocator.h
index a789e7a..28502f0f 100644
--- a/content/renderer/p2p/port_allocator.h
+++ b/content/renderer/p2p/port_allocator.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
 #define CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
 
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
 #include "third_party/webrtc/p2p/client/basicportallocator.h"
 #include "url/gurl.h"
 
@@ -44,11 +46,13 @@
     bool enable_multiple_routes = true;
   };
 
-  P2PPortAllocator(P2PSocketDispatcher* socket_dispatcher,
-                   rtc::NetworkManager* network_manager,
-                   rtc::PacketSocketFactory* socket_factory,
-                   const Config& config,
-                   const GURL& origin);
+  P2PPortAllocator(
+      const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+      scoped_ptr<rtc::NetworkManager> network_manager,
+      rtc::PacketSocketFactory* socket_factory,
+      const Config& config,
+      const GURL& origin,
+      const scoped_refptr<base::SingleThreadTaskRunner> task_runner);
   ~P2PPortAllocator() override;
 
   cricket::PortAllocatorSession* CreateSessionInternal(
@@ -59,11 +63,16 @@
 
  private:
   friend class P2PPortAllocatorSession;
-
-  P2PSocketDispatcher* socket_dispatcher_;
+  scoped_ptr<rtc::NetworkManager> network_manager_;
+  scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
   Config config_;
   GURL origin_;
 
+  // This is the thread |network_manager_| is associated with and must be used
+  // to delete |network_manager_|.
+  const scoped_refptr<base::SingleThreadTaskRunner>
+      network_manager_task_runner_;
+
   DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
 };
 
diff --git a/content/renderer/pepper/host_dispatcher_wrapper.cc b/content/renderer/pepper/host_dispatcher_wrapper.cc
index 1bee361..ba709fe 100644
--- a/content/renderer/pepper/host_dispatcher_wrapper.cc
+++ b/content/renderer/pepper/host_dispatcher_wrapper.cc
@@ -94,7 +94,7 @@
         plugin_instance->GetContainer()
             ->element()
             .document()
-            .isPrivilegedContext(unused) &&
+            .isSecureContext(unused) &&
         content::IsOriginSecure(plugin_instance->GetPluginURL());
     render_frame->Send(new FrameHostMsg_DidCreateOutOfProcessPepperInstance(
         plugin_child_id_, instance,
diff --git a/content/renderer/pepper/message_channel.cc b/content/renderer/pepper/message_channel.cc
index 9c17e5d..2a02ebd 100644
--- a/content/renderer/pepper/message_channel.cc
+++ b/content/renderer/pepper/message_channel.cc
@@ -364,17 +364,6 @@
   if (!container)
     return;
 
-  WebDOMEvent event =
-      container->element().document().createEvent("MessageEvent");
-  WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
-  msg_event.initMessageEvent("message",     // type
-                             false,         // canBubble
-                             false,         // cancelable
-                             message_data,  // data
-                             "",            // origin [*]
-                             NULL,          // source [*]
-                             container->element().document(), // target document
-                             "");           // lastEventId
   // [*] Note that the |origin| is only specified for cross-document and server-
   //     sent messages, while |source| is only specified for cross-document
   //     messages:
@@ -383,6 +372,7 @@
   //     at least, postMessage on Workers does not provide the origin or source.
   //     TODO(dmichael):  Add origin if we change to a more iframe-like origin
   //                      policy (see crbug.com/81537)
+  WebDOMMessageEvent msg_event(message_data);
   container->element().dispatchEvent(msg_event);
 }
 
diff --git a/content/renderer/pepper/pepper_platform_audio_output.cc b/content/renderer/pepper/pepper_platform_audio_output.cc
index 1edf45b3..796ae28d 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.cc
+++ b/content/renderer/pepper/pepper_platform_audio_output.cc
@@ -73,7 +73,7 @@
     media::AudioOutputIPCDelegateState state) {}
 
 void PepperPlatformAudioOutput::OnDeviceAuthorized(
-    bool success,
+    media::OutputDeviceStatus device_status,
     const media::AudioParameters& output_params) {
   NOTREACHED();
 }
@@ -104,7 +104,7 @@
 }
 
 void PepperPlatformAudioOutput::OnOutputDeviceSwitched(
-    media::SwitchOutputDeviceResult result) {}
+    media::OutputDeviceStatus result) {}
 
 void PepperPlatformAudioOutput::OnIPCClosed() { ipc_.reset(); }
 
diff --git a/content/renderer/pepper/pepper_platform_audio_output.h b/content/renderer/pepper/pepper_platform_audio_output.h
index f51d0bcf..5be46103 100644
--- a/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/content/renderer/pepper/pepper_platform_audio_output.h
@@ -48,12 +48,12 @@
 
   // media::AudioOutputIPCDelegate implementation.
   void OnStateChanged(media::AudioOutputIPCDelegateState state) override;
-  void OnDeviceAuthorized(bool success,
+  void OnDeviceAuthorized(media::OutputDeviceStatus device_status,
                           const media::AudioParameters& output_params) override;
   void OnStreamCreated(base::SharedMemoryHandle handle,
                        base::SyncSocket::Handle socket_handle,
                        int length) override;
-  void OnOutputDeviceSwitched(media::SwitchOutputDeviceResult result) override;
+  void OnOutputDeviceSwitched(media::OutputDeviceStatus result) override;
   void OnIPCClosed() override;
 
  protected:
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index b4690b0..0a8f0b3 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -3038,6 +3038,9 @@
                          .plugin_fullscreen_allowed)
     return false;
 
+  if (fullscreen && !IsProcessingUserGesture())
+    return false;
+
   // Unbind current 2D or 3D graphics context.
   DVLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off");
   if (fullscreen) {
diff --git a/content/renderer/push_messaging/push_messaging_dispatcher.cc b/content/renderer/push_messaging/push_messaging_dispatcher.cc
index dcf79de..ca9747e 100644
--- a/content/renderer/push_messaging/push_messaging_dispatcher.cc
+++ b/content/renderer/push_messaging/push_messaging_dispatcher.cc
@@ -85,13 +85,13 @@
 void PushMessagingDispatcher::OnSubscribeFromDocumentSuccess(
     int32_t request_id,
     const GURL& endpoint,
-    const std::vector<uint8_t>& curve25519dh) {
+    const std::vector<uint8_t>& p256dh) {
   blink::WebPushSubscriptionCallbacks* callbacks =
       subscription_callbacks_.Lookup(request_id);
   DCHECK(callbacks);
 
   callbacks->onSuccess(blink::adoptWebPtr(
-      new blink::WebPushSubscription(endpoint, curve25519dh)));
+      new blink::WebPushSubscription(endpoint, p256dh)));
 
   subscription_callbacks_.Remove(request_id);
 }
diff --git a/content/renderer/push_messaging/push_messaging_dispatcher.h b/content/renderer/push_messaging/push_messaging_dispatcher.h
index f3cf3c8..6c2678e 100644
--- a/content/renderer/push_messaging/push_messaging_dispatcher.h
+++ b/content/renderer/push_messaging/push_messaging_dispatcher.h
@@ -53,7 +53,7 @@
 
   void OnSubscribeFromDocumentSuccess(int32_t request_id,
                                       const GURL& endpoint,
-                                      const std::vector<uint8_t>& curve25519dh);
+                                      const std::vector<uint8_t>& p256dh);
 
   void OnSubscribeFromDocumentError(int32_t request_id,
                                     PushRegistrationStatus status);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 6d5eaba..b2e454f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -136,6 +136,7 @@
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
+#include "third_party/WebKit/public/web/WebPageSerializer.h"
 #include "third_party/WebKit/public/web/WebPlugin.h"
 #include "third_party/WebKit/public/web/WebPluginParams.h"
 #include "third_party/WebKit/public/web/WebRange.h"
@@ -202,6 +203,7 @@
 
 using blink::WebContentDecryptionModule;
 using blink::WebContextMenuData;
+using blink::WebCString;
 using blink::WebData;
 using blink::WebDataSource;
 using blink::WebDocument;
@@ -220,6 +222,8 @@
 using blink::WebNavigationPolicy;
 using blink::WebNavigationType;
 using blink::WebNode;
+using blink::WebPageSerializer;
+using blink::WebPageSerializerClient;
 using blink::WebPluginParams;
 using blink::WebPopupMenuInfo;
 using blink::WebRange;
@@ -1128,6 +1132,8 @@
     IPC_MESSAGE_HANDLER(FrameMsg_FailedNavigation, OnFailedNavigation)
     IPC_MESSAGE_HANDLER(FrameMsg_GetSavableResourceLinks,
                         OnGetSavableResourceLinks)
+    IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks,
+                        OnGetSerializedHtmlWithLocalLinks)
 #if defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
 #elif defined(OS_MACOSX)
@@ -1748,17 +1754,6 @@
     serialized_script_value = WebSerializedScriptValue::fromString(params.data);
   }
 
-  // Create an event with the message.  The next-to-last parameter to
-  // initMessageEvent is the last event ID, which is not used with postMessage.
-  WebDOMEvent event = frame_->document().createEvent("MessageEvent");
-  WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
-  msg_event.initMessageEvent("message",
-                             // |canBubble| and |cancellable| are always false
-                             false, false,
-                             serialized_script_value,
-                             params.source_origin, source_frame,
-                             frame_->document(), "", channels);
-
   // We must pass in the target_origin to do the security check on this side,
   // since it may have changed since the original postMessage call was made.
   WebSecurityOrigin target_origin;
@@ -1766,6 +1761,12 @@
     target_origin =
         WebSecurityOrigin::createFromString(WebString(params.target_origin));
   }
+
+  WebDOMMessageEvent msg_event(serialized_script_value,
+                               params.source_origin,
+                               source_frame,
+                               frame_->document(),
+                               channels);
   frame_->dispatchMessageEventWithOriginCheck(target_origin, msg_event);
 }
 
@@ -3893,6 +3894,14 @@
   DidPause(player);
 }
 
+void RenderFrameImpl::didSerializeDataForFrame(
+    const WebURL& frame_url,
+    const WebCString& data,
+    WebPageSerializerClient::PageSerializationStatus status) {
+  Send(new FrameHostMsg_SerializedHtmlWithLocalLinksResponse(
+      routing_id_, frame_url, data.data(), static_cast<int32>(status)));
+}
+
 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
   observers_.AddObserver(observer);
 }
@@ -4444,6 +4453,28 @@
       routing_id_, frame_->document().url(), resources_list, referrers_list));
 }
 
+void RenderFrameImpl::OnGetSerializedHtmlWithLocalLinks(
+    std::vector<GURL> original_urls,
+    std::vector<base::FilePath> equivalent_local_paths,
+    base::FilePath local_directory_path) {
+  // Only DCHECK, since the message comes from the trusted browser process.
+  DCHECK(original_urls.size() == equivalent_local_paths.size());
+
+  // Convert std::vector of GURLs to WebVector<WebURL>
+  WebVector<WebURL> weburl_links(original_urls);
+
+  // Convert std::vector of base::FilePath to WebVector<WebString>
+  WebVector<WebString> webstring_paths(equivalent_local_paths.size());
+  for (size_t i = 0; i < equivalent_local_paths.size(); i++)
+    webstring_paths[i] = equivalent_local_paths[i].AsUTF16Unsafe();
+
+  // Serialize the frame (without recursing into subframes).
+  WebPageSerializer::serialize(GetWebFrame(),
+                               this,   // WebPageSerializerClient.
+                               weburl_links, webstring_paths,
+                               local_directory_path.AsUTF16Unsafe());
+}
+
 void RenderFrameImpl::OpenURL(WebFrame* frame,
                               const GURL& url,
                               const Referrer& referrer,
@@ -4706,8 +4737,8 @@
 
     range = gfx::Range(location, location + length);
 
-    if (GetRenderWidget()->webwidget()->textInputInfo().type !=
-            blink::WebTextInputTypeNone) {
+    if (GetRenderWidget()->webwidget()->textInputType() !=
+        blink::WebTextInputTypeNone) {
       // If current focused element is editable, we will send 100 more chars
       // before and after selection. It is for input method surrounding text
       // feature.
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 7e611d604..0189577e 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -34,6 +34,7 @@
 #include "third_party/WebKit/public/web/WebDataSource.h"
 #include "third_party/WebKit/public/web/WebFrameClient.h"
 #include "third_party/WebKit/public/web/WebHistoryCommitType.h"
+#include "third_party/WebKit/public/web/WebPageSerializerClient.h"
 #include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
 #include "ui/gfx/range/range.h"
 
@@ -131,7 +132,8 @@
 class CONTENT_EXPORT RenderFrameImpl
     : public RenderFrame,
       NON_EXPORTED_BASE(public blink::WebFrameClient),
-      NON_EXPORTED_BASE(public media::WebMediaPlayerDelegate) {
+      NON_EXPORTED_BASE(public media::WebMediaPlayerDelegate),
+      NON_EXPORTED_BASE(public blink::WebPageSerializerClient) {
  public:
   // Creates a new RenderFrame as the main frame of |render_view|.
   static RenderFrameImpl* CreateMainFrame(RenderViewImpl* render_view,
@@ -568,6 +570,12 @@
   void DidPause(blink::WebMediaPlayer* player) override;
   void PlayerGone(blink::WebMediaPlayer* player) override;
 
+  // WebPageSerializerClient implementation:
+  void didSerializeDataForFrame(
+      const blink::WebURL& frame_url,
+      const blink::WebCString& data,
+      blink::WebPageSerializerClient::PageSerializationStatus status) override;
+
   // Make this frame show an empty, unscriptable page.
   // TODO(nasko): Remove this method once swapped out state is no longer used.
   void NavigateToSwappedOutURL();
@@ -722,6 +730,10 @@
                           bool has_stale_copy_in_cache,
                           int error_code);
   void OnGetSavableResourceLinks();
+  void OnGetSerializedHtmlWithLocalLinks(
+      std::vector<GURL> original_urls,
+      std::vector<base::FilePath> equivalent_local_paths,
+      base::FilePath local_directory_path);
 
   // Virtual since overridden by WebTestProxy for layout tests.
   virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 9266eeb1..aa5828c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -163,6 +163,7 @@
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
+#include "content/renderer/theme_helper_mac.h"
 #include "content/renderer/webscrollbarbehavior_impl_mac.h"
 #endif
 
@@ -1429,8 +1430,7 @@
 
 AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
   if (!audio_renderer_mixer_manager_) {
-    audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager(
-        GetAudioHardwareConfig()));
+    audio_renderer_mixer_manager_.reset(new AudioRendererMixerManager());
   }
 
   return audio_renderer_mixer_manager_.get();
@@ -1622,6 +1622,7 @@
 #endif
 #if defined(OS_MACOSX)
     IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
+    IPC_MESSAGE_HANDLER(ViewMsg_SystemColorsChanged, OnSystemColorsChanged)
 #endif
 #if defined(ENABLE_PLUGINS)
     IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
@@ -1817,6 +1818,14 @@
       params.preferred_scroller_style, params.redraw,
       params.scroll_animation_enabled, params.button_placement);
 }
+
+void RenderThreadImpl::OnSystemColorsChanged(
+    int aqua_color_variant,
+    const std::string& highlight_text_color,
+    const std::string& highlight_color) {
+  SystemColorsDidChange(aqua_color_variant, highlight_text_color,
+                        highlight_color);
+}
 #endif
 
 void RenderThreadImpl::OnCreateNewSharedWorker(
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index eef203bf..190d5578 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -476,6 +476,9 @@
 #if defined(OS_MACOSX)
   void OnUpdateScrollbarTheme(
       const ViewMsg_UpdateScrollbarTheme_Params& params);
+  void OnSystemColorsChanged(int aqua_color_variant,
+                             const std::string& highlight_text_color,
+                             const std::string& highlight_color);
 #endif
   void OnCreateNewSharedWorker(
       const WorkerProcessMsg_CreateWorker_Params& params);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 60f38fc..d2760ad 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -153,7 +153,6 @@
 #include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
 #include "third_party/WebKit/public/web/WebNodeList.h"
 #include "third_party/WebKit/public/web/WebPageImportanceSignals.h"
-#include "third_party/WebKit/public/web/WebPageSerializer.h"
 #include "third_party/WebKit/public/web/WebPlugin.h"
 #include "third_party/WebKit/public/web/WebPluginAction.h"
 #include "third_party/WebKit/public/web/WebPluginContainer.h"
@@ -245,8 +244,6 @@
 using blink::WebNavigationPolicy;
 using blink::WebNavigationType;
 using blink::WebNode;
-using blink::WebPageSerializer;
-using blink::WebPageSerializerClient;
 using blink::WebPeerConnection00Handler;
 using blink::WebPeerConnection00HandlerClient;
 using blink::WebPeerConnectionHandler;
@@ -1286,10 +1283,6 @@
     webview()->transferActiveWheelFlingAnimation(params);
 }
 
-bool RenderViewImpl::HasIMETextFocus() {
-  return GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
-}
-
 bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
   WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
   if (main_frame && main_frame->isWebLocalFrame())
@@ -1353,9 +1346,6 @@
     IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt)
     IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
     IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
-    IPC_MESSAGE_HANDLER(
-        ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
-        OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
     IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
     // TODO(viettrungluu): Move to a separate message filter.
     IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryOffsetAndLength,
@@ -2070,8 +2060,7 @@
 
   // TODO(estade): hit test the event against focused node to make sure
   // the tap actually hit the focused node.
-  blink::WebTextInputType text_input_type =
-      GetWebView()->textInputInfo().type;
+  blink::WebTextInputType text_input_type = GetWebView()->textInputType();
 
   Send(new ViewHostMsg_FocusedNodeTouched(
       routing_id(), text_input_type != blink::WebTextInputTypeNone));
@@ -2193,19 +2182,6 @@
   return WebString::fromUTF8(renderer_preferences_.accept_languages);
 }
 
-// blink::WebPageSerializerClient implementation ------------------------------
-
-void RenderViewImpl::didSerializeDataForFrame(
-    const WebURL& frame_url,
-    const WebCString& data,
-    WebPageSerializerClient::PageSerializationStatus status) {
-  Send(new ViewHostMsg_SendSerializedHtmlData(
-    routing_id(),
-    frame_url,
-    data.data(),
-    static_cast<int32>(status)));
-}
-
 // RenderView implementation ---------------------------------------------------
 
 bool RenderViewImpl::Send(IPC::Message* message) {
@@ -2782,27 +2758,6 @@
     webview()->performPluginAction(action, location);
 }
 
-void RenderViewImpl::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
-    const std::vector<GURL>& links,
-    const std::vector<base::FilePath>& local_paths,
-    const base::FilePath& local_directory_name) {
-
-  // Convert std::vector of GURLs to WebVector<WebURL>
-  WebVector<WebURL> weburl_links(links);
-
-  // Convert std::vector of base::FilePath to WebVector<WebString>
-  WebVector<WebString> webstring_paths(local_paths.size());
-  for (size_t i = 0; i < local_paths.size(); i++)
-    webstring_paths[i] = local_paths[i].AsUTF16Unsafe();
-
-  WebPageSerializer::serialize(webview()->mainFrame()->toWebLocalFrame(),
-                               true,
-                               this,
-                               weburl_links,
-                               webstring_paths,
-                               local_directory_name.AsUTF16Unsafe());
-}
-
 void RenderViewImpl::OnSuppressDialogsUntilSwapOut() {
   // Don't show any more dialogs until we finish OnSwapOut.
   suppress_dialogs_until_swap_out_ = true;
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 5e01f94..805dc07 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -53,7 +53,6 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/web/WebNavigationType.h"
 #include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebPageSerializerClient.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/web/WebViewClient.h"
 #include "ui/base/window_open_disposition.h"
@@ -153,7 +152,6 @@
 class CONTENT_EXPORT RenderViewImpl
     : public RenderWidget,
       NON_EXPORTED_BASE(public blink::WebViewClient),
-      NON_EXPORTED_BASE(public blink::WebPageSerializerClient),
       public RenderView,
       public base::SupportsWeakPtr<RenderViewImpl> {
  public:
@@ -283,11 +281,6 @@
   void TransferActiveWheelFlingAnimation(
       const blink::WebActiveWheelFlingParameters& params);
 
-  // Returns true if the focused element is editable text from the perspective
-  // of IME support (also used for on-screen keyboard). Works correctly inside
-  // supported PPAPI plugins.
-  bool HasIMETextFocus();
-
   // Synchronously sends the current navigation state to the browser.
   void SendUpdateState();
 
@@ -416,13 +409,6 @@
   virtual void didScrollWithKeyboard(const blink::WebSize& delta);
 #endif
 
-  // blink::WebPageSerializerClient implementation ----------------------------
-
-  void didSerializeDataForFrame(
-      const blink::WebURL& frame_url,
-      const blink::WebCString& data,
-      PageSerializationStatus status) override;
-
   // RenderView implementation -------------------------------------------------
 
   bool Send(IPC::Message* message) override;
@@ -643,10 +629,6 @@
   void OnFind(int request_id,
               const base::string16&,
               const blink::WebFindOptions&);
-  void OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
-      const std::vector<GURL>& links,
-      const std::vector<base::FilePath>& local_paths,
-      const base::FilePath& local_directory_name);
   void OnMediaPlayerActionAt(const gfx::Point& location,
                              const blink::WebMediaPlayerAction& action);
   void OnPluginActionAt(const gfx::Point& location,
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index afd5e8b..b932e76 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -2039,7 +2039,7 @@
 
 ui::TextInputType RenderWidget::GetTextInputType() {
   if (webwidget_)
-    return WebKitToUiTextInputType(webwidget_->textInputInfo().type);
+    return WebKitToUiTextInputType(webwidget_->textInputType());
   return ui::TEXT_INPUT_TYPE_NONE;
 }
 
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index 3a34300..3a463ea 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -6,6 +6,7 @@
 #include "base/command_line.h"
 #include "base/debug/debugger.h"
 #include "base/debug/leak_annotations.h"
+#include "base/feature_list.h"
 #include "base/i18n/rtl.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
@@ -159,6 +160,12 @@
     DCHECK(result);
   }
 
+  scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+  feature_list->InitializeFromCommandLine(
+      parsed_command_line.GetSwitchValueASCII(switches::kEnableFeatures),
+      parsed_command_line.GetSwitchValueASCII(switches::kDisableFeatures));
+  base::FeatureList::SetInstance(feature_list.Pass());
+
   // PlatformInitialize uses FieldTrials, so this must happen later.
   platform.PlatformInitialize();
 
diff --git a/content/renderer/theme_helper_mac.h b/content/renderer/theme_helper_mac.h
new file mode 100644
index 0000000..98e69491
--- /dev/null
+++ b/content/renderer/theme_helper_mac.h
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. 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_THEME_HELPER_MAC_H_
+#define CONTENT_RENDERER_THEME_HELPER_MAC_H_
+
+#include <string>
+
+namespace content {
+
+// Updates the process-wide preferences for system theme colors, by setting
+// the respective NSUserDefaults and posting notifications.
+void SystemColorsDidChange(int aqua_color_variant,
+                           const std::string& highlight_text_color,
+                           const std::string& highlight_color);
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_THEME_HELPER_MAC_H_
diff --git a/content/renderer/theme_helper_mac.mm b/content/renderer/theme_helper_mac.mm
new file mode 100644
index 0000000..7fbc6ba
--- /dev/null
+++ b/content/renderer/theme_helper_mac.mm
@@ -0,0 +1,55 @@
+// Copyright 2015 The Chromium Authors. 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/theme_helper_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/strings/sys_string_conversions.h"
+
+namespace content {
+
+void SystemColorsDidChange(int aqua_color_variant,
+                           const std::string& highlight_text_color,
+                           const std::string& highlight_color) {
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+
+  // Register the defaults in the NSArgumentDomain, which is considered
+  // volatile. Registering in the normal application domain fails from within
+  // the sandbox on 10.10+.
+  [defaults removeVolatileDomainForName:NSArgumentDomain];
+
+  NSDictionary* domain_values = @{
+    @"AppleAquaColorVariant" : @(aqua_color_variant),
+    @"AppleHighlightedTextColor" :
+        base::SysUTF8ToNSString(highlight_text_color),
+    @"AppleHighlightColor" : base::SysUTF8ToNSString(highlight_color)
+  };
+  [defaults setVolatileDomain:domain_values forName:NSArgumentDomain];
+
+  // CoreUI expects two distributed notifications to be posted as a result of
+  // the Aqua color variant being changed: AppleAquaColorVariantChanged and
+  // AppleColorPreferencesChangedNotification. These cannot be posted from
+  // within the sandbox, as distributed notifications are always delivered
+  // from the distnoted server, not directly from the posting app. As a result,
+  // the Aqua control color will not change as it should.
+
+  // However, the highlight color variant can be updated as a result of
+  // posting local notifications. Post the notifications required to make that
+  // change visible.
+  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+
+  // Trigger a NSDynamicSystemColorStore recache. Both Will and Did
+  // must be posted.
+  [center postNotificationName:@"NSSystemColorsWillChangeNotification"
+                        object:nil];
+  [center postNotificationName:NSSystemColorsDidChangeNotification
+                        object:nil];
+  // Post the notification that CoreUI would trigger as a result of the Aqua
+  // color change.
+  [center postNotificationName:NSControlTintDidChangeNotification
+                        object:nil];
+}
+
+}  // namespace content
diff --git a/content/renderer/usb/web_usb_client_impl.cc b/content/renderer/usb/web_usb_client_impl.cc
index 3d011fe..9449c35e 100644
--- a/content/renderer/usb/web_usb_client_impl.cc
+++ b/content/renderer/usb/web_usb_client_impl.cc
@@ -80,13 +80,8 @@
 void WebUSBClientImpl::getDevices(
     blink::WebUSBClientGetDevicesCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  // TODO(rockot): Remove this once DeviceManager is updated. It should no
-  // longer take enumeration options.
-  device::usb::EnumerationOptionsPtr options =
-      device::usb::EnumerationOptions::New();
-  options->filters = mojo::Array<device::usb::DeviceFilterPtr>::New(0);
   device_manager_->GetDevices(
-      options.Pass(),
+      nullptr,
       base::Bind(&OnGetDevicesComplete, base::Passed(&scoped_callbacks),
                  base::Unretained(device_services_.get())));
 }
diff --git a/content/renderer/usb/web_usb_device_impl.cc b/content/renderer/usb/web_usb_device_impl.cc
index 46c4fba..beeec4f 100644
--- a/content/renderer/usb/web_usb_device_impl.cc
+++ b/content/renderer/usb/web_usb_device_impl.cc
@@ -24,7 +24,6 @@
 const char kClearHaltFailed[] = "Unable to clear endpoint.";
 const char kDeviceNoAccess[] = "Access denied.";
 const char kDeviceNotConfigured[] = "Device not configured.";
-const char kDeviceNotOpened[] = "Device not opened.";
 const char kDeviceUnavailable[] = "Device unavailable.";
 const char kDeviceResetFailed[] = "Unable to reset the device.";
 const char kReleaseInterfaceFailed[] = "Unable to release interface.";
@@ -174,65 +173,44 @@
 
 void WebUSBDeviceImpl::close(blink::WebUSBDeviceCloseCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->Close(
-        base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
-  }
+  device_->Close(base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
 }
 
 void WebUSBDeviceImpl::getConfiguration(
     blink::WebUSBDeviceGetConfigurationCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->GetConfiguration(
-        base::Bind(&OnGetConfiguration, base::Passed(&scoped_callbacks)));
-  }
+  device_->GetConfiguration(
+      base::Bind(&OnGetConfiguration, base::Passed(&scoped_callbacks)));
 }
 
 void WebUSBDeviceImpl::setConfiguration(
     uint8_t configuration_value,
     blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->SetConfiguration(
-        configuration_value,
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kSetConfigurationFailed));
-  }
+  device_->SetConfiguration(
+      configuration_value,
+      base::Bind(&HandlePassFailDeviceOperation,
+                 base::Passed(&scoped_callbacks), kSetConfigurationFailed));
 }
 
 void WebUSBDeviceImpl::claimInterface(
     uint8_t interface_number,
     blink::WebUSBDeviceClaimInterfaceCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->ClaimInterface(
-        interface_number,
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
-  }
+  device_->ClaimInterface(
+      interface_number,
+      base::Bind(&HandlePassFailDeviceOperation,
+                 base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
 }
 
 void WebUSBDeviceImpl::releaseInterface(
     uint8_t interface_number,
     blink::WebUSBDeviceReleaseInterfaceCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->ReleaseInterface(
-        interface_number,
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
-  }
+  device_->ReleaseInterface(
+      interface_number,
+      base::Bind(&HandlePassFailDeviceOperation,
+                 base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
 }
 
 void WebUSBDeviceImpl::setInterface(
@@ -240,28 +218,20 @@
     uint8_t alternate_setting,
     blink::WebUSBDeviceSetInterfaceAlternateSettingCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->SetInterfaceAlternateSetting(
-        interface_number, alternate_setting,
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kSetInterfaceFailed));
-  }
+  device_->SetInterfaceAlternateSetting(
+      interface_number, alternate_setting,
+      base::Bind(&HandlePassFailDeviceOperation,
+                 base::Passed(&scoped_callbacks), kSetInterfaceFailed));
 }
 
 void WebUSBDeviceImpl::clearHalt(
     uint8_t endpoint_number,
     blink::WebUSBDeviceClearHaltCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->ClearHalt(
-        endpoint_number,
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kClearHaltFailed));
-  }
+  device_->ClearHalt(
+      endpoint_number,
+      base::Bind(&HandlePassFailDeviceOperation,
+                 base::Passed(&scoped_callbacks), kClearHaltFailed));
 }
 
 void WebUSBDeviceImpl::controlTransfer(
@@ -271,30 +241,28 @@
     unsigned int timeout,
     blink::WebUSBDeviceControlTransferCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device::usb::ControlTransferParamsPtr params =
-        device::usb::ControlTransferParams::From(parameters);
-    switch (parameters.direction) {
-      case WebUSBDevice::TransferDirection::In:
-        device_->ControlTransferIn(params.Pass(), data_size, timeout,
-            base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
-        break;
-      case WebUSBDevice::TransferDirection::Out: {
-        std::vector<uint8_t> bytes;
-        if (data)
-          bytes.assign(data, data + data_size);
-        mojo::Array<uint8_t> mojo_bytes;
-        mojo_bytes.Swap(&bytes);
-        device_->ControlTransferOut(params.Pass(), mojo_bytes.Pass(), timeout,
-            base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
-                       data_size));
-        break;
-      }
-      default:
-        NOTREACHED();
+  device::usb::ControlTransferParamsPtr params =
+      device::usb::ControlTransferParams::From(parameters);
+  switch (parameters.direction) {
+    case WebUSBDevice::TransferDirection::In:
+      device_->ControlTransferIn(
+          params.Pass(), data_size, timeout,
+          base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
+      break;
+    case WebUSBDevice::TransferDirection::Out: {
+      std::vector<uint8_t> bytes;
+      if (data)
+        bytes.assign(data, data + data_size);
+      mojo::Array<uint8_t> mojo_bytes;
+      mojo_bytes.Swap(&bytes);
+      device_->ControlTransferOut(
+          params.Pass(), mojo_bytes.Pass(), timeout,
+          base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
+                     data_size));
+      break;
     }
+    default:
+      NOTREACHED();
   }
 }
 
@@ -306,42 +274,34 @@
     unsigned int timeout,
     blink::WebUSBDeviceBulkTransferCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    switch (direction) {
-      case WebUSBDevice::TransferDirection::In:
-        device_->GenericTransferIn(
-            endpoint_number, data_size, timeout,
-            base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
-        break;
-      case WebUSBDevice::TransferDirection::Out: {
-        std::vector<uint8_t> bytes;
-        if (data)
-          bytes.assign(data, data + data_size);
-        mojo::Array<uint8_t> mojo_bytes;
-        mojo_bytes.Swap(&bytes);
-        device_->GenericTransferOut(
-            endpoint_number, mojo_bytes.Pass(), timeout,
-            base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
-                       data_size));
-        break;
-      }
-      default:
-        NOTREACHED();
+  switch (direction) {
+    case WebUSBDevice::TransferDirection::In:
+      device_->GenericTransferIn(
+          endpoint_number, data_size, timeout,
+          base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
+      break;
+    case WebUSBDevice::TransferDirection::Out: {
+      std::vector<uint8_t> bytes;
+      if (data)
+        bytes.assign(data, data + data_size);
+      mojo::Array<uint8_t> mojo_bytes;
+      mojo_bytes.Swap(&bytes);
+      device_->GenericTransferOut(
+          endpoint_number, mojo_bytes.Pass(), timeout,
+          base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
+                     data_size));
+      break;
     }
+    default:
+      NOTREACHED();
   }
 }
 
 void WebUSBDeviceImpl::reset(blink::WebUSBDeviceResetCallbacks* callbacks) {
   auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
-  if (!device_) {
-    RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
-  } else {
-    device_->Reset(
-        base::Bind(&HandlePassFailDeviceOperation,
-                   base::Passed(&scoped_callbacks), kDeviceResetFailed));
-  }
+  device_->Reset(base::Bind(&HandlePassFailDeviceOperation,
+                            base::Passed(&scoped_callbacks),
+                            kDeviceResetFailed));
 }
 
 }  // namespace content
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
index 95ab6033..bfa3a16 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -86,8 +86,7 @@
             mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl));
         }
 
-        if (CommandLine.getInstance().hasSwitch(ContentSwitches.RUN_LAYOUT_TEST)
-                || CommandLine.getInstance().hasSwitch(ContentSwitches.DUMP_RENDER_TREE)) {
+        if (CommandLine.getInstance().hasSwitch(ContentSwitches.RUN_LAYOUT_TEST)) {
             try {
                 BrowserStartupController.get(this, LibraryProcessType.PROCESS_BROWSER)
                         .startBrowserProcessesSync(false);
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index d9601d5..24525e8 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -121,12 +121,6 @@
 bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
   base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
 
-  // "dump-render-tree" has been renamed to "run-layout-test", but the old
-  // flag name is still used in some places, so this check will remain until
-  // it is phased out entirely.
-  if (command_line.HasSwitch(switches::kDumpRenderTree))
-    command_line.AppendSwitch(switches::kRunLayoutTest);
-
 #if defined(OS_WIN)
   // Enable trace control and transport through event tracing for Windows.
   logging::LogEventProvider::Initialize(kContentShellProviderName);
diff --git a/content/shell/browser/layout_test/layout_test_push_messaging_service.cc b/content/shell/browser/layout_test/layout_test_push_messaging_service.cc
index 03498e7..e108c03 100644
--- a/content/shell/browser/layout_test/layout_test_push_messaging_service.cc
+++ b/content/shell/browser/layout_test/layout_test_push_messaging_service.cc
@@ -16,14 +16,14 @@
 
 namespace {
 
-// Curve25519 public key made available to layout tests. Must be 32 bytes.
-const uint8_t kTestCurve25519dh[] = {
+// P-256 public key made available to layout tests. Must be 32 bytes.
+const uint8_t kTestP256Key[] = {
   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
   0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
 };
 
-static_assert(sizeof(kTestCurve25519dh) == 32,
+static_assert(sizeof(kTestP256Key) == 32,
               "The fake public key must have the size of a real public key.");
 
 blink::WebPushPermissionStatus ToWebPushPermissionStatus(
@@ -73,10 +73,10 @@
     const PushMessagingService::RegisterCallback& callback) {
   if (GetPermissionStatus(requesting_origin, requesting_origin, user_visible) ==
       blink::WebPushPermissionStatusGranted) {
-    std::vector<uint8_t> curve25519dh(
-        kTestCurve25519dh, kTestCurve25519dh + arraysize(kTestCurve25519dh));
+    std::vector<uint8_t> p256dh(
+        kTestP256Key, kTestP256Key + arraysize(kTestP256Key));
 
-    callback.Run("layoutTestRegistrationId", curve25519dh,
+    callback.Run("layoutTestRegistrationId", p256dh,
                  PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE);
   } else {
     callback.Run("registration_id", std::vector<uint8_t>(),
@@ -88,10 +88,10 @@
     const GURL& origin,
     int64_t service_worker_registration_id,
     const PublicKeyCallback& callback) {
-  std::vector<uint8_t> curve25519dh(
-        kTestCurve25519dh, kTestCurve25519dh + arraysize(kTestCurve25519dh));
+  std::vector<uint8_t> p256dh(
+        kTestP256Key, kTestP256Key + arraysize(kTestP256Key));
 
-  callback.Run(true /* success */, curve25519dh);
+  callback.Run(true /* success */, p256dh);
 }
 
 blink::WebPushPermissionStatus
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index 247010a..837eb82 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -91,7 +91,7 @@
 
 scoped_ptr<net::NetworkDelegate>
 ShellURLRequestContextGetter::CreateNetworkDelegate() {
-  return make_scoped_ptr(new ShellNetworkDelegate).Pass();
+  return make_scoped_ptr(new ShellNetworkDelegate);
 }
 
 scoped_ptr<net::ProxyConfigService>
@@ -201,10 +201,8 @@
     network_session_params.host_resolver =
         url_request_context_->host_resolver();
 
-    storage_->set_http_transaction_factory(
-        make_scoped_ptr(
-            new net::HttpCache(network_session_params, main_backend))
-            .Pass());
+    storage_->set_http_transaction_factory(make_scoped_ptr(
+        new net::HttpCache(network_session_params, main_backend)));
 
     scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
         new net::URLRequestJobFactoryImpl());
diff --git a/content/shell/common/shell_switches.cc b/content/shell/common/shell_switches.cc
index 55d349e..9bce7af 100644
--- a/content/shell/common/shell_switches.cc
+++ b/content/shell/common/shell_switches.cc
@@ -28,12 +28,7 @@
 // causes the leak detector to cause immediate crash when found leak.
 const char kCrashOnFailure[] = "crash-on-failure";
 
-// Request the render trees of pages to be dumped as text once they have
-// finished loading. Note that this switch has been deprecated, and the
-// identically functioning |kRunLayoutTest| switch should be used instead.
-const char kDumpRenderTree[] = "dump-render-tree";
-
-// When dump-render-tree is enabled, this causes the line box tree for
+// When run-layout-test is enabled, this causes the line box tree for
 // each LayoutBlockFlow to be dumped as well.
 const char kDumpLineBoxTrees[] = "dump-line-box-trees";
 
diff --git a/content/shell/renderer/ipc_echo.cc b/content/shell/renderer/ipc_echo.cc
index 5bdb320..12f049b3 100644
--- a/content/shell/renderer/ipc_echo.cc
+++ b/content/shell/renderer/ipc_echo.cc
@@ -111,12 +111,7 @@
 void IPCEcho::DidRespondEcho(int id, int size) {
   last_echo_id_ = id;
   last_echo_size_ = size;
-  blink::WebString eventName = blink::WebString::fromUTF8("CustomEvent");
-  blink::WebString eventType = blink::WebString::fromUTF8("pong");
-  blink::WebDOMEvent event = document_.createEvent(eventName);
-  event.to<blink::WebDOMCustomEvent>().initCustomEvent(
-      eventType, false, false, blink::WebSerializedScriptValue());
-  document_.dispatchEvent(event);
+  document_.dispatchEvent(blink::WebDOMCustomEvent("pong"));
 }
 
 void IPCEcho::Install(blink::WebFrame* frame) {
diff --git a/content/test/data/dom_serializer/iframe-src-is-exe.htm b/content/test/data/dom_serializer/iframe-src-is-exe.htm
deleted file mode 100644
index ed32b12..0000000
--- a/content/test/data/dom_serializer/iframe-src-is-exe.htm
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>

-<body>

-This tests that we can serialize a page that has a downloaded url in an iframe without crashing.

-

-<iframe src="dummy.exe"></iframe>

-

-</body>

-</html>
\ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/context_lost.py b/content/test/gpu/gpu_tests/context_lost.py
index ce7861a5..80002b0 100644
--- a/content/test/gpu/gpu_tests/context_lost.py
+++ b/content/test/gpu/gpu_tests/context_lost.py
@@ -6,6 +6,7 @@
 
 import context_lost_expectations
 import gpu_test_base
+import path_util
 
 from telemetry.core import exceptions
 from telemetry.core import util
@@ -13,7 +14,7 @@
 from telemetry.story import story_set as story_set_module
 
 data_path = os.path.join(
-    util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu')
+    path_util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu')
 
 wait_timeout = 60  # seconds
 
diff --git a/content/test/gpu/gpu_tests/exception_formatter.py b/content/test/gpu/gpu_tests/exception_formatter.py
index 912c006..78cbc46 100644
--- a/content/test/gpu/gpu_tests/exception_formatter.py
+++ b/content/test/gpu/gpu_tests/exception_formatter.py
@@ -9,8 +9,9 @@
 import sys
 import traceback
 
+import path_util
+
 from telemetry.core import exceptions
-from telemetry.core import util
 
 
 def PrintFormattedException(exception_class=None, exception=None, tb=None,
@@ -55,7 +56,7 @@
   print >> sys.stderr
 
   # Format the traceback.
-  base_dir = os.path.abspath(util.GetChromiumSrcDir())
+  base_dir = os.path.abspath(path_util.GetChromiumSrcDir())
   print >> sys.stderr, 'Traceback (most recent call last):'
   for filename, line, function, text in processed_tb:
     filename = os.path.abspath(filename)
diff --git a/content/test/gpu/gpu_tests/gpu_test_base_unittest.py b/content/test/gpu/gpu_tests/gpu_test_base_unittest.py
index 4ad7016..7001f6f 100644
--- a/content/test/gpu/gpu_tests/gpu_test_base_unittest.py
+++ b/content/test/gpu/gpu_tests/gpu_test_base_unittest.py
@@ -144,6 +144,15 @@
     self.assertEquals(mock_shared_state.mock_calls, expected)
 
 class PageExecutionTest(unittest.TestCase):
+  def setUp(self):
+    self.patcher = mock.patch(
+        'telemetry.internal.story_runner.browser_finder.FindBrowser')
+    find_browser_mock = self.patcher.start()
+    find_browser_mock.return_value = fakes.FakePossibleBrowser()
+
+  def tearDown(self):
+    mock.patch.stopall()
+
   def setupTest(self, num_test_failures=0, manager_mock=None):
     finder_options = fakes.CreateBrowserFinderOptions()
     finder_options.browser_options.platform = fakes.FakeLinuxPlatform()
diff --git a/content/test/gpu/gpu_tests/maps.py b/content/test/gpu/gpu_tests/maps.py
index 939fc575..9109170 100644
--- a/content/test/gpu/gpu_tests/maps.py
+++ b/content/test/gpu/gpu_tests/maps.py
@@ -13,6 +13,7 @@
 import cloud_storage_test_base
 import gpu_test_base
 import maps_expectations
+import path_util
 
 from telemetry.core import util
 from telemetry.page import page_test
@@ -100,7 +101,7 @@
 
   def CreateStorySet(self, options):
     story_set_path = os.path.join(
-        util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'page_sets')
+        path_util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'page_sets')
     ps = story_set_module.StorySet(
         archive_data_file='data/maps.json',
         base_dir=story_set_path,
diff --git a/content/test/gpu/gpu_tests/path_util.py b/content/test/gpu/gpu_tests/path_util.py
new file mode 100644
index 0000000..34790ce
--- /dev/null
+++ b/content/test/gpu/gpu_tests/path_util.py
@@ -0,0 +1,10 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+
+def GetChromiumSrcDir():
+  return os.path.abspath(os.path.join(
+      os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir))
diff --git a/content/test/gpu/gpu_tests/screenshot_sync.py b/content/test/gpu/gpu_tests/screenshot_sync.py
index 867d7213..e6984b9 100644
--- a/content/test/gpu/gpu_tests/screenshot_sync.py
+++ b/content/test/gpu/gpu_tests/screenshot_sync.py
@@ -5,16 +5,16 @@
 import random
 
 import gpu_test_base
+import path_util
 import screenshot_sync_expectations as expectations
 
 from telemetry import benchmark
-from telemetry.core import util
 from telemetry.page import page_test
 from telemetry.story import story_set as story_set_module
 from telemetry.util import image_util
 
 data_path = os.path.join(
-    util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu')
+    path_util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu')
 
 class ScreenshotSyncValidator(gpu_test_base.ValidatorBase):
   def CustomizeBrowserOptions(self, options):
diff --git a/content/test/gpu/gpu_tests/webgl_conformance.py b/content/test/gpu/gpu_tests/webgl_conformance.py
index 0f72e60..4c3c9ab 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance.py
@@ -7,9 +7,9 @@
 import sys
 
 import gpu_test_base
+import path_util
 import webgl_conformance_expectations
 
-from telemetry.core import util
 from telemetry.internal.browser import browser_finder
 from telemetry.page import page_test
 from telemetry.page import shared_page_state
@@ -17,7 +17,7 @@
 
 
 conformance_path = os.path.join(
-    util.GetChromiumSrcDir(),
+    path_util.GetChromiumSrcDir(),
     'third_party', 'webgl', 'src', 'sdk', 'tests')
 
 conformance_harness_script = r"""
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index bb980d7e7..673faff 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -408,12 +408,6 @@
         ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Fail('conformance/glsl/functions/glsl-function-sin.html',
         ['chromeos', ('intel', 0xa011)], bug=375554)
-    self.Fail('conformance/glsl/misc/empty_main.vert.html',
-        ['chromeos', ('intel', 0xa011)], bug=375554)
-    self.Fail('conformance/glsl/misc/gl_position_unset.vert.html',
-        ['chromeos', ('intel', 0xa011)], bug=375554)
-    self.Fail('conformance/glsl/misc/shaders-with-varyings.html',
-        ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Fail('conformance/glsl/variables/gl-frontfacing.html',
         ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Fail('conformance/limits/gl-max-texture-dimensions.html',
@@ -469,8 +463,6 @@
         ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Fail('conformance/textures/misc/texture-size.html',
         ['chromeos', ('intel', 0xa011)], bug=375554)
-    self.Fail('conformance/textures/misc/texture-size-limit.html',
-        ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Fail('conformance/uniforms/gl-uniform-arrays.html',
         ['chromeos', ('intel', 0xa011)], bug=375554)
     self.Skip('conformance/uniforms/uniform-default-values.html',
@@ -649,6 +641,29 @@
         ['mac'], bug=483282)
     self.Fail('conformance2/textures/misc/texture-npot.html',
         ['mac'], bug=483282)
+    # Mac Intel only.
+    self.Fail('deqp/data/gles3/shaders/arrays.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/conditionals.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/declarations.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/fragdata.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/invalid_texture_functions.html',
+        ['mac', 'intel'], bug=536887)
+    self.Fail('deqp/data/gles3/shaders/keywords.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/negative.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/switch.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/data/gles3/shaders/swizzles.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/functional/gles3/bufferobjectquery.html', ['mac', 'intel'],
+        bug=536887)
+    self.Fail('deqp/functional/gles3/fbostencilbuffer.html', ['mac', 'intel'],
+        bug=536887)
 
     # Linux only.
     self.Fail('conformance2/glsl3/vector-dynamic-indexing.html',
@@ -660,27 +675,10 @@
     # Linux NVIDIA only.
     self.Skip('deqp/functional/gles3/shaderswitch.html',
         ['linux', 'nvidia'], bug=483282)
-    # Linux AMD only.
+    # Linux AMD only (but fails on all Linux, so not specified as AMD specific)
     # It looks like AMD shader compiler rejects many valid ES3 semantics.
-    self.Skip('deqp/data/gles3/shaders/arrays.html',
-        ['linux', 'amd'], bug=483282)
+    self.Skip('deqp/data/gles3/shaders/arrays.html', ['linux'], bug=483282)
     self.Skip('deqp/data/gles3/shaders/constant_expressions.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/data/gles3/shaders/constants.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/data/gles3/shaders/conversions.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/data/gles3/shaders/functions.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/data/gles3/shaders/linkage.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/data/gles3/shaders/preprocessor.html',
-        ['linux', 'amd'], bug=483282)
+        ['linux'], bug=483282)
     self.Skip('deqp/data/gles3/shaders/qualification_order.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/framework/opengl/simplereference/referencecontext.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/functional/gles3//attriblocation.html',
-        ['linux', 'amd'], bug=483282)
-    self.Skip('deqp/functional/gles3/booleanstatequery.html',
-        ['linux', 'amd'], bug=483282)
+        ['linux'], bug=483282)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py
index 2501aac2..e562fb1 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py
@@ -4,11 +4,11 @@
 import os
 import unittest
 
-from telemetry.core import util
 from telemetry.testing import fakes
 
 import fake_win_amd_gpu_info
 import gpu_test_base
+import path_util
 import webgl_conformance_expectations
 
 class FakeWindowsPlatform(fakes.FakePlatform):
@@ -50,7 +50,7 @@
     expectations = webgl_conformance_expectations.\
                    WebGLConformanceExpectations(
                      os.path.join(
-                       util.GetChromiumSrcDir(),
+                       path_util.GetChromiumSrcDir(),
                        'third_party', 'webgl', 'src', 'sdk', 'tests'))
     page = FakePage(
       'conformance/glsl/constructors/glsl-construct-vec-mat-index.html',
diff --git a/content/test/gpu/run_unittests.py b/content/test/gpu/run_unittests.py
index ea5461e..11eb514 100755
--- a/content/test/gpu/run_unittests.py
+++ b/content/test/gpu/run_unittests.py
@@ -26,5 +26,5 @@
 
   path_to_run_tests = os.path.join(telemetry_dir, 'telemetry', 'testing',
                                    'run_tests.py')
-  argv = ['--top-level-dir', gpu_test_dir] + sys.argv[1:]
+  argv = ['--no-browser', '--top-level-dir', gpu_test_dir] + sys.argv[1:]
   sys.exit(subprocess.call([sys.executable, path_to_run_tests] + argv, env=env))
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index db0dd6c..e7a77b8 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -155,6 +155,13 @@
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableBrowserSideNavigation)) {
     NavigationRequest* request = frame_tree_node_->navigation_request();
+    CHECK(request);
+    // Simulate a beforeUnload ACK from the renderer if the browser is waiting
+    // for it. If it runs it will update the request state.
+    if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE) {
+      static_cast<TestRenderFrameHost*>(frame_tree_node()->current_frame_host())
+          ->SendBeforeUnloadACK(true);
+    }
     TestNavigationURLLoader* url_loader =
         static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
     CHECK(url_loader);
@@ -364,8 +371,10 @@
 
   // Simulate a beforeUnload ACK from the renderer if the browser is waiting for
   // it. If it runs it will update the request state.
-  if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE)
-    SendBeforeUnloadACK(true);
+  if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE) {
+    static_cast<TestRenderFrameHost*>(frame_tree_node()->current_frame_host())
+        ->SendBeforeUnloadACK(true);
+  }
 
   CHECK(request->state() == NavigationRequest::STARTED);
 
diff --git a/content/test/web_contents_observer_sanity_checker.cc b/content/test/web_contents_observer_sanity_checker.cc
index f3b0f72..2754dde 100644
--- a/content/test/web_contents_observer_sanity_checker.cc
+++ b/content/test/web_contents_observer_sanity_checker.cc
@@ -128,6 +128,7 @@
   CHECK(navigation_handle->GetNetErrorCode() == net::OK);
   CHECK(!navigation_handle->HasCommitted());
   CHECK(!navigation_handle->IsErrorPage());
+  CHECK_EQ(navigation_handle->GetWebContents(), web_contents());
 
   ongoing_navigations_.insert(navigation_handle);
 }
@@ -139,6 +140,7 @@
   CHECK(navigation_handle->GetNetErrorCode() == net::OK);
   CHECK(!navigation_handle->HasCommitted());
   CHECK(!navigation_handle->IsErrorPage());
+  CHECK_EQ(navigation_handle->GetWebContents(), web_contents());
 }
 
 void WebContentsObserverSanityChecker::ReadyToCommitNavigation(
@@ -147,6 +149,8 @@
 
   CHECK(!navigation_handle->HasCommitted());
   CHECK(navigation_handle->GetRenderFrameHost());
+  CHECK_EQ(navigation_handle->GetWebContents(), web_contents());
+  CHECK(navigation_handle->GetRenderFrameHost() != nullptr);
 }
 
 void WebContentsObserverSanityChecker::DidFinishNavigation(
@@ -159,6 +163,7 @@
   CHECK_IMPLIES(
       navigation_handle->HasCommitted() && navigation_handle->IsErrorPage(),
       navigation_handle->GetNetErrorCode() != net::OK);
+  CHECK_EQ(navigation_handle->GetWebContents(), web_contents());
 
   CHECK_IMPLIES(navigation_handle->HasCommitted(),
                 navigation_handle->GetRenderFrameHost() != nullptr);
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index af78cbf..215bd6fa 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -10,8 +10,6 @@
   sources = [
     "aead_openssl.cc",
     "aead_openssl.h",
-    "aes_128_gcm_helpers_nss.cc",
-    "aes_128_gcm_helpers_nss.h",
     "apple_keychain.h",
     "apple_keychain_ios.mm",
     "apple_keychain_mac.mm",
@@ -138,8 +136,6 @@
   if (use_openssl) {
     # Remove NSS files when using OpenSSL
     sources -= [
-      "aes_128_gcm_helpers_nss.cc",
-      "aes_128_gcm_helpers_nss.h",
       "ec_private_key_nss.cc",
       "ec_signature_creator_nss.cc",
       "encryptor_nss.cc",
@@ -240,7 +236,6 @@
 test("crypto_unittests") {
   sources = [
     "aead_openssl_unittest.cc",
-    "aes_128_gcm_helpers_nss_unittest.cc",
     "curve25519_unittest.cc",
     "ec_private_key_unittest.cc",
     "ec_signature_creator_unittest.cc",
@@ -271,9 +266,7 @@
     ]
   }
 
-  if (use_openssl) {
-    sources -= [ "aes_128_gcm_helpers_nss_unittest.cc" ]
-  } else {
+  if (!use_openssl) {
     sources -= [ "openssl_bio_string_unittest.cc" ]
   }
 
diff --git a/crypto/aes_128_gcm_helpers_nss.cc b/crypto/aes_128_gcm_helpers_nss.cc
deleted file mode 100644
index 621f28b..0000000
--- a/crypto/aes_128_gcm_helpers_nss.cc
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/aes_128_gcm_helpers_nss.h"
-
-#include <pkcs11t.h>
-#include <seccomon.h>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "crypto/ghash.h"
-#include "crypto/scoped_nss_types.h"
-
-#if defined(USE_NSS_CERTS)
-#include <dlfcn.h>
-#endif
-
-namespace crypto {
-namespace {
-
-// Declaration of the prototype both PK11_Decrypt and PK11_Encrypt follow.
-using PK11_TransformFunction = SECStatus(PK11SymKey* symKey,
-                                         CK_MECHANISM_TYPE mechanism,
-                                         SECItem* param,
-                                         unsigned char* out,
-                                         unsigned int* outLen,
-                                         unsigned int maxLen,
-                                         const unsigned char* data,
-                                         unsigned int dataLen);
-
-// On Linux, dynamically link against the system version of libnss3.so. In
-// order to continue working on systems without up-to-date versions of NSS,
-// lookup PK11_Decrypt and PK11_Encrypt with dlsym.
-//
-// GcmSupportChecker is a singleton which caches the results of runtime symbol
-// resolution of these symbols.
-class GcmSupportChecker {
- public:
-  PK11_TransformFunction* pk11_decrypt_func() { return pk11_decrypt_func_; }
-
-  PK11_TransformFunction* pk11_encrypt_func() { return pk11_encrypt_func_; }
-
- private:
-  friend struct base::DefaultLazyInstanceTraits<GcmSupportChecker>;
-
-  GcmSupportChecker() {
-#if !defined(USE_NSS_CERTS)
-    // Using a bundled version of NSS that is guaranteed to have these symbols.
-    pk11_decrypt_func_ = PK11_Decrypt;
-    pk11_encrypt_func_ = PK11_Encrypt;
-#else
-    // Using system NSS libraries and PCKS #11 modules, which may not have the
-    // necessary functions (PK11_Decrypt and PK11_Encrypt) or mechanism support
-    // (CKM_AES_GCM).
-
-    // If PK11_Decrypt() and PK11_Encrypt() were successfully resolved, then NSS
-    // will support AES-GCM directly. This was introduced in NSS 3.15.
-    pk11_decrypt_func_ = reinterpret_cast<PK11_TransformFunction*>(
-        dlsym(RTLD_DEFAULT, "PK11_Decrypt"));
-    pk11_encrypt_func_ = reinterpret_cast<PK11_TransformFunction*>(
-        dlsym(RTLD_DEFAULT, "PK11_Encrypt"));
-#endif
-  }
-
-  ~GcmSupportChecker() {}
-
-  // |pk11_decrypt_func_| stores the runtime symbol resolution of PK11_Decrypt.
-  PK11_TransformFunction* pk11_decrypt_func_;
-
-  // |pk11_encrypt_func_| stores the runtime symbol resolution of PK11_Encrypt.
-  PK11_TransformFunction* pk11_encrypt_func_;
-
-  DISALLOW_COPY_AND_ASSIGN(GcmSupportChecker);
-};
-
-base::LazyInstance<GcmSupportChecker>::Leaky g_gcm_support_checker =
-    LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
-
-// Calls PK11_Decrypt if it's available. Otherwise, emulates CKM_AES_GCM using
-// CKM_AES_CTR and the GaloisHash class.
-SECStatus PK11DecryptHelper(PK11SymKey* key,
-                            CK_MECHANISM_TYPE mechanism,
-                            SECItem* param,
-                            unsigned char* out,
-                            unsigned int* out_len,
-                            unsigned int max_len,
-                            const unsigned char* data,
-                            unsigned int data_len) {
-  // If PK11_Decrypt() was successfully resolved or if bundled version of NSS is
-  // being used, then NSS will support AES-GCM directly.
-  PK11_TransformFunction* pk11_decrypt_func =
-      g_gcm_support_checker.Get().pk11_decrypt_func();
-
-  if (pk11_decrypt_func != nullptr) {
-    return pk11_decrypt_func(key, mechanism, param, out, out_len, max_len, data,
-                             data_len);
-  }
-
-  // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x
-  // has a bug in the AES GCM code
-  // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing
-  // the PK11_Decrypt function
-  // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are
-  // resolved in NSS 3.15.
-
-  CHECK_EQ(mechanism, static_cast<CK_MECHANISM_TYPE>(CKM_AES_GCM));
-  CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS));
-
-  const CK_GCM_PARAMS* gcm_params =
-      reinterpret_cast<CK_GCM_PARAMS*>(param->data);
-
-  const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8;
-
-  if (gcm_params->ulIvLen != 12u) {
-    DVLOG(1) << "ulIvLen is not equal to 12";
-    PORT_SetError(SEC_ERROR_INPUT_LEN);
-    return SECFailure;
-  }
-
-  SECItem my_param = {siBuffer, nullptr, 0};
-
-  // Step 2. Let H = CIPH_K(128 '0' bits).
-  unsigned char ghash_key[16] = {0};
-  crypto::ScopedPK11Context ctx(
-      PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param));
-  if (!ctx) {
-    DVLOG(1) << "PK11_CreateContextBySymKey failed";
-    return SECFailure;
-  }
-  int output_len;
-  if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key),
-                    ghash_key, sizeof(ghash_key)) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-
-  if (PK11_Finalize(ctx.get()) != SECSuccess) {
-    DVLOG(1) << "PK11_Finalize failed";
-    return SECFailure;
-  }
-
-  if (output_len != sizeof(ghash_key)) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  // Step 3. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1.
-  CK_AES_CTR_PARAMS ctr_params = {0};
-  ctr_params.ulCounterBits = 32;
-  memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen);
-  ctr_params.cb[12] = 0;
-  ctr_params.cb[13] = 0;
-  ctr_params.cb[14] = 0;
-  ctr_params.cb[15] = 1;
-
-  my_param.type = siBuffer;
-  my_param.data = reinterpret_cast<unsigned char*>(&ctr_params);
-  my_param.len = sizeof(ctr_params);
-
-  ctx.reset(
-      PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param));
-  if (!ctx) {
-    DVLOG(1) << "PK11_CreateContextBySymKey failed";
-    return SECFailure;
-  }
-
-  // Step 6. Calculate the encryption mask of GCTR_K(J0, ...).
-  unsigned char tag_mask[16] = {0};
-  if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask),
-                    tag_mask, sizeof(tag_mask)) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-  if (output_len != sizeof(tag_mask)) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  if (data_len < auth_tag_size) {
-    PORT_SetError(SEC_ERROR_INPUT_LEN);
-    return SECFailure;
-  }
-
-  // The const_cast for |data| can be removed if system NSS libraries are
-  // NSS 3.14.1 or later (NSS bug
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=808218).
-  if (PK11_CipherOp(ctx.get(), out, &output_len, max_len,
-                    const_cast<unsigned char*>(data),
-                    data_len - auth_tag_size) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-
-  if (PK11_Finalize(ctx.get()) != SECSuccess) {
-    DVLOG(1) << "PK11_Finalize failed";
-    return SECFailure;
-  }
-
-  if (static_cast<unsigned int>(output_len) != data_len - auth_tag_size) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  crypto::GaloisHash ghash(ghash_key);
-  ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen);
-  ghash.UpdateCiphertext(data, output_len);
-  unsigned char auth_tag[auth_tag_size];
-  ghash.Finish(auth_tag, auth_tag_size);
-  for (unsigned int i = 0; i < auth_tag_size; i++) {
-    auth_tag[i] ^= tag_mask[i];
-  }
-
-  if (NSS_SecureMemcmp(auth_tag, data + output_len, auth_tag_size) != 0) {
-    PORT_SetError(SEC_ERROR_BAD_DATA);
-    return SECFailure;
-  }
-
-  *out_len = output_len;
-  return SECSuccess;
-}
-
-// Calls PK11_Encrypt if it's available. Otherwise, emulates CKM_AES_GCM using
-// CKM_AES_CTR and the GaloisHash class.
-SECStatus PK11EncryptHelper(PK11SymKey* key,
-                            CK_MECHANISM_TYPE mechanism,
-                            SECItem* param,
-                            unsigned char* out,
-                            unsigned int* out_len,
-                            unsigned int max_len,
-                            const unsigned char* data,
-                            unsigned int data_len) {
-  // If PK11_Encrypt() was successfully resolved or if bundled version of NSS is
-  // being used, then NSS will support AES-GCM directly.
-  PK11_TransformFunction* pk11_encrypt_func =
-      g_gcm_support_checker.Get().pk11_encrypt_func();
-
-  if (pk11_encrypt_func != nullptr) {
-    return pk11_encrypt_func(key, mechanism, param, out, out_len, max_len, data,
-                             data_len);
-  }
-
-  // Otherwise, the user has an older version of NSS. Regrettably, NSS 3.14.x
-  // has a bug in the AES GCM code
-  // (https://bugzilla.mozilla.org/show_bug.cgi?id=853285), as well as missing
-  // the PK11_Encrypt function
-  // (https://bugzilla.mozilla.org/show_bug.cgi?id=854063), both of which are
-  // resolved in NSS 3.15.
-
-  CHECK_EQ(mechanism, static_cast<CK_MECHANISM_TYPE>(CKM_AES_GCM));
-  CHECK_EQ(param->len, sizeof(CK_GCM_PARAMS));
-
-  const CK_GCM_PARAMS* gcm_params =
-      reinterpret_cast<CK_GCM_PARAMS*>(param->data);
-
-  const CK_ULONG auth_tag_size = gcm_params->ulTagBits / 8;
-
-  if (max_len < auth_tag_size) {
-    DVLOG(1) << "max_len is less than kAuthTagSize";
-    PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-    return SECFailure;
-  }
-
-  if (gcm_params->ulIvLen != 12u) {
-    DVLOG(1) << "ulIvLen is not equal to 12";
-    PORT_SetError(SEC_ERROR_INPUT_LEN);
-    return SECFailure;
-  }
-
-  SECItem my_param = {siBuffer, nullptr, 0};
-
-  // Step 1. Let H = CIPH_K(128 '0' bits).
-  unsigned char ghash_key[16] = {0};
-  crypto::ScopedPK11Context ctx(
-      PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, key, &my_param));
-  if (!ctx) {
-    DVLOG(1) << "PK11_CreateContextBySymKey failed";
-    return SECFailure;
-  }
-  int output_len;
-  if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key),
-                    ghash_key, sizeof(ghash_key)) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-
-  if (PK11_Finalize(ctx.get()) != SECSuccess) {
-    DVLOG(1) << "PK11_Finalize failed";
-    return SECFailure;
-  }
-
-  if (output_len != sizeof(ghash_key)) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  // Step 2. If len(IV)=96, then let J0 = IV || 31 '0' bits || 1.
-  CK_AES_CTR_PARAMS ctr_params = {0};
-  ctr_params.ulCounterBits = 32;
-  memcpy(ctr_params.cb, gcm_params->pIv, gcm_params->ulIvLen);
-  ctr_params.cb[12] = 0;
-  ctr_params.cb[13] = 0;
-  ctr_params.cb[14] = 0;
-  ctr_params.cb[15] = 1;
-
-  my_param.type = siBuffer;
-  my_param.data = reinterpret_cast<unsigned char*>(&ctr_params);
-  my_param.len = sizeof(ctr_params);
-
-  ctx.reset(
-      PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key, &my_param));
-  if (!ctx) {
-    DVLOG(1) << "PK11_CreateContextBySymKey failed";
-    return SECFailure;
-  }
-
-  // Step 6. Calculate the encryption mask of GCTR_K(J0, ...).
-  unsigned char tag_mask[16] = {0};
-  if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask),
-                    tag_mask, sizeof(tag_mask)) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-  if (output_len != sizeof(tag_mask)) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  // The const_cast for |data| can be removed if system NSS libraries are
-  // NSS 3.14.1 or later (NSS bug
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=808218).
-  if (PK11_CipherOp(ctx.get(), out, &output_len, max_len,
-                    const_cast<unsigned char*>(data), data_len) != SECSuccess) {
-    DVLOG(1) << "PK11_CipherOp failed";
-    return SECFailure;
-  }
-
-  if (PK11_Finalize(ctx.get()) != SECSuccess) {
-    DVLOG(1) << "PK11_Finalize failed";
-    return SECFailure;
-  }
-
-  if (static_cast<unsigned int>(output_len) != data_len) {
-    DVLOG(1) << "Wrong output length";
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-  }
-
-  if ((max_len - auth_tag_size) < static_cast<unsigned int>(output_len)) {
-    DVLOG(1) << "(max_len - kAuthTagSize) is less than output_len";
-    PORT_SetError(SEC_ERROR_OUTPUT_LEN);
-    return SECFailure;
-  }
-
-  crypto::GaloisHash ghash(ghash_key);
-  ghash.UpdateAdditional(gcm_params->pAAD, gcm_params->ulAADLen);
-  ghash.UpdateCiphertext(out, output_len);
-  ghash.Finish(out + output_len, auth_tag_size);
-  for (unsigned int i = 0; i < auth_tag_size; i++) {
-    out[output_len + i] ^= tag_mask[i];
-  }
-
-  *out_len = output_len + auth_tag_size;
-  return SECSuccess;
-}
-
-}  // namespace crypto
diff --git a/crypto/aes_128_gcm_helpers_nss.h b/crypto/aes_128_gcm_helpers_nss.h
deleted file mode 100644
index dadc56e..0000000
--- a/crypto/aes_128_gcm_helpers_nss.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CRYPTO_AES_128_GCM_HELPERS_NSS_H_
-#define CRYPTO_AES_128_GCM_HELPERS_NSS_H_
-
-#include <pk11pub.h>
-#include <secerr.h>
-
-#include "crypto/crypto_export.h"
-
-namespace crypto {
-
-// When using the CKM_AES_GCM mechanism, one must consider that the mechanism
-// had a bug in NSS 3.14.x (https://bugzilla.mozilla.org/show_bug.cgi?id=853285)
-// which also lacks the PK11_Decrypt and PK11_Encrypt functions.
-// (https://bugzilla.mozilla.org/show_bug.cgi?id=854063)
-//
-// While both these bugs were resolved in NSS 3.15, certain builds of Chromium
-// may still be loading older versions of NSS as the system libraries. These
-// helper methods emulate support by using CKM_AES_CTR and the GaloisHash.
-
-// Helper function for using PK11_Decrypt. |mechanism| must be set to
-// CKM_AES_GCM for this method.
-CRYPTO_EXPORT SECStatus PK11DecryptHelper(PK11SymKey* key,
-                                          CK_MECHANISM_TYPE mechanism,
-                                          SECItem* param,
-                                          unsigned char* out,
-                                          unsigned int* out_len,
-                                          unsigned int max_len,
-                                          const unsigned char* data,
-                                          unsigned int data_len);
-
-// Helper function for using PK11_Encrypt. |mechanism| must be set to
-// CKM_AES_GCM for this method.
-CRYPTO_EXPORT SECStatus PK11EncryptHelper(PK11SymKey* key,
-                                          CK_MECHANISM_TYPE mechanism,
-                                          SECItem* param,
-                                          unsigned char* out,
-                                          unsigned int* out_len,
-                                          unsigned int max_len,
-                                          const unsigned char* data,
-                                          unsigned int data_len);
-
-}  // namespace crypto
-
-#endif  // CRYPTO_AES_128_GCM_HELPERS_NSS_H_
diff --git a/crypto/aes_128_gcm_helpers_nss_unittest.cc b/crypto/aes_128_gcm_helpers_nss_unittest.cc
deleted file mode 100644
index d741b2f..0000000
--- a/crypto/aes_128_gcm_helpers_nss_unittest.cc
+++ /dev/null
@@ -1,580 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "crypto/aes_128_gcm_helpers_nss.h"
-
-#include <pk11pub.h>
-#include <secerr.h>
-#include <string>
-
-#include "base/logging.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "crypto/nss_util.h"
-#include "crypto/random.h"
-#include "crypto/scoped_nss_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace crypto {
-
-namespace {
-
-// The AES GCM test vectors come from the gcmDecrypt128.rsp and
-// gcmEncryptExtIV128.rsp files downloaded from
-// http://csrc.nist.gov/groups/STM/cavp/index.html on 2013-02-01. The test
-// vectors in that file look like this:
-//
-// [Keylen = 128]
-// [IVlen = 96]
-// [PTlen = 0]
-// [AADlen = 0]
-// [Taglen = 128]
-//
-// Count = 0
-// Key = cf063a34d4a9a76c2c86787d3f96db71
-// IV = 113b9785971864c83b01c787
-// CT =
-// AAD =
-// Tag = 72ac8493e3a5228b5d130a69d2510e42
-// PT =
-//
-// Count = 1
-// Key = a49a5e26a2f8cb63d05546c2a62f5343
-// IV = 907763b19b9b4ab6bd4f0281
-// CT =
-// AAD =
-// Tag = a2be08210d8c470a8df6e8fbd79ec5cf
-// FAIL
-//
-// ...
-//
-// These files are huge (2.6 MB and 2.8 MB), so this file contains just a
-// selection of test vectors.
-
-// Describes a group of test vectors that all have a given key length, IV
-// length, plaintext length, AAD length, and tag length.
-struct TestGroupInfo {
-  size_t key_len;
-  size_t iv_len;
-  size_t input_len;
-  size_t aad_len;
-  size_t tag_len;
-};
-
-// Each test vector consists of six strings of lowercase hexadecimal digits.
-// The strings may be empty (zero length). A test vector with a NULL |key|
-// marks the end of an array of test vectors.
-struct TestVector {
-  // Input:
-  const char* key;
-  const char* iv;
-  const char* input;
-  const char* aad;
-  const char* tag;
-
-  // Expected output:
-  const char* output;  // An empty string "" means decryption or encryption
-                       // succeeded and the plaintext is zero-length. NULL means
-                       // that the decryption or encryption failed.
-};
-
-const TestGroupInfo test_group_info[] = {
-    {128, 96, 0, 0, 128},
-    {128, 96, 0, 128, 128},
-    {128, 96, 128, 0, 128},
-    {128, 96, 408, 160, 128},
-    {128, 96, 408, 720, 128},
-    {128, 96, 104, 0, 128},
-};
-
-const TestVector decryption_test_group_0[] = {
-    {"cf063a34d4a9a76c2c86787d3f96db71",
-     "113b9785971864c83b01c787",
-     "",
-     "",
-     "72ac8493e3a5228b5d130a69d2510e42",
-     ""},
-    {
-     "a49a5e26a2f8cb63d05546c2a62f5343",
-     "907763b19b9b4ab6bd4f0281",
-     "",
-     "",
-     "a2be08210d8c470a8df6e8fbd79ec5cf",
-     NULL  // FAIL
-    },
-    {NULL}};
-
-const TestVector decryption_test_group_1[] = {
-    {
-     "d1f6af919cde85661208bdce0c27cb22",
-     "898c6929b435017bf031c3c5",
-     "",
-     "7c5faa40e636bbc91107e68010c92b9f",
-     "ae45f11777540a2caeb128be8092468a",
-     NULL  // FAIL
-    },
-    {"2370e320d4344208e0ff5683f243b213",
-     "04dbb82f044d30831c441228",
-     "",
-     "d43a8e5089eea0d026c03a85178b27da",
-     "2a049c049d25aa95969b451d93c31c6e",
-     ""},
-    {NULL}};
-
-const TestVector decryption_test_group_2[] = {
-    {"e98b72a9881a84ca6b76e0f43e68647a",
-     "8b23299fde174053f3d652ba",
-     "5a3c1cf1985dbb8bed818036fdd5ab42",
-     "",
-     "23c7ab0f952b7091cd324835043b5eb5",
-     "28286a321293253c3e0aa2704a278032"},
-    {"33240636cd3236165f1a553b773e728e",
-     "17c4d61493ecdc8f31700b12",
-     "47bb7e23f7bdfe05a8091ac90e4f8b2e",
-     "",
-     "b723c70e931d9785f40fd4ab1d612dc9",
-     "95695a5b12f2870b9cc5fdc8f218a97d"},
-    {
-     "5164df856f1e9cac04a79b808dc5be39",
-     "e76925d5355e0584ce871b2b",
-     "0216c899c88d6e32c958c7e553daa5bc",
-     "",
-     "a145319896329c96df291f64efbe0e3a",
-     NULL  // FAIL
-    },
-    {NULL}};
-
-const TestVector decryption_test_group_3[] = {
-    {"af57f42c60c0fc5a09adb81ab86ca1c3",
-     "a2dc01871f37025dc0fc9a79",
-     "b9a535864f48ea7b6b1367914978f9bfa087d854bb0e269bed8d279d2eea1210e48947"
-     "338b22f9bad09093276a331e9c79c7f4",
-     "41dc38988945fcb44faf2ef72d0061289ef8efd8",
-     "4f71e72bde0018f555c5adcce062e005",
-     "3803a0727eeb0ade441e0ec107161ded2d425ec0d102f21f51bf2cf9947c7ec4aa7279"
-     "5b2f69b041596e8817d0a3c16f8fadeb"},
-    {"ebc753e5422b377d3cb64b58ffa41b61",
-     "2e1821efaced9acf1f241c9b",
-     "069567190554e9ab2b50a4e1fbf9c147340a5025fdbd201929834eaf6532325899ccb9"
-     "f401823e04b05817243d2142a3589878",
-     "b9673412fd4f88ba0e920f46dd6438ff791d8eef",
-     "534d9234d2351cf30e565de47baece0b",
-     "39077edb35e9c5a4b1e4c2a6b9bb1fce77f00f5023af40333d6d699014c2bcf4209c18"
-     "353a18017f5b36bfc00b1f6dcb7ed485"},
-    {
-     "52bdbbf9cf477f187ec010589cb39d58",
-     "d3be36d3393134951d324b31",
-     "700188da144fa692cf46e4a8499510a53d90903c967f7f13e8a1bd8151a74adc4fe63e"
-     "32b992760b3a5f99e9a47838867000a9",
-     "93c4fc6a4135f54d640b0c976bf755a06a292c33",
-     "8ca4e38aa3dfa6b1d0297021ccf3ea5f",
-     NULL  // FAIL
-    },
-    {NULL}};
-
-const TestVector decryption_test_group_4[] = {
-    {"da2bb7d581493d692380c77105590201",
-     "44aa3e7856ca279d2eb020c6",
-     "9290d430c9e89c37f0446dbd620c9a6b34b1274aeb6f911f75867efcf95b6feda69f1a"
-     "f4ee16c761b3c9aeac3da03aa9889c88",
-     "4cd171b23bddb3a53cdf959d5c1710b481eb3785a90eb20a2345ee00d0bb7868c367ab"
-     "12e6f4dd1dee72af4eee1d197777d1d6499cc541f34edbf45cda6ef90b3c024f9272d7"
-     "2ec1909fb8fba7db88a4d6f7d3d925980f9f9f72",
-     "9e3ac938d3eb0cadd6f5c9e35d22ba38",
-     "9bbf4c1a2742f6ac80cb4e8a052e4a8f4f07c43602361355b717381edf9fabd4cb7e3a"
-     "d65dbd1378b196ac270588dd0621f642"},
-    {"d74e4958717a9d5c0e235b76a926cae8",
-     "0b7471141e0c70b1995fd7b1",
-     "e701c57d2330bf066f9ff8cf3ca4343cafe4894651cd199bdaaa681ba486b4a65c5a22"
-     "b0f1420be29ea547d42c713bc6af66aa",
-     "4a42b7aae8c245c6f1598a395316e4b8484dbd6e64648d5e302021b1d3fa0a38f46e22"
-     "bd9c8080b863dc0016482538a8562a4bd0ba84edbe2697c76fd039527ac179ec5506cf"
-     "34a6039312774cedebf4961f3978b14a26509f96",
-     "e192c23cb036f0b31592989119eed55d",
-     "840d9fb95e32559fb3602e48590280a172ca36d9b49ab69510f5bd552bfab7a306f85f"
-     "f0a34bc305b88b804c60b90add594a17"},
-    {
-     "1986310c725ac94ecfe6422e75fc3ee7",
-     "93ec4214fa8e6dc4e3afc775",
-     "b178ec72f85a311ac4168f42a4b2c23113fbea4b85f4b9dabb74e143eb1b8b0a361e02"
-     "43edfd365b90d5b325950df0ada058f9",
-     "e80b88e62c49c958b5e0b8b54f532d9ff6aa84c8a40132e93e55b59fc24e8decf28463"
-     "139f155d1e8ce4ee76aaeefcd245baa0fc519f83a5fb9ad9aa40c4b21126013f576c42"
-     "72c2cb136c8fd091cc4539877a5d1e72d607f960",
-     "8b347853f11d75e81e8a95010be81f17",
-     NULL  // FAIL
-    },
-    {NULL}};
-
-const TestVector decryption_test_group_5[] = {
-    {"387218b246c1a8257748b56980e50c94",
-     "dd7e014198672be39f95b69d",
-     "cdba9e73eaf3d38eceb2b04a8d",
-     "",
-     "ecf90f4a47c9c626d6fb2c765d201556",
-     "48f5b426baca03064554cc2b30"},
-    {"294de463721e359863887c820524b3d4",
-     "3338b35c9d57a5d28190e8c9",
-     "2f46634e74b8e4c89812ac83b9",
-     "",
-     "dabd506764e68b82a7e720aa18da0abe",
-     "46a2e55c8e264df211bd112685"},
-    {"28ead7fd2179e0d12aa6d5d88c58c2dc",
-     "5055347f18b4d5add0ae5c41",
-     "142d8210c3fb84774cdbd0447a",
-     "",
-     "5fd321d9cdb01952dc85f034736c2a7d",
-     "3b95b981086ee73cc4d0cc1422"},
-    {
-     "7d7b6c988137b8d470c57bf674a09c87",
-     "9edf2aa970d016ac962e1fd8",
-     "a85b66c3cb5eab91d5bdc8bc0e",
-     "",
-     "dc054efc01f3afd21d9c2484819f569a",
-     NULL  // FAIL
-    },
-    {NULL}};
-
-const TestVector encryption_test_group_0[] = {
-    {"11754cd72aec309bf52f7687212e8957",
-     "3c819d9a9bed087615030b65",
-     "",
-     "",
-     "250327c674aaf477aef2675748cf6971",
-     ""},
-    {"ca47248ac0b6f8372a97ac43508308ed",
-     "ffd2b598feabc9019262d2be",
-     "",
-     "",
-     "60d20404af527d248d893ae495707d1a",
-     ""},
-    {NULL}};
-
-const TestVector encryption_test_group_1[] = {
-    {"77be63708971c4e240d1cb79e8d77feb",
-     "e0e00f19fed7ba0136a797f3",
-     "",
-     "7a43ec1d9c0a5a78a0b16533a6213cab",
-     "209fcc8d3675ed938e9c7166709dd946",
-     ""},
-    {"7680c5d3ca6154758e510f4d25b98820",
-     "f8f105f9c3df4965780321f8",
-     "",
-     "c94c410194c765e3dcc7964379758ed3",
-     "94dca8edfcf90bb74b153c8d48a17930",
-     ""},
-    {NULL}};
-
-const TestVector encryption_test_group_2[] = {
-    {"7fddb57453c241d03efbed3ac44e371c",
-     "ee283a3fc75575e33efd4887",
-     "d5de42b461646c255c87bd2962d3b9a2",
-     "",
-     "b36d1df9b9d5e596f83e8b7f52971cb3",
-     "2ccda4a5415cb91e135c2a0f78c9b2fd"},
-    {"ab72c77b97cb5fe9a382d9fe81ffdbed",
-     "54cc7dc2c37ec006bcc6d1da",
-     "007c5e5b3e59df24a7c355584fc1518d",
-     "",
-     "2b4401346697138c7a4891ee59867d0c",
-     "0e1bde206a07a9c2c1b65300f8c64997"},
-    {NULL}};
-
-const TestVector encryption_test_group_3[] = {
-    {"fe47fcce5fc32665d2ae399e4eec72ba",
-     "5adb9609dbaeb58cbd6e7275",
-     "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1"
-     "b840382c4bccaf3bafb4ca8429bea063",
-     "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a",
-     "291ef1982e4defedaa2249f898556b47",
-     "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf539304373636525"
-     "3ddbc5db8778371495da76d269e5db3e"},
-    {"ec0c2ba17aa95cd6afffe949da9cc3a8",
-     "296bce5b50b7d66096d627ef",
-     "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987"
-     "b764b9611f6c0f8641843d5d58f3a242",
-     "f8d00f05d22bf68599bcdeb131292ad6e2df5d14",
-     "890147971946b627c40016da1ecf3e77",
-     "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a0716299"
-     "5506fde6309ffc19e716eddf1a828c5a"},
-    {NULL}};
-
-const TestVector encryption_test_group_4[] = {
-    {"2c1f21cf0f6fb3661943155c3e3d8492",
-     "23cb5ff362e22426984d1907",
-     "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d6"
-     "8b5615ba7c1220ff6510e259f06655d8",
-     "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e"
-     "3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f"
-     "4488f33cfb5e979e42b6e1cfc0a60238982a7aec",
-     "57a3ee28136e94c74838997ae9823f3a",
-     "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222"
-     "b6ad57af43e1895df9dca2a5344a62cc"},
-    {"d9f7d2411091f947b4d6f1e2d1f0fb2e",
-     "e1934f5db57cc983e6b180e7",
-     "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490"
-     "c2c6f6166f4a59431e182663fcaea05a",
-     "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d"
-     "0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a201"
-     "15d2e51398344b16bee1ed7c499b353d6c597af8",
-     "21b51ca862cb637cdd03b99a0f93b134",
-     "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d57"
-     "3c7891c2a91fbc48db29967ec9542b23"},
-    {NULL}};
-
-const TestVector encryption_test_group_5[] = {
-    {"fe9bb47deb3a61e423c2231841cfd1fb",
-     "4d328eb776f500a2f7fb47aa",
-     "f1cc3818e421876bb6b8bbd6c9",
-     "",
-     "43fd4727fe5cdb4b5b42818dea7ef8c9",
-     "b88c5c1977b35b517b0aeae967"},
-    {"6703df3701a7f54911ca72e24dca046a",
-     "12823ab601c350ea4bc2488c",
-     "793cd125b0b84a043e3ac67717",
-     "",
-     "38e6bcd29962e5f2c13626b85a877101",
-     "b2051c80014f42f08735a7b0cd"},
-    {NULL}};
-
-const TestVector* const decryption_test_group_array[] = {
-    decryption_test_group_0,
-    decryption_test_group_1,
-    decryption_test_group_2,
-    decryption_test_group_3,
-    decryption_test_group_4,
-    decryption_test_group_5,
-};
-
-const TestVector* const encryption_test_group_array[] = {
-    encryption_test_group_0,
-    encryption_test_group_1,
-    encryption_test_group_2,
-    encryption_test_group_3,
-    encryption_test_group_4,
-    encryption_test_group_5,
-};
-
-bool DecodeHexString(const base::StringPiece& hex, std::string* bytes) {
-  bytes->clear();
-  if (hex.empty())
-    return true;
-  std::vector<uint8> v;
-  if (!base::HexStringToBytes(hex.as_string(), &v))
-    return false;
-  if (!v.empty())
-    bytes->assign(reinterpret_cast<const char*>(&v[0]), v.size());
-  return true;
-}
-
-class Aes128GcmHelpersTest : public ::testing::Test {
- public:
-  enum Mode { DECRYPT, ENCRYPT };
-
-  void SetUp() override { EnsureNSSInit(); }
-
-  bool DecryptOrEncrypt(Mode mode,
-                        const base::StringPiece& input,
-                        const base::StringPiece& key,
-                        const base::StringPiece& nonce,
-                        const base::StringPiece& aad,
-                        size_t auth_tag_size,
-                        std::string* output) {
-    DCHECK(output);
-
-    const CK_ATTRIBUTE_TYPE cka_mode =
-        mode == DECRYPT ? CKA_DECRYPT : CKA_ENCRYPT;
-
-    SECItem key_item;
-    key_item.type = siBuffer;
-    key_item.data = const_cast<unsigned char*>(
-        reinterpret_cast<const unsigned char*>(key.data()));
-    key_item.len = key.size();
-
-    crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
-    DCHECK(slot);
-
-    crypto::ScopedPK11SymKey aead_key(
-        PK11_ImportSymKey(slot.get(), CKM_AES_GCM, PK11_OriginUnwrap, cka_mode,
-                          &key_item, nullptr));
-
-    CK_GCM_PARAMS gcm_params;
-    gcm_params.pIv = const_cast<unsigned char*>(
-        reinterpret_cast<const unsigned char*>(nonce.data()));
-    gcm_params.ulIvLen = nonce.size();
-
-    gcm_params.pAAD = const_cast<unsigned char*>(
-        reinterpret_cast<const unsigned char*>(aad.data()));
-
-    gcm_params.ulAADLen = aad.size();
-
-    gcm_params.ulTagBits = auth_tag_size * 8;
-
-    SECItem param;
-    param.type = siBuffer;
-    param.data = reinterpret_cast<unsigned char*>(&gcm_params);
-    param.len = sizeof(CK_GCM_PARAMS);
-
-    size_t maximum_output_length = input.size();
-    if (mode == ENCRYPT)
-      maximum_output_length += auth_tag_size;
-
-    unsigned int output_length = 0;
-    unsigned char* raw_input = const_cast<unsigned char*>(
-        reinterpret_cast<const unsigned char*>(input.data()));
-    unsigned char* raw_output = reinterpret_cast<unsigned char*>(
-        base::WriteInto(output, maximum_output_length + 1 /* null */));
-
-    PK11Helper_TransformFunction* transform_function =
-        mode == DECRYPT ? PK11DecryptHelper : PK11EncryptHelper;
-
-    const SECStatus result = transform_function(
-        aead_key.get(), CKM_AES_GCM, &param, raw_output, &output_length,
-        maximum_output_length, raw_input, input.size());
-
-    if (result != SECSuccess)
-      return false;
-
-    const size_t expected_output_length = mode == DECRYPT
-                                              ? input.size() - auth_tag_size
-                                              : input.size() + auth_tag_size;
-
-    EXPECT_EQ(expected_output_length, output_length);
-
-    output->resize(expected_output_length);
-    return true;
-  }
-
- private:
-  // The prototype of PK11_Decrypt and PK11_Encrypt.
-  using PK11Helper_TransformFunction = SECStatus(PK11SymKey* symKey,
-                                                 CK_MECHANISM_TYPE mechanism,
-                                                 SECItem* param,
-                                                 unsigned char* out,
-                                                 unsigned int* outLen,
-                                                 unsigned int maxLen,
-                                                 const unsigned char* data,
-                                                 unsigned int dataLen);
-};
-
-}  // namespace
-
-TEST_F(Aes128GcmHelpersTest, RoundTrip) {
-  const std::string message = "Hello, world!";
-
-  const size_t kKeySize = 16;
-  const size_t kNonceSize = 16;
-
-  std::string key, nonce;
-  RandBytes(base::WriteInto(&key, kKeySize + 1), kKeySize);
-  RandBytes(base::WriteInto(&nonce, kNonceSize + 1), kNonceSize);
-
-  // AEAD_AES_128_GCM is defined with a default authentication tag size of 16,
-  // but RFC 5282 extends this to authentication tag sizes of 8 and 12 as well.
-  size_t auth_tag_size = base::RandInt(2, 4) * 4;
-
-  std::string encrypted;
-  ASSERT_TRUE(DecryptOrEncrypt(ENCRYPT, message, key, nonce,
-                               base::StringPiece(), auth_tag_size, &encrypted));
-
-  std::string decrypted;
-  ASSERT_TRUE(DecryptOrEncrypt(DECRYPT, encrypted, key, nonce,
-                               base::StringPiece(), auth_tag_size, &decrypted));
-
-  EXPECT_EQ(message, decrypted);
-}
-
-TEST_F(Aes128GcmHelpersTest, DecryptionVectors) {
-  for (size_t i = 0; i < arraysize(decryption_test_group_array); i++) {
-    SCOPED_TRACE(i);
-    const TestVector* test_vectors = decryption_test_group_array[i];
-    const TestGroupInfo& test_info = test_group_info[i];
-
-    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
-      // If not present then decryption is expected to fail.
-      bool has_output = test_vectors[j].output;
-
-      // Decode the test vector.
-      std::string key, iv, input, aad, tag, expected_output;
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag));
-      if (has_output)
-        ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output));
-
-      // The test vector's lengths should look sane. Note that the lengths
-      // in |test_info| are in bits.
-      EXPECT_EQ(test_info.key_len, key.length() * 8);
-      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
-      EXPECT_EQ(test_info.input_len, input.length() * 8);
-      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
-      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
-      if (has_output)
-        EXPECT_EQ(test_info.input_len, expected_output.length() * 8);
-
-      const std::string ciphertext = input + tag;
-      std::string output;
-
-      if (!DecryptOrEncrypt(DECRYPT, ciphertext, key, iv, aad, tag.length(),
-                            &output)) {
-        EXPECT_FALSE(has_output);
-        continue;
-      }
-
-      EXPECT_TRUE(has_output);
-      EXPECT_EQ(expected_output, output);
-    }
-  }
-}
-
-TEST_F(Aes128GcmHelpersTest, EncryptionVectors) {
-  for (size_t i = 0; i < arraysize(encryption_test_group_array); i++) {
-    SCOPED_TRACE(i);
-    const TestVector* test_vectors = encryption_test_group_array[i];
-    const TestGroupInfo& test_info = test_group_info[i];
-
-    for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
-      // If not present then decryption is expected to fail.
-      bool has_output = test_vectors[j].output;
-
-      // Decode the test vector.
-      std::string key, iv, input, aad, tag, expected_output;
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].key, &key));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].iv, &iv));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].input, &input));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].aad, &aad));
-      ASSERT_TRUE(DecodeHexString(test_vectors[j].tag, &tag));
-      if (has_output)
-        ASSERT_TRUE(DecodeHexString(test_vectors[j].output, &expected_output));
-
-      // The test vector's lengths should look sane. Note that the lengths
-      // in |test_info| are in bits.
-      EXPECT_EQ(test_info.key_len, key.length() * 8);
-      EXPECT_EQ(test_info.iv_len, iv.length() * 8);
-      EXPECT_EQ(test_info.input_len, input.length() * 8);
-      EXPECT_EQ(test_info.aad_len, aad.length() * 8);
-      EXPECT_EQ(test_info.tag_len, tag.length() * 8);
-      if (has_output)
-        EXPECT_EQ(test_info.input_len, expected_output.length() * 8);
-
-      std::string output;
-
-      if (!DecryptOrEncrypt(ENCRYPT, input, key, iv, aad, tag.length(),
-                            &output)) {
-        EXPECT_FALSE(has_output);
-        continue;
-      }
-
-      const std::string expected_output_with_tag = expected_output + tag;
-
-      EXPECT_TRUE(has_output);
-      EXPECT_EQ(expected_output_with_tag, output);
-    }
-  }
-}
-
-}  // namespace crypto
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 5153fa83..c1c1047c4 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -103,8 +103,6 @@
             # TODO(joth): Use a glob to match exclude patterns once the
             #             OpenSSL file set is complete.
             'sources!': [
-              'aes_128_gcm_helpers_nss.cc',
-              'aes_128_gcm_helpers_nss.h',
               'ec_private_key_nss.cc',
               'ec_signature_creator_nss.cc',
               'encryptor_nss.cc',
@@ -164,7 +162,6 @@
       'type': 'executable',
       'sources': [
         'aead_openssl_unittest.cc',
-        'aes_128_gcm_helpers_nss_unittest.cc',
         'curve25519_unittest.cc',
         'ec_private_key_unittest.cc',
         'ec_signature_creator_unittest.cc',
@@ -229,9 +226,6 @@
           'dependencies': [
             '../third_party/boringssl/boringssl.gyp:boringssl',
           ],
-          'sources!': [
-            'aes_128_gcm_helpers_nss_unittest.cc',
-          ],
         }, {
           'sources!': [
             'openssl_bio_string_unittest.cc',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index 71ffbec..73b3332 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -29,8 +29,6 @@
       '<@(hmac_win64_related_sources)',
       'aead_openssl.cc',
       'aead_openssl.h',
-      'aes_128_gcm_helpers_nss.cc',
-      'aes_128_gcm_helpers_nss.h',
       'apple_keychain.h',
       'apple_keychain_ios.mm',
       'apple_keychain_mac.mm',
diff --git a/dbus/property.cc b/dbus/property.cc
index b7a0c8b..234036c3 100644
--- a/dbus/property.cc
+++ b/dbus/property.cc
@@ -133,6 +133,35 @@
     callback.Run(response);
 }
 
+bool PropertySet::GetAndBlock(PropertyBase* property) {
+  MethodCall method_call(kPropertiesInterface, kPropertiesGet);
+  MessageWriter writer(&method_call);
+  writer.AppendString(interface());
+  writer.AppendString(property->name());
+
+  DCHECK(object_proxy_);
+  scoped_ptr<dbus::Response> response(
+      object_proxy_->CallMethodAndBlock(&method_call,
+                                        ObjectProxy::TIMEOUT_USE_DEFAULT));
+
+  if (!response.get()) {
+    LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
+    return false;
+  }
+
+  MessageReader reader(response.get());
+  if (property->PopValueFromReader(&reader)) {
+    property->set_valid(true);
+    NotifyPropertyChanged(property->name());
+  } else {
+    if (property->is_valid()) {
+      property->set_valid(false);
+      NotifyPropertyChanged(property->name());
+    }
+  }
+  return true;
+}
+
 void PropertySet::GetAll() {
   MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
   MessageWriter writer(&method_call);
@@ -184,7 +213,7 @@
   DCHECK(object_proxy_);
   scoped_ptr<dbus::Response> response(
       object_proxy_->CallMethodAndBlock(&method_call,
-      ObjectProxy::TIMEOUT_USE_DEFAULT));
+                                        ObjectProxy::TIMEOUT_USE_DEFAULT));
   if (response.get())
     return true;
   return false;
diff --git a/dbus/property.h b/dbus/property.h
index 940ef715d..e379f8a 100644
--- a/dbus/property.h
+++ b/dbus/property.h
@@ -259,6 +259,10 @@
   virtual void OnGet(PropertyBase* property, GetCallback callback,
                      Response* response);
 
+  // The synchronous version of Get().
+  // This should never be used on an interactive thread.
+  virtual bool GetAndBlock(PropertyBase* property);
+
   // Queries the remote object for values of all properties and updates
   // initial values. Sub-classes may override to use a different D-Bus
   // method, or if the remote object does not support retrieving all
@@ -276,11 +280,13 @@
   // depending on the remote object. This method may be overridden by
   // sub-classes if interfaces use different method calls.
   virtual void Set(PropertyBase* property, SetCallback callback);
-  // The sychronous version of Set().
-  virtual bool SetAndBlock(PropertyBase* property);
   virtual void OnSet(PropertyBase* property, SetCallback callback,
                      Response* response);
 
+  // The synchronous version of Set().
+  // This should never be used on an interactive thread.
+  virtual bool SetAndBlock(PropertyBase* property);
+
   // Update properties by reading an array of dictionary entries, each
   // containing a string with the name and a variant with the value, from
   // |message_reader|. Returns false if message is in incorrect format.
@@ -382,6 +388,12 @@
     property_set()->Get(this, callback);
   }
 
+  // The synchronous version of Get().
+  // This should never be used on an interactive thread.
+  virtual bool GetAndBlock() {
+    return property_set()->GetAndBlock(this);
+  }
+
   // Requests that the remote object change the property value to |value|,
   // |callback| will be called to indicate the success or failure of the
   // request, however the new value may not be available depending on the
@@ -391,7 +403,8 @@
     property_set()->Set(this, callback);
   }
 
-  // The sychronous version of Set().
+  // The synchronous version of Set().
+  // This should never be used on an interactive thread.
   virtual bool SetAndBlock(const T& value) {
     set_value_ = value;
     return property_set()->SetAndBlock(this);
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 4961292c..6c8277a 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -112,6 +112,8 @@
     sources += [
       "devices_app/usb/device_impl_unittest.cc",
       "devices_app/usb/device_manager_impl_unittest.cc",
+      "devices_app/usb/fake_permission_provider.cc",
+      "devices_app/usb/fake_permission_provider.h",
       "test/test_device_client.cc",
       "test/test_device_client.h",
       "test/usb_test_gadget_impl.cc",
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn
index cb8f2935..69da108 100644
--- a/device/bluetooth/BUILD.gn
+++ b/device/bluetooth/BUILD.gn
@@ -157,6 +157,95 @@
   if (is_win) {
     libs = [ "setupapi.lib" ]
   }
+
+  # This block will also build for Linux once we write the linux
+  # implementation of BluezDbusManager.
+  if (is_chromeos) {
+    defines += [ "DEVICE_BLUETOOTH_IMPLEMENTATION" ]
+    sources += [
+      "dbus/bluetooth_adapter_client.cc",
+      "dbus/bluetooth_adapter_client.h",
+      "dbus/bluetooth_agent_manager_client.cc",
+      "dbus/bluetooth_agent_manager_client.h",
+      "dbus/bluetooth_agent_service_provider.cc",
+      "dbus/bluetooth_agent_service_provider.h",
+      "dbus/bluetooth_dbus_client_bundle.cc",
+      "dbus/bluetooth_dbus_client_bundle.h",
+      "dbus/bluetooth_device_client.cc",
+      "dbus/bluetooth_device_client.h",
+      "dbus/bluetooth_gatt_characteristic_client.cc",
+      "dbus/bluetooth_gatt_characteristic_client.h",
+      "dbus/bluetooth_gatt_characteristic_service_provider.cc",
+      "dbus/bluetooth_gatt_characteristic_service_provider.h",
+      "dbus/bluetooth_gatt_descriptor_client.cc",
+      "dbus/bluetooth_gatt_descriptor_client.h",
+      "dbus/bluetooth_gatt_descriptor_service_provider.cc",
+      "dbus/bluetooth_gatt_descriptor_service_provider.h",
+      "dbus/bluetooth_gatt_manager_client.cc",
+      "dbus/bluetooth_gatt_manager_client.h",
+      "dbus/bluetooth_gatt_service_client.cc",
+      "dbus/bluetooth_gatt_service_client.h",
+      "dbus/bluetooth_gatt_service_service_provider.cc",
+      "dbus/bluetooth_gatt_service_service_provider.h",
+      "dbus/bluetooth_input_client.cc",
+      "dbus/bluetooth_input_client.h",
+      "dbus/bluetooth_le_advertisement_service_provider.cc",
+      "dbus/bluetooth_le_advertisement_service_provider.h",
+      "dbus/bluetooth_le_advertising_manager_client.cc",
+      "dbus/bluetooth_le_advertising_manager_client.h",
+      "dbus/bluetooth_media_client.cc",
+      "dbus/bluetooth_media_client.h",
+      "dbus/bluetooth_media_endpoint_service_provider.cc",
+      "dbus/bluetooth_media_endpoint_service_provider.h",
+      "dbus/bluetooth_media_transport_client.cc",
+      "dbus/bluetooth_media_transport_client.h",
+      "dbus/bluetooth_profile_manager_client.cc",
+      "dbus/bluetooth_profile_manager_client.h",
+      "dbus/bluetooth_profile_service_provider.cc",
+      "dbus/bluetooth_profile_service_provider.h",
+      "dbus/bluez_dbus_client.h",
+      "dbus/bluez_dbus_manager.cc",
+      "dbus/bluez_dbus_manager.h",
+      "dbus/fake_bluetooth_adapter_client.cc",
+      "dbus/fake_bluetooth_adapter_client.h",
+      "dbus/fake_bluetooth_agent_manager_client.cc",
+      "dbus/fake_bluetooth_agent_manager_client.h",
+      "dbus/fake_bluetooth_agent_service_provider.cc",
+      "dbus/fake_bluetooth_agent_service_provider.h",
+      "dbus/fake_bluetooth_device_client.cc",
+      "dbus/fake_bluetooth_device_client.h",
+      "dbus/fake_bluetooth_gatt_characteristic_client.cc",
+      "dbus/fake_bluetooth_gatt_characteristic_client.h",
+      "dbus/fake_bluetooth_gatt_characteristic_service_provider.cc",
+      "dbus/fake_bluetooth_gatt_characteristic_service_provider.h",
+      "dbus/fake_bluetooth_gatt_descriptor_client.cc",
+      "dbus/fake_bluetooth_gatt_descriptor_client.h",
+      "dbus/fake_bluetooth_gatt_descriptor_service_provider.cc",
+      "dbus/fake_bluetooth_gatt_descriptor_service_provider.h",
+      "dbus/fake_bluetooth_gatt_manager_client.cc",
+      "dbus/fake_bluetooth_gatt_manager_client.h",
+      "dbus/fake_bluetooth_gatt_service_client.cc",
+      "dbus/fake_bluetooth_gatt_service_client.h",
+      "dbus/fake_bluetooth_gatt_service_service_provider.cc",
+      "dbus/fake_bluetooth_gatt_service_service_provider.h",
+      "dbus/fake_bluetooth_input_client.cc",
+      "dbus/fake_bluetooth_input_client.h",
+      "dbus/fake_bluetooth_le_advertisement_service_provider.cc",
+      "dbus/fake_bluetooth_le_advertisement_service_provider.h",
+      "dbus/fake_bluetooth_le_advertising_manager_client.cc",
+      "dbus/fake_bluetooth_le_advertising_manager_client.h",
+      "dbus/fake_bluetooth_media_client.cc",
+      "dbus/fake_bluetooth_media_client.h",
+      "dbus/fake_bluetooth_media_endpoint_service_provider.cc",
+      "dbus/fake_bluetooth_media_endpoint_service_provider.h",
+      "dbus/fake_bluetooth_media_transport_client.cc",
+      "dbus/fake_bluetooth_media_transport_client.h",
+      "dbus/fake_bluetooth_profile_manager_client.cc",
+      "dbus/fake_bluetooth_profile_manager_client.h",
+      "dbus/fake_bluetooth_profile_service_provider.cc",
+      "dbus/fake_bluetooth_profile_service_provider.h",
+    ]
+  }
 }
 
 static_library("mocks") {
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
index 925d78f..fc76c32 100644
--- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
+++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
@@ -27,7 +27,7 @@
 final class ChromeBluetoothDevice {
     private static final String TAG = "Bluetooth";
 
-    private final long mNativeBluetoothDeviceAndroid;
+    private long mNativeBluetoothDeviceAndroid;
     final Wrappers.BluetoothDeviceWrapper mDevice;
     private List<ParcelUuid> mUuidsFromScan;
     Wrappers.BluetoothGattWrapper mBluetoothGatt;
@@ -41,6 +41,15 @@
         Log.v(TAG, "ChromeBluetoothDevice created.");
     }
 
+    /**
+     * Handles C++ object being destroyed.
+     */
+    @CalledByNative
+    private void onBluetoothDeviceAndroidDestruction() {
+        disconnectGatt();
+        mNativeBluetoothDeviceAndroid = 0;
+    }
+
     // ---------------------------------------------------------------------------------------------
     // BluetoothDeviceAndroid methods implemented in java:
 
@@ -112,7 +121,7 @@
     @CalledByNative
     private void disconnectGatt() {
         Log.i(TAG, "BluetoothGatt.disconnect");
-        mBluetoothGatt.disconnect();
+        if (mBluetoothGatt != null) mBluetoothGatt.disconnect();
     }
 
     // Implements BluetoothDeviceAndroid::GetDeviceName.
@@ -129,8 +138,10 @@
                     (newState == android.bluetooth.BluetoothProfile.STATE_CONNECTED)
                             ? "Connected"
                             : "Disconnected");
-            nativeOnConnectionStateChange(mNativeBluetoothDeviceAndroid, status,
-                    newState == android.bluetooth.BluetoothProfile.STATE_CONNECTED);
+            if (mNativeBluetoothDeviceAndroid != 0) {
+                nativeOnConnectionStateChange(mNativeBluetoothDeviceAndroid, status,
+                        newState == android.bluetooth.BluetoothProfile.STATE_CONNECTED);
+            }
         }
     }
 
diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp
index 881a160..5e4e821 100644
--- a/device/bluetooth/bluetooth.gyp
+++ b/device/bluetooth/bluetooth.gyp
@@ -129,6 +129,96 @@
         'bluetooth_uuid.h',
       ],
       'conditions': [
+        # This block will also build for Linux once we write the linux
+        # implementation of BluezDbusManager.
+        ['chromeos==1', {
+         'defines': [
+            'DEVICE_BLUETOOTH_IMPLEMENTATION',
+          ],
+          'sources': [
+            'dbus/bluetooth_adapter_client.cc',
+            'dbus/bluetooth_adapter_client.h',
+            'dbus/bluetooth_le_advertising_manager_client.cc',
+            'dbus/bluetooth_le_advertising_manager_client.h',
+            'dbus/bluetooth_le_advertisement_service_provider.cc',
+            'dbus/bluetooth_le_advertisement_service_provider.h',
+            'dbus/bluetooth_agent_manager_client.cc',
+            'dbus/bluetooth_agent_manager_client.h',
+            'dbus/bluetooth_agent_service_provider.cc',
+            'dbus/bluetooth_agent_service_provider.h',
+            'dbus/bluetooth_dbus_client_bundle.cc',
+            'dbus/bluetooth_dbus_client_bundle.h',
+            'dbus/bluetooth_device_client.cc',
+            'dbus/bluetooth_device_client.h',
+            'dbus/bluetooth_gatt_characteristic_client.cc',
+            'dbus/bluetooth_gatt_characteristic_client.h',
+            'dbus/bluetooth_gatt_characteristic_service_provider.cc',
+            'dbus/bluetooth_gatt_characteristic_service_provider.h',
+            'dbus/bluetooth_gatt_descriptor_client.cc',
+            'dbus/bluetooth_gatt_descriptor_client.h',
+            'dbus/bluetooth_gatt_descriptor_service_provider.cc',
+            'dbus/bluetooth_gatt_descriptor_service_provider.h',
+            'dbus/bluetooth_gatt_manager_client.cc',
+            'dbus/bluetooth_gatt_manager_client.h',
+            'dbus/bluetooth_gatt_service_client.cc',
+            'dbus/bluetooth_gatt_service_client.h',
+            'dbus/bluetooth_gatt_service_service_provider.cc',
+            'dbus/bluetooth_gatt_service_service_provider.h',
+            'dbus/bluetooth_input_client.cc',
+            'dbus/bluetooth_input_client.h',
+            'dbus/bluetooth_media_client.cc',
+            'dbus/bluetooth_media_client.h',
+            'dbus/bluetooth_media_endpoint_service_provider.cc',
+            'dbus/bluetooth_media_endpoint_service_provider.h',
+            'dbus/bluetooth_media_transport_client.cc',
+            'dbus/bluetooth_media_transport_client.h',
+            'dbus/bluetooth_profile_manager_client.cc',
+            'dbus/bluetooth_profile_manager_client.h',
+            'dbus/bluetooth_profile_service_provider.cc',
+            'dbus/bluetooth_profile_service_provider.h',
+            'dbus/bluez_dbus_client.h',
+            'dbus/bluez_dbus_manager.cc',
+            'dbus/bluez_dbus_manager.h',
+            'dbus/fake_bluetooth_adapter_client.cc',
+            'dbus/fake_bluetooth_adapter_client.h',
+            'dbus/fake_bluetooth_le_advertising_manager_client.cc',
+            'dbus/fake_bluetooth_le_advertising_manager_client.h',
+            'dbus/fake_bluetooth_le_advertisement_service_provider.cc',
+            'dbus/fake_bluetooth_le_advertisement_service_provider.h',
+            'dbus/fake_bluetooth_agent_manager_client.cc',
+            'dbus/fake_bluetooth_agent_manager_client.h',
+            'dbus/fake_bluetooth_agent_service_provider.cc',
+            'dbus/fake_bluetooth_agent_service_provider.h',
+            'dbus/fake_bluetooth_device_client.cc',
+            'dbus/fake_bluetooth_device_client.h',
+            'dbus/fake_bluetooth_gatt_characteristic_client.cc',
+            'dbus/fake_bluetooth_gatt_characteristic_client.h',
+            'dbus/fake_bluetooth_gatt_characteristic_service_provider.cc',
+            'dbus/fake_bluetooth_gatt_characteristic_service_provider.h',
+            'dbus/fake_bluetooth_gatt_descriptor_client.cc',
+            'dbus/fake_bluetooth_gatt_descriptor_client.h',
+            'dbus/fake_bluetooth_gatt_descriptor_service_provider.cc',
+            'dbus/fake_bluetooth_gatt_descriptor_service_provider.h',
+            'dbus/fake_bluetooth_gatt_manager_client.cc',
+            'dbus/fake_bluetooth_gatt_manager_client.h',
+            'dbus/fake_bluetooth_gatt_service_client.cc',
+            'dbus/fake_bluetooth_gatt_service_client.h',
+            'dbus/fake_bluetooth_gatt_service_service_provider.cc',
+            'dbus/fake_bluetooth_gatt_service_service_provider.h',
+            'dbus/fake_bluetooth_input_client.cc',
+            'dbus/fake_bluetooth_input_client.h',
+            'dbus/fake_bluetooth_media_client.cc',
+            'dbus/fake_bluetooth_media_client.h',
+            'dbus/fake_bluetooth_media_endpoint_service_provider.cc',
+            'dbus/fake_bluetooth_media_endpoint_service_provider.h',
+            'dbus/fake_bluetooth_media_transport_client.cc',
+            'dbus/fake_bluetooth_media_transport_client.h',
+            'dbus/fake_bluetooth_profile_manager_client.cc',
+            'dbus/fake_bluetooth_profile_manager_client.h',
+            'dbus/fake_bluetooth_profile_service_provider.cc',
+            'dbus/fake_bluetooth_profile_service_provider.h',
+          ],
+        }],
         ['chromeos==1', {
           'dependencies': [
             '../../build/linux/system.gyp:dbus',
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.cc b/device/bluetooth/bluetooth_adapter_chromeos.cc
index 1ba14a58b..15f30bf 100644
--- a/device/bluetooth/bluetooth_adapter_chromeos.cc
+++ b/device/bluetooth/bluetooth_adapter_chromeos.cc
@@ -13,12 +13,6 @@
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
-#include "chromeos/dbus/bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/system/devicetype.h"
 #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h"
 #include "device/bluetooth/bluetooth_advertisement_chromeos.h"
@@ -33,6 +27,12 @@
 #include "device/bluetooth/bluetooth_socket_chromeos.h"
 #include "device/bluetooth/bluetooth_socket_thread.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 using device::BluetoothAdapter;
@@ -61,9 +61,9 @@
 
 UMABluetoothDiscoverySessionOutcome TranslateDiscoveryErrorToUMA(
     const std::string& error_name) {
-  if (error_name == chromeos::BluetoothAdapterClient::kUnknownAdapterError) {
+  if (error_name == bluez::BluetoothAdapterClient::kUnknownAdapterError) {
     return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_UNKNOWN_ADAPTER;
-  } else if (error_name == chromeos::BluetoothAdapterClient::kNoResponseError) {
+  } else if (error_name == bluez::BluetoothAdapterClient::kNoResponseError) {
     return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_NO_RESPONSE;
   } else if (error_name == bluetooth_device::kErrorInProgress) {
     return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_IN_PROGRESS;
@@ -100,9 +100,9 @@
 void BluetoothAdapterChromeOS::Shutdown() {
   if (dbus_is_shutdown_)
     return;
-  DCHECK(DBusThreadManager::IsInitialized())
+  DCHECK(bluez::BluezDBusManager::IsInitialized())
       << "Call BluetoothAdapterFactory::Shutdown() before "
-         "DBusThreadManager::Shutdown().";
+         "BluezDBusManager::Shutdown().";
 
   if (IsPresent())
     RemoveAdapter();  // Also deletes devices_.
@@ -115,14 +115,19 @@
     delete it.second;
   profile_queues_.clear();
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this);
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
-  DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(
+      this);
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(
+      this);
+  bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->RemoveObserver(
+      this);
 
   VLOG(1) << "Unregistering pairing agent";
-  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->UnregisterAgent(
-      dbus::ObjectPath(kAgentPath), base::Bind(&base::DoNothing),
-      base::Bind(&OnUnregisterAgentError));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAgentManagerClient()
+      ->UnregisterAgent(dbus::ObjectPath(kAgentPath),
+                        base::Bind(&base::DoNothing),
+                        base::Bind(&OnUnregisterAgentError));
 
   agent_.reset();
   dbus_is_shutdown_ = true;
@@ -136,18 +141,20 @@
   ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
   socket_thread_ = device::BluetoothSocketThread::Get();
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this);
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
-  DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->AddObserver(
+      this);
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->AddObserver(this);
 
   // Register the pairing agent.
-  dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
-  agent_.reset(BluetoothAgentServiceProvider::Create(
+  dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
+  agent_.reset(bluez::BluetoothAgentServiceProvider::Create(
       system_bus, dbus::ObjectPath(kAgentPath), this));
   DCHECK(agent_.get());
 
-  std::vector<dbus::ObjectPath> object_paths =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters();
+  std::vector<dbus::ObjectPath> object_paths = bluez::BluezDBusManager::Get()
+                                                   ->GetBluetoothAdapterClient()
+                                                   ->GetAdapters();
 
   if (!object_paths.empty()) {
     VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available.";
@@ -163,9 +170,10 @@
   if (!IsPresent())
     return std::string();
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
 
   return BluetoothDevice::CanonicalizeAddress(properties->address.value());
@@ -175,9 +183,10 @@
   if (!IsPresent())
     return std::string();
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
 
   return properties->alias.value();
@@ -191,13 +200,13 @@
     return;
   }
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-      GetProperties(object_path_)->alias.Set(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAdapterClient()
+      ->GetProperties(object_path_)
+      ->alias.Set(
           name,
           base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback,
-                     error_callback));
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
 }
 
 bool BluetoothAdapterChromeOS::IsInitialized() const {
@@ -212,9 +221,10 @@
   if (!IsPresent())
     return false;
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   return properties->powered.value();
 }
@@ -228,22 +238,23 @@
     return;
   }
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-      GetProperties(object_path_)->powered.Set(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAdapterClient()
+      ->GetProperties(object_path_)
+      ->powered.Set(
           powered,
           base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback,
-                     error_callback));
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
 }
 
 bool BluetoothAdapterChromeOS::IsDiscoverable() const {
   if (!IsPresent())
     return false;
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   return properties->discoverable.value();
 }
@@ -257,22 +268,23 @@
     return;
   }
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-      GetProperties(object_path_)->discoverable.Set(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAdapterClient()
+      ->GetProperties(object_path_)
+      ->discoverable.Set(
           discoverable,
           base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback,
-                     error_callback));
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
 }
 
 bool BluetoothAdapterChromeOS::IsDiscovering() const {
   if (!IsPresent())
     return false;
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   return properties->discovering.value();
 }
@@ -377,9 +389,10 @@
     return;
   DCHECK(IsPresent());
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   if (property_name == properties->powered.name()) {
     PoweredChanged(properties->powered.value());
@@ -392,10 +405,10 @@
 
 void BluetoothAdapterChromeOS::DeviceAdded(
   const dbus::ObjectPath& object_path) {
-  DCHECK(DBusThreadManager::Get());
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path);
+  DCHECK(bluez::BluezDBusManager::Get());
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path);
   if (!properties || properties->adapter.value() != object_path_)
     return;
   DCHECK(IsPresent());
@@ -437,9 +450,9 @@
   if (!device_chromeos)
     return;
 
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path);
 
   if (property_name == properties->address.name()) {
     for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
@@ -504,9 +517,9 @@
   if (!device_chromeos)
     return;
 
-  BluetoothInputClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothInputClient()->
-          GetProperties(object_path);
+  bluez::BluetoothInputClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
+          object_path);
 
   // Properties structure can be removed, which triggers a change in the
   // BluetoothDevice::IsConnectable() property, as does a change in the
@@ -663,8 +676,9 @@
 void BluetoothAdapterChromeOS::OnRegisterAgent() {
   VLOG(1) << "Pairing agent registered, requesting to be made default";
 
-  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
-      RequestDefaultAgent(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAgentManagerClient()
+      ->RequestDefaultAgent(
           dbus::ObjectPath(kAgentPath),
           base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent,
                      weak_ptr_factory_.GetWeakPtr()),
@@ -755,8 +769,9 @@
   VLOG(1) << object_path_.value() << ": using adapter.";
 
   VLOG(1) << "Registering pairing agent";
-  DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
-      RegisterAgent(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAgentManagerClient()
+      ->RegisterAgent(
           dbus::ObjectPath(kAgentPath),
           bluetooth_agent_manager::kKeyboardDisplayCapability,
           base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent,
@@ -766,9 +781,10 @@
 
   SetDefaultAdapterName();
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   PresentChanged(true);
 
@@ -780,8 +796,9 @@
     DiscoveringChanged(true);
 
   std::vector<dbus::ObjectPath> device_paths =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetDevicesForAdapter(object_path_);
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothDeviceClient()
+          ->GetDevicesForAdapter(object_path_);
 
   for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin();
        iter != device_paths.end(); ++iter) {
@@ -818,9 +835,10 @@
   DCHECK(IsPresent());
   VLOG(1) << object_path_.value() << ": adapter removed.";
 
-  BluetoothAdapterClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothAdapterClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothAdapterClient()
+          ->GetProperties(object_path_);
 
   object_path_ = dbus::ObjectPath("");
 
@@ -1008,8 +1026,8 @@
 void BluetoothAdapterChromeOS::UseProfile(
     const BluetoothUUID& uuid,
     const dbus::ObjectPath& device_path,
-    const BluetoothProfileManagerClient::Options& options,
-    BluetoothProfileServiceProvider::Delegate* delegate,
+    const bluez::BluetoothProfileManagerClient::Options& options,
+    bluez::BluetoothProfileServiceProvider::Delegate* delegate,
     const ProfileRegisteredCallback& success_callback,
     const ErrorCompletionCallback& error_callback) {
   DCHECK(delegate);
@@ -1080,7 +1098,7 @@
 void BluetoothAdapterChromeOS::SetProfileDelegate(
     const BluetoothUUID& uuid,
     const dbus::ObjectPath& device_path,
-    BluetoothProfileServiceProvider::Delegate* delegate,
+    bluez::BluetoothProfileServiceProvider::Delegate* delegate,
     const ProfileRegisteredCallback& success_callback,
     const ErrorCompletionCallback& error_callback) {
   if (profiles_.find(uuid) == profiles_.end()) {
@@ -1123,13 +1141,13 @@
 
   // Set the discoverable_timeout property to zero so the adapter remains
   // discoverable forever.
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-      GetProperties(object_path_)->discoverable_timeout.Set(
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAdapterClient()
+      ->GetProperties(object_path_)
+      ->discoverable_timeout.Set(
           0,
           base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback,
-                     error_callback));
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
 }
 
 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
@@ -1197,7 +1215,7 @@
 
   // This is the first request to start device discovery.
   discovery_request_pending_ = true;
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
       object_path_,
       base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery,
                  weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
@@ -1251,15 +1269,11 @@
   // discovery.
   DCHECK_EQ(num_discovery_sessions_, 1);
   discovery_request_pending_ = true;
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->
-      StopDiscovery(
-          object_path_,
-          base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback),
-          base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     error_callback));
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StopDiscovery(
+      object_path_, base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery,
+                               weak_ptr_factory_.GetWeakPtr(), callback),
+      base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError,
+                 weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
@@ -1288,7 +1302,7 @@
 
   current_filter_.reset(discovery_filter.release());
 
-  chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
+  bluez::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
 
   if (current_filter_.get()) {
     uint16_t pathloss;
@@ -1323,12 +1337,14 @@
     }
   }
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter(
-      object_path_, dbus_discovery_filter,
-      base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter,
-                 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
-      base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError,
-                 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothAdapterClient()
+      ->SetDiscoveryFilter(
+          object_path_, dbus_discovery_filter,
+          base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter,
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
+          base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError,
+                     weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
 }
 
 void BluetoothAdapterChromeOS::OnStartDiscovery(
@@ -1418,7 +1434,7 @@
   DCHECK(discovery_request_pending_);
   DCHECK_EQ(num_discovery_sessions_, 0);
 
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
       object_path_,
       base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery,
                  weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
diff --git a/device/bluetooth/bluetooth_adapter_chromeos.h b/device/bluetooth/bluetooth_adapter_chromeos.h
index 7570780..b51e603 100644
--- a/device/bluetooth/bluetooth_adapter_chromeos.h
+++ b/device/bluetooth/bluetooth_adapter_chromeos.h
@@ -12,18 +12,18 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_audio_sink.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_discovery_session.h"
 #include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -60,10 +60,10 @@
 // BluetoothChromeOSTest, Shutdown.
 class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterChromeOS
     : public device::BluetoothAdapter,
-      public chromeos::BluetoothAdapterClient::Observer,
-      public chromeos::BluetoothDeviceClient::Observer,
-      public chromeos::BluetoothInputClient::Observer,
-      public chromeos::BluetoothAgentServiceProvider::Delegate {
+      public bluez::BluetoothAdapterClient::Observer,
+      public bluez::BluetoothDeviceClient::Observer,
+      public bluez::BluetoothInputClient::Observer,
+      public bluez::BluetoothAgentServiceProvider::Delegate {
  public:
   typedef base::Callback<void(const std::string& error_message)>
       ErrorCompletionCallback;
@@ -156,8 +156,8 @@
   // |error_callback| will be called.
   void UseProfile(const device::BluetoothUUID& uuid,
                   const dbus::ObjectPath& device_path,
-                  const BluetoothProfileManagerClient::Options& options,
-                  BluetoothProfileServiceProvider::Delegate* delegate,
+                  const bluez::BluetoothProfileManagerClient::Options& options,
+                  bluez::BluetoothProfileServiceProvider::Delegate* delegate,
                   const ProfileRegisteredCallback& success_callback,
                   const ErrorCompletionCallback& error_callback);
 
@@ -193,23 +193,23 @@
   BluetoothAdapterChromeOS();
   ~BluetoothAdapterChromeOS() override;
 
-  // BluetoothAdapterClient::Observer override.
+  // bluez::BluetoothAdapterClient::Observer override.
   void AdapterAdded(const dbus::ObjectPath& object_path) override;
   void AdapterRemoved(const dbus::ObjectPath& object_path) override;
   void AdapterPropertyChanged(const dbus::ObjectPath& object_path,
                               const std::string& property_name) override;
 
-  // BluetoothDeviceClient::Observer override.
+  // bluez::BluetoothDeviceClient::Observer override.
   void DeviceAdded(const dbus::ObjectPath& object_path) override;
   void DeviceRemoved(const dbus::ObjectPath& object_path) override;
   void DevicePropertyChanged(const dbus::ObjectPath& object_path,
                              const std::string& property_name) override;
 
-  // BluetoothInputClient::Observer override.
+  // bluez::BluetoothInputClient::Observer override.
   void InputPropertyChanged(const dbus::ObjectPath& object_path,
                             const std::string& property_name) override;
 
-  // BluetoothAgentServiceProvider::Delegate override.
+  // bluez::BluetoothAgentServiceProvider::Delegate override.
   void Released() override;
   void RequestPinCode(const dbus::ObjectPath& device_path,
                       const PinCodeCallback& callback) override;
@@ -332,11 +332,12 @@
   void OnRegisterProfile(const device::BluetoothUUID& uuid,
                          scoped_ptr<BluetoothAdapterProfileChromeOS> profile);
 
-  void SetProfileDelegate(const device::BluetoothUUID& uuid,
-                          const dbus::ObjectPath& device_path,
-                          BluetoothProfileServiceProvider::Delegate* delegate,
-                          const ProfileRegisteredCallback& success_callback,
-                          const ErrorCompletionCallback& error_callback);
+  void SetProfileDelegate(
+      const device::BluetoothUUID& uuid,
+      const dbus::ObjectPath& device_path,
+      bluez::BluetoothProfileServiceProvider::Delegate* delegate,
+      const ProfileRegisteredCallback& success_callback,
+      const ErrorCompletionCallback& error_callback);
   void OnRegisterProfileError(const device::BluetoothUUID& uuid,
                               const std::string& error_name,
                               const std::string& error_message);
@@ -376,7 +377,7 @@
 
   // Instance of the D-Bus agent object used for pairing, initialized with
   // our own class as its delegate.
-  scoped_ptr<BluetoothAgentServiceProvider> agent_;
+  scoped_ptr<bluez::BluetoothAgentServiceProvider> agent_;
 
   // UI thread task runner and socket thread object used to create sockets.
   scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos.cc b/device/bluetooth/bluetooth_adapter_profile_chromeos.cc
index 207c55c4..27779f28 100644
--- a/device/bluetooth/bluetooth_adapter_profile_chromeos.cc
+++ b/device/bluetooth/bluetooth_adapter_profile_chromeos.cc
@@ -9,32 +9,31 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 namespace chromeos {
 
 // static
 void BluetoothAdapterProfileChromeOS::Register(
     const device::BluetoothUUID& uuid,
-    const BluetoothProfileManagerClient::Options& options,
+    const bluez::BluetoothProfileManagerClient::Options& options,
     const ProfileRegisteredCallback& success_callback,
-    const BluetoothProfileManagerClient::ErrorCallback& error_callback) {
+    const bluez::BluetoothProfileManagerClient::ErrorCallback& error_callback) {
   scoped_ptr<BluetoothAdapterProfileChromeOS> profile(
       new BluetoothAdapterProfileChromeOS(uuid));
 
   VLOG(1) << "Registering profile: " << profile->object_path().value();
   const dbus::ObjectPath& object_path = profile->object_path();
-  DBusThreadManager::Get()->GetBluetoothProfileManagerClient()->RegisterProfile(
-      object_path,
-      uuid.canonical_value(),
-      options,
-      base::Bind(success_callback, base::Passed(&profile)),
-      error_callback);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothProfileManagerClient()
+      ->RegisterProfile(object_path, uuid.canonical_value(), options,
+                        base::Bind(success_callback, base::Passed(&profile)),
+                        error_callback);
 }
 
 BluetoothAdapterProfileChromeOS::BluetoothAdapterProfileChromeOS(
@@ -45,9 +44,9 @@
   object_path_ =
       dbus::ObjectPath("/org/chromium/bluetooth_profile/" + uuid_path);
 
-  dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
-  profile_.reset(
-      BluetoothProfileServiceProvider::Create(system_bus, object_path_, this));
+  dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
+  profile_.reset(bluez::BluetoothProfileServiceProvider::Create(
+      system_bus, object_path_, this));
   DCHECK(profile_.get());
 }
 
@@ -56,7 +55,7 @@
 
 bool BluetoothAdapterProfileChromeOS::SetDelegate(
     const dbus::ObjectPath& device_path,
-    BluetoothProfileServiceProvider::Delegate* delegate) {
+    bluez::BluetoothProfileServiceProvider::Delegate* delegate) {
   DCHECK(delegate);
   VLOG(1) << "SetDelegate: " << object_path_.value() << " dev "
           << device_path.value();
@@ -86,7 +85,7 @@
   VLOG(1) << device_path.value() << " No delegates left, unregistering.";
 
   // No users left, release the profile.
-  DBusThreadManager::Get()
+  bluez::BluezDBusManager::Get()
       ->GetBluetoothProfileManagerClient()
       ->UnregisterProfile(
           object_path_, unregistered_callback,
@@ -105,7 +104,7 @@
   unregistered_callback.Run();
 }
 
-// BluetoothProfileServiceProvider::Delegate:
+// bluez::BluetoothProfileServiceProvider::Delegate:
 void BluetoothAdapterProfileChromeOS::Released() {
   VLOG(1) << object_path_.value() << ": Release";
 }
@@ -113,7 +112,7 @@
 void BluetoothAdapterProfileChromeOS::NewConnection(
     const dbus::ObjectPath& device_path,
     scoped_ptr<dbus::FileDescriptor> fd,
-    const BluetoothProfileServiceProvider::Delegate::Options& options,
+    const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
     const ConfirmationCallback& callback) {
   dbus::ObjectPath delegate_path = device_path;
 
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos.h b/device/bluetooth/bluetooth_adapter_profile_chromeos.h
index 85e2ffe..35971e8 100644
--- a/device/bluetooth/bluetooth_adapter_profile_chromeos.h
+++ b/device/bluetooth/bluetooth_adapter_profile_chromeos.h
@@ -6,10 +6,10 @@
 #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_PROFILE_CHROMEOS_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
 namespace device {
 class BluetoothUUID;
@@ -28,7 +28,7 @@
 // BluetoothAdapterProfileChromeOS objects are owned by the
 // BluetoothAdapterChromeOS and allocated through Register()
 class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterProfileChromeOS
-    : public chromeos::BluetoothProfileServiceProvider::Delegate {
+    : public bluez::BluetoothProfileServiceProvider::Delegate {
  public:
   typedef base::Callback<void(scoped_ptr<BluetoothAdapterProfileChromeOS>
                                   profile)> ProfileRegisteredCallback;
@@ -39,9 +39,10 @@
   // will be called.
   static void Register(
       const device::BluetoothUUID& uuid,
-      const BluetoothProfileManagerClient::Options& options,
+      const bluez::BluetoothProfileManagerClient::Options& options,
       const ProfileRegisteredCallback& success_callback,
-      const BluetoothProfileManagerClient::ErrorCallback& error_callback);
+      const bluez::BluetoothProfileManagerClient::ErrorCallback&
+          error_callback);
 
   ~BluetoothAdapterProfileChromeOS() override;
 
@@ -56,7 +57,7 @@
   // Returns true if the delegate was set, and false if the |device_path|
   // already had a delegate set.
   bool SetDelegate(const dbus::ObjectPath& device_path,
-                   BluetoothProfileServiceProvider::Delegate* delegate);
+                   bluez::BluetoothProfileServiceProvider::Delegate* delegate);
 
   // Remove the delegate for a device. |unregistered_callback| will be called
   // if this unregisters the profile.
@@ -69,12 +70,12 @@
  private:
   BluetoothAdapterProfileChromeOS(const device::BluetoothUUID& uuid);
 
-  // BluetoothProfileServiceProvider::Delegate:
+  // bluez::BluetoothProfileServiceProvider::Delegate:
   void Released() override;
   void NewConnection(
       const dbus::ObjectPath& device_path,
       scoped_ptr<dbus::FileDescriptor> fd,
-      const BluetoothProfileServiceProvider::Delegate::Options& options,
+      const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
       const ConfirmationCallback& callback) override;
   void RequestDisconnection(const dbus::ObjectPath& device_path,
                             const ConfirmationCallback& callback) override;
@@ -86,7 +87,8 @@
                                 const std::string& error_message);
 
   // List of delegates which this profile is multiplexing to.
-  std::map<std::string, BluetoothProfileServiceProvider::Delegate*> delegates_;
+  std::map<std::string, bluez::BluetoothProfileServiceProvider::Delegate*>
+      delegates_;
 
   // The UUID that this profile represents.
   const device::BluetoothUUID& uuid_;
@@ -95,7 +97,7 @@
   dbus::ObjectPath object_path_;
 
   // Profile dbus object for receiving profile method calls from BlueZ
-  scoped_ptr<BluetoothProfileServiceProvider> profile_;
+  scoped_ptr<bluez::BluetoothProfileServiceProvider> profile_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc b/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc
index 1b9c0b3..be999019 100644
--- a/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_profile_chromeos_unittest.cc
@@ -4,17 +4,17 @@
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using device::BluetoothAdapter;
@@ -27,25 +27,29 @@
   BluetoothAdapterProfileChromeOSTest()
       : success_callback_count_(0),
         error_callback_count_(0),
-        fake_delegate_paired_(FakeBluetoothDeviceClient::kPairedDevicePath),
-        fake_delegate_autopair_(FakeBluetoothDeviceClient::kLegacyAutopairPath),
+        fake_delegate_paired_(
+            bluez::FakeBluetoothDeviceClient::kPairedDevicePath),
+        fake_delegate_autopair_(
+            bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath),
         fake_delegate_listen_(""),
         profile_user_ptr_(nullptr) {}
 
   void SetUp() override {
-    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
-        DBusThreadManager::GetSetterForTesting();
+    scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
+        bluez::BluezDBusManager::GetSetterForTesting();
 
     dbus_setter->SetBluetoothAdapterClient(
-        scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
+        scoped_ptr<bluez::BluetoothAdapterClient>(
+            new bluez::FakeBluetoothAdapterClient));
     dbus_setter->SetBluetoothAgentManagerClient(
-        scoped_ptr<BluetoothAgentManagerClient>(
-            new FakeBluetoothAgentManagerClient));
+        scoped_ptr<bluez::BluetoothAgentManagerClient>(
+            new bluez::FakeBluetoothAgentManagerClient));
     dbus_setter->SetBluetoothDeviceClient(
-        scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
+        scoped_ptr<bluez::BluetoothDeviceClient>(
+            new bluez::FakeBluetoothDeviceClient));
     dbus_setter->SetBluetoothProfileManagerClient(
-        scoped_ptr<BluetoothProfileManagerClient>(
-            new FakeBluetoothProfileManagerClient));
+        scoped_ptr<bluez::BluetoothProfileManagerClient>(
+            new bluez::FakeBluetoothProfileManagerClient));
 
     // Grab a pointer to the adapter.
     device::BluetoothAdapterFactory::GetAdapter(
@@ -64,21 +68,20 @@
   void TearDown() override {
     profile_.reset();
     adapter_ = nullptr;
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
     adapter_ = adapter;
   }
 
-  class FakeDelegate
-      : public chromeos::BluetoothProfileServiceProvider::Delegate {
+  class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate {
    public:
     FakeDelegate(const std::string& device_path) : connections_(0) {
       device_path_ = dbus::ObjectPath(device_path);
     }
 
-    // BluetoothProfileServiceProvider::Delegate:
+    // bluez::BluetoothProfileServiceProvider::Delegate:
     void Released() override {
       // noop
     }
@@ -86,7 +89,8 @@
     void NewConnection(
         const dbus::ObjectPath& device_path,
         scoped_ptr<dbus::FileDescriptor> fd,
-        const BluetoothProfileServiceProvider::Delegate::Options& options,
+        const bluez::BluetoothProfileServiceProvider::Delegate::Options&
+            options,
         const ConfirmationCallback& callback) override {
       ++connections_;
       fd->CheckValidity();
@@ -157,8 +161,8 @@
 };
 
 TEST_F(BluetoothAdapterProfileChromeOSTest, DelegateCount) {
-  BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid);
-  BluetoothProfileManagerClient::Options options;
+  BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
+  bluez::BluetoothProfileManagerClient::Options options;
 
   options.require_authentication.reset(new bool(false));
 
@@ -194,8 +198,8 @@
 }
 
 TEST_F(BluetoothAdapterProfileChromeOSTest, BlackHole) {
-  BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid);
-  BluetoothProfileManagerClient::Options options;
+  BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
+  bluez::BluetoothProfileManagerClient::Options options;
 
   options.require_authentication.reset(new bool(false));
 
@@ -212,9 +216,9 @@
   EXPECT_EQ(1U, success_callback_count_);
   EXPECT_EQ(0U, error_callback_count_);
 
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath),
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
       base::Bind(
           &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback,
           base::Unretained(this)),
@@ -230,8 +234,8 @@
 }
 
 TEST_F(BluetoothAdapterProfileChromeOSTest, Routing) {
-  BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid);
-  BluetoothProfileManagerClient::Options options;
+  BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
+  bluez::BluetoothProfileManagerClient::Options options;
 
   options.require_authentication.reset(new bool(false));
 
@@ -255,9 +259,9 @@
   profile_->SetDelegate(fake_delegate_listen_.device_path_,
                         &fake_delegate_listen_);
 
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath),
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
       base::Bind(
           &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback,
           base::Unretained(this)),
@@ -271,9 +275,9 @@
 
   EXPECT_EQ(1U, fake_delegate_paired_.connections_);
 
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLegacyAutopairPath),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath),
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
       base::Bind(
           &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback,
           base::Unretained(this)),
@@ -288,9 +292,9 @@
   EXPECT_EQ(1U, fake_delegate_autopair_.connections_);
 
   // Incoming connections look the same from BlueZ.
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPinCodePath),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath),
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
       base::Bind(
           &BluetoothAdapterProfileChromeOSTest::DBusConnectSuccessCallback,
           base::Unretained(this)),
@@ -306,8 +310,8 @@
 }
 
 TEST_F(BluetoothAdapterProfileChromeOSTest, SimultaneousRegister) {
-  BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kRfcommUuid);
-  BluetoothProfileManagerClient::Options options;
+  BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
+  bluez::BluetoothProfileManagerClient::Options options;
   BluetoothAdapterChromeOS* adapter =
       static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
@@ -347,8 +351,9 @@
 }
 
 TEST_F(BluetoothAdapterProfileChromeOSTest, SimultaneousRegisterFail) {
-  BluetoothUUID uuid(FakeBluetoothProfileManagerClient::kUnregisterableUuid);
-  BluetoothProfileManagerClient::Options options;
+  BluetoothUUID uuid(
+      bluez::FakeBluetoothProfileManagerClient::kUnregisterableUuid);
+  bluez::BluetoothProfileManagerClient::Options options;
   BluetoothAdapterChromeOS* adapter =
       static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
 
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos.cc b/device/bluetooth/bluetooth_advertisement_chromeos.cc
index 8cdfe90e..671977dc 100644
--- a/device/bluetooth/bluetooth_advertisement_chromeos.cc
+++ b/device/bluetooth/bluetooth_advertisement_chromeos.cc
@@ -12,11 +12,11 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace {
@@ -82,10 +82,12 @@
   dbus::ObjectPath advertisement_object_path =
       dbus::ObjectPath("/org/chromium/bluetooth_advertisement/" + GuidString);
 
-  DCHECK(DBusThreadManager::Get());
-  provider_ = BluetoothLEAdvertisementServiceProvider::Create(
-      DBusThreadManager::Get()->GetSystemBus(), advertisement_object_path, this,
-      static_cast<BluetoothLEAdvertisementServiceProvider::AdvertisementType>(
+  DCHECK(bluez::BluezDBusManager::Get());
+  provider_ = bluez::BluetoothLEAdvertisementServiceProvider::Create(
+      bluez::BluezDBusManager::Get()->GetSystemBus(), advertisement_object_path,
+      this,
+      static_cast<
+          bluez::BluetoothLEAdvertisementServiceProvider::AdvertisementType>(
           data->type()),
       data->service_uuids().Pass(), data->manufacturer_data().Pass(),
       data->solicit_uuids().Pass(), data->service_data().Pass());
@@ -95,8 +97,8 @@
     const base::Closure& success_callback,
     const device::BluetoothAdapter::CreateAdvertisementErrorCallback&
         error_callback) {
-  DCHECK(DBusThreadManager::Get());
-  DBusThreadManager::Get()
+  DCHECK(bluez::BluezDBusManager::Get());
+  bluez::BluezDBusManager::Get()
       ->GetBluetoothLEAdvertisingManagerClient()
       ->RegisterAdvertisement(
           adapter_->object_path(), provider_->object_path(), success_callback,
@@ -118,8 +120,8 @@
     return;
   }
 
-  DCHECK(DBusThreadManager::Get());
-  DBusThreadManager::Get()
+  DCHECK(bluez::BluezDBusManager::Get());
+  bluez::BluezDBusManager::Get()
       ->GetBluetoothLEAdvertisingManagerClient()
       ->UnregisterAdvertisement(
           adapter_->object_path(), provider_->object_path(), success_callback,
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos.h b/device/bluetooth/bluetooth_advertisement_chromeos.h
index aeb59b7c..44abec27 100644
--- a/device/bluetooth/bluetooth_advertisement_chromeos.h
+++ b/device/bluetooth/bluetooth_advertisement_chromeos.h
@@ -6,21 +6,24 @@
 #define DEVICE_BLUETOOTH_BLUETOOTH_ADVERTISEMENT_CHROMEOS_H_
 
 #include "base/macros.h"
-#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_advertisement.h"
 #include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h"
+
+namespace bluez {
+class BluetoothLEAdvertisementServiceProvider;
+}
 
 namespace chromeos {
 
-class BluetoothLEAdvertisementServiceProvider;
 class BluetoothAdapterChromeOS;
 
 // The BluetoothAdvertisementChromeOS class implements BluetoothAdvertisement
 // for the Chrome OS platform.
 class DEVICE_BLUETOOTH_EXPORT BluetoothAdvertisementChromeOS
     : public device::BluetoothAdvertisement,
-      public BluetoothLEAdvertisementServiceProvider::Delegate {
+      public bluez::BluetoothLEAdvertisementServiceProvider::Delegate {
  public:
   BluetoothAdvertisementChromeOS(
       scoped_ptr<device::BluetoothAdvertisement::Data> data,
@@ -30,7 +33,7 @@
   void Unregister(const SuccessCallback& success_callback,
                   const ErrorCallback& error_callback) override;
 
-  // BluetoothLEAdvertisementServiceProvider::Delegate overrides:
+  // bluez::BluetoothLEAdvertisementServiceProvider::Delegate overrides:
   void Released() override;
 
   void Register(
@@ -40,7 +43,7 @@
 
   // Used from tests to be able to trigger events on the fake advertisement
   // provider.
-  BluetoothLEAdvertisementServiceProvider* provider() {
+  bluez::BluetoothLEAdvertisementServiceProvider* provider() {
     return provider_.get();
   }
 
@@ -49,7 +52,7 @@
 
   // Adapter this advertisement is advertising on.
   scoped_refptr<BluetoothAdapterChromeOS> adapter_;
-  scoped_ptr<BluetoothLEAdvertisementServiceProvider> provider_;
+  scoped_ptr<bluez::BluetoothLEAdvertisementServiceProvider> provider_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementChromeOS);
 };
diff --git a/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc b/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc
index 02fe1e4a..165dc8d9 100644
--- a/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_advertisement_chromeos_unittest.cc
@@ -9,12 +9,12 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_advertisement.h"
 #include "device/bluetooth/bluetooth_advertisement_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using device::BluetoothAdapter;
@@ -52,7 +52,7 @@
 class BluetoothAdvertisementChromeOSTest : public testing::Test {
  public:
   void SetUp() override {
-    DBusThreadManager::Initialize();
+    bluez::BluezDBusManager::Initialize(NULL, true);
 
     callback_count_ = 0;
     error_callback_count_ = 0;
@@ -70,7 +70,7 @@
     // The adapter should outlive the advertisement.
     advertisement_ = nullptr;
     adapter_ = nullptr;
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   // Gets the existing Bluetooth adapter.
@@ -134,8 +134,8 @@
   void TriggerReleased(scoped_refptr<BluetoothAdvertisement> advertisement) {
     BluetoothAdvertisementChromeOS* adv =
         static_cast<BluetoothAdvertisementChromeOS*>(advertisement.get());
-    FakeBluetoothLEAdvertisementServiceProvider* provider =
-        static_cast<FakeBluetoothLEAdvertisementServiceProvider*>(
+    bluez::FakeBluetoothLEAdvertisementServiceProvider* provider =
+        static_cast<bluez::FakeBluetoothLEAdvertisementServiceProvider*>(
             adv->provider());
     provider->Release();
   }
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos.cc b/device/bluetooth/bluetooth_audio_sink_chromeos.cc
index 82b87f76..9bb4b60 100644
--- a/device/bluetooth/bluetooth_audio_sink_chromeos.cc
+++ b/device/bluetooth/bluetooth_audio_sink_chromeos.cc
@@ -14,9 +14,9 @@
 #include "base/debug/stack_trace.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/message.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 using dbus::ObjectPath;
 using device::BluetoothAudioSink;
@@ -94,17 +94,17 @@
 
   CHECK(adapter_.get());
   CHECK(adapter_->IsPresent());
-  CHECK(DBusThreadManager::IsInitialized());
+  CHECK(bluez::BluezDBusManager::IsInitialized());
 
   adapter_->AddObserver(this);
 
-  BluetoothMediaClient* media =
-      DBusThreadManager::Get()->GetBluetoothMediaClient();
+  bluez::BluetoothMediaClient* media =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
   CHECK(media);
   media->AddObserver(this);
 
-  BluetoothMediaTransportClient* transport =
-      DBusThreadManager::Get()->GetBluetoothMediaTransportClient();
+  bluez::BluetoothMediaTransportClient* transport =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient();
   CHECK(transport);
   transport->AddObserver(this);
 
@@ -123,13 +123,13 @@
 
   adapter_->RemoveObserver(this);
 
-  BluetoothMediaClient* media =
-      DBusThreadManager::Get()->GetBluetoothMediaClient();
+  bluez::BluetoothMediaClient* media =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
   CHECK(media);
   media->RemoveObserver(this);
 
-  BluetoothMediaTransportClient* transport =
-      DBusThreadManager::Get()->GetBluetoothMediaTransportClient();
+  bluez::BluetoothMediaTransportClient* transport =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient();
   CHECK(transport);
   transport->RemoveObserver(this);
 }
@@ -139,11 +139,11 @@
     const device::BluetoothAudioSink::ErrorCallback& error_callback) {
   VLOG(1) << "Unregister";
 
-  if (!DBusThreadManager::IsInitialized())
+  if (!bluez::BluezDBusManager::IsInitialized())
     error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED);
 
-  BluetoothMediaClient* media =
-      DBusThreadManager::Get()->GetBluetoothMediaClient();
+  bluez::BluetoothMediaClient* media =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
   CHECK(media);
 
   media->UnregisterEndpoint(
@@ -185,28 +185,28 @@
   DCHECK_EQ(state_, BluetoothAudioSink::STATE_DISCONNECTED);
 
   // Gets system bus.
-  dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
+  dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
 
   // Creates a Media Endpoint with newly-generated path.
   endpoint_path_ = GenerateEndpointPath();
-  media_endpoint_.reset(
-      BluetoothMediaEndpointServiceProvider::Create(
-          system_bus, endpoint_path_, this));
+  media_endpoint_.reset(bluez::BluetoothMediaEndpointServiceProvider::Create(
+      system_bus, endpoint_path_, this));
 
   DCHECK(media_endpoint_.get());
 
   // Creates endpoint properties with |options|.
   options_ = options;
-  chromeos::BluetoothMediaClient::EndpointProperties endpoint_properties;
-  endpoint_properties.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID;
+  bluez::BluetoothMediaClient::EndpointProperties endpoint_properties;
+  endpoint_properties.uuid =
+      bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID;
   endpoint_properties.codec = options_.codec;
   endpoint_properties.capabilities = options_.capabilities;
 
   media_path_ = static_cast<BluetoothAdapterChromeOS*>(
       adapter_.get())->object_path();
 
-  BluetoothMediaClient* media =
-      DBusThreadManager::Get()->GetBluetoothMediaClient();
+  bluez::BluetoothMediaClient* media =
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
   CHECK(media);
   media->RegisterEndpoint(
       media_path_,
@@ -218,8 +218,8 @@
                  weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
-BluetoothMediaEndpointServiceProvider*
-    BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() {
+bluez::BluetoothMediaEndpointServiceProvider*
+BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() {
   return media_endpoint_.get();
 }
 
@@ -280,21 +280,21 @@
   VLOG(1) << "MediaTransportPropertyChanged: " << property_name;
 
   // Retrieves the property set of the transport object with |object_path|.
-  BluetoothMediaTransportClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothMediaTransportClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothMediaTransportClient()
           ->GetProperties(object_path);
 
   // Dispatches a property changed event to the corresponding handler.
   if (property_name == properties->state.name()) {
     if (properties->state.value() ==
-        BluetoothMediaTransportClient::kStateIdle) {
+        bluez::BluetoothMediaTransportClient::kStateIdle) {
       StateChanged(BluetoothAudioSink::STATE_IDLE);
     } else if (properties->state.value() ==
-               BluetoothMediaTransportClient::kStatePending) {
+               bluez::BluetoothMediaTransportClient::kStatePending) {
       StateChanged(BluetoothAudioSink::STATE_PENDING);
     } else if (properties->state.value() ==
-               BluetoothMediaTransportClient::kStateActive) {
+               bluez::BluetoothMediaTransportClient::kStateActive) {
       StateChanged(BluetoothAudioSink::STATE_ACTIVE);
     }
   } else if (property_name == properties->volume.name()) {
@@ -309,7 +309,7 @@
   transport_path_ = transport_path;
 
   // The initial state for a connection should be "idle".
-  if (properties.state != BluetoothMediaTransportClient::kStateIdle) {
+  if (properties.state != bluez::BluetoothMediaTransportClient::kStateIdle) {
     VLOG(1) << "SetConfiugration - unexpected state :" << properties.state;
     return;
   }
@@ -356,7 +356,7 @@
 
   read_has_failed_ = false;
 
-  DBusThreadManager::Get()->GetBluetoothMediaTransportClient()->Acquire(
+  bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()->Acquire(
       transport_path_,
       base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireSucceeded,
                  weak_ptr_factory_.GetWeakPtr()),
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos.h b/device/bluetooth/bluetooth_audio_sink_chromeos.h
index 6261ace2..750b31d 100644
--- a/device/bluetooth/bluetooth_audio_sink_chromeos.h
+++ b/device/bluetooth/bluetooth_audio_sink_chromeos.h
@@ -14,14 +14,14 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/observer_list.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
-#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_audio_sink.h"
 #include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
 
 namespace chromeos {
 
@@ -30,9 +30,9 @@
 class DEVICE_BLUETOOTH_EXPORT BluetoothAudioSinkChromeOS
     : public device::BluetoothAudioSink,
       public device::BluetoothAdapter::Observer,
-      public BluetoothMediaClient::Observer,
-      public BluetoothMediaTransportClient::Observer,
-      public BluetoothMediaEndpointServiceProvider::Delegate,
+      public bluez::BluetoothMediaClient::Observer,
+      public bluez::BluetoothMediaTransportClient::Observer,
+      public bluez::BluetoothMediaEndpointServiceProvider::Delegate,
       public base::MessageLoopForIO::Watcher {
  public:
   explicit BluetoothAudioSinkChromeOS(
@@ -61,7 +61,7 @@
 
   // Returns a pointer to the media endpoint object. This function should be
   // used for testing purpose only.
-  BluetoothMediaEndpointServiceProvider* GetEndpointServiceProvider();
+  bluez::BluetoothMediaEndpointServiceProvider* GetEndpointServiceProvider();
 
  private:
   ~BluetoothAudioSinkChromeOS() override;
@@ -72,15 +72,15 @@
   void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
                              bool powered) override;
 
-  // BluetoothMediaClient::Observer overrides.
+  // bluez::BluetoothMediaClient::Observer overrides.
   void MediaRemoved(const dbus::ObjectPath& object_path) override;
 
-  // BluetoothMediaTransportClient::Observer overrides.
+  // bluez::BluetoothMediaTransportClient::Observer overrides.
   void MediaTransportRemoved(const dbus::ObjectPath& object_path) override;
   void MediaTransportPropertyChanged(const dbus::ObjectPath& object_path,
                                      const std::string& property_name) override;
 
-  // BluetoothMediaEndpointServiceProvider::Delegate overrides.
+  // bluez::BluetoothMediaEndpointServiceProvider::Delegate overrides.
   void SetConfiguration(const dbus::ObjectPath& transport_path,
                         const TransportProperties& properties) override;
   void SelectConfiguration(
@@ -204,7 +204,7 @@
   device::BluetoothAudioSink::Options options_;
 
   // Media Endpoint object owned by the audio sink object.
-  scoped_ptr<BluetoothMediaEndpointServiceProvider> media_endpoint_;
+  scoped_ptr<bluez::BluetoothMediaEndpointServiceProvider> media_endpoint_;
 
   // List of observers interested in event notifications from us. Objects in
   // |observers_| are expected to outlive a BluetoothAudioSinkChromeOS object.
diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc
index 9781dec1..22918f7 100644
--- a/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_audio_sink_chromeos_unittest.cc
@@ -8,18 +8,18 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
-#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_media_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_media_transport_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_audio_sink.h"
 #include "device/bluetooth/bluetooth_audio_sink_chromeos.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using dbus::ObjectPath;
@@ -81,28 +81,29 @@
 class BluetoothAudioSinkChromeOSTest : public testing::Test {
  public:
   void SetUp() override {
-    DBusThreadManager::Initialize();
+    bluez::BluezDBusManager::Initialize(NULL, true);
 
     callback_count_ = 0;
     error_callback_count_ = 0;
 
-    fake_media_ = static_cast<FakeBluetoothMediaClient*>(
-        DBusThreadManager::Get()->GetBluetoothMediaClient());
-    fake_transport_ = static_cast<FakeBluetoothMediaTransportClient*>(
-        DBusThreadManager::Get()->GetBluetoothMediaTransportClient());
+    fake_media_ = static_cast<bluez::FakeBluetoothMediaClient*>(
+        bluez::BluezDBusManager::Get()->GetBluetoothMediaClient());
+    fake_transport_ = static_cast<bluez::FakeBluetoothMediaTransportClient*>(
+        bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient());
 
     // Initiates Delegate::TransportProperties with default values.
-    properties_.device =
-        ObjectPath(FakeBluetoothMediaTransportClient::kTransportDevicePath);
-    properties_.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID;
-    properties_.codec = FakeBluetoothMediaTransportClient::kTransportCodec;
+    properties_.device = ObjectPath(
+        bluez::FakeBluetoothMediaTransportClient::kTransportDevicePath);
+    properties_.uuid = bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID;
+    properties_.codec =
+        bluez::FakeBluetoothMediaTransportClient::kTransportCodec;
     properties_.configuration =
-        FakeBluetoothMediaTransportClient::kTransportConfiguration;
-    properties_.state = BluetoothMediaTransportClient::kStateIdle;
-    properties_.delay.reset(
-        new uint16_t(FakeBluetoothMediaTransportClient::kTransportDelay));
-    properties_.volume.reset(
-        new uint16_t(FakeBluetoothMediaTransportClient::kTransportVolume));
+        bluez::FakeBluetoothMediaTransportClient::kTransportConfiguration;
+    properties_.state = bluez::BluetoothMediaTransportClient::kStateIdle;
+    properties_.delay.reset(new uint16_t(
+        bluez::FakeBluetoothMediaTransportClient::kTransportDelay));
+    properties_.volume.reset(new uint16_t(
+        bluez::FakeBluetoothMediaTransportClient::kTransportVolume));
 
     GetAdapter();
   }
@@ -117,7 +118,7 @@
     // The adapter should outlive audio sink.
     audio_sink_ = nullptr;
     adapter_ = nullptr;
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   // Gets the existing Bluetooth adapter.
@@ -178,8 +179,9 @@
         static_cast<BluetoothAudioSinkChromeOS*>(audio_sink_.get());
     ASSERT_NE(audio_sink_chromeos, nullptr);
 
-    media_endpoint_ = static_cast<FakeBluetoothMediaEndpointServiceProvider*>(
-        audio_sink_chromeos->GetEndpointServiceProvider());
+    media_endpoint_ =
+        static_cast<bluez::FakeBluetoothMediaEndpointServiceProvider*>(
+            audio_sink_chromeos->GetEndpointServiceProvider());
   }
 
   // Called whenever RegisterAudioSink is completed successfully.
@@ -231,16 +233,16 @@
 
   base::MessageLoopForIO message_loop_;
 
-  FakeBluetoothMediaClient* fake_media_;
-  FakeBluetoothMediaTransportClient* fake_transport_;
-  FakeBluetoothMediaEndpointServiceProvider* media_endpoint_;
+  bluez::FakeBluetoothMediaClient* fake_media_;
+  bluez::FakeBluetoothMediaTransportClient* fake_transport_;
+  bluez::FakeBluetoothMediaEndpointServiceProvider* media_endpoint_;
   scoped_ptr<TestAudioSinkObserver> observer_;
   scoped_refptr<BluetoothAdapter> adapter_;
   scoped_refptr<BluetoothAudioSink> audio_sink_;
 
   // The default property set used while calling SetConfiguration on a media
   // endpoint object.
-  BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties
+  bluez::BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties
       properties_;
 };
 
@@ -784,7 +786,7 @@
   // |kTransportVolume| is the initial volume of the transport, and this
   // value is propagated to the audio sink via SetConfiguration.
   EXPECT_EQ(audio_sink_->GetVolume(),
-            FakeBluetoothMediaTransportClient::kTransportVolume);
+            bluez::FakeBluetoothMediaTransportClient::kTransportVolume);
 
   // Changes volume to a valid level.
   fake_transport_->SetVolume(media_endpoint_->object_path(), 100);
@@ -842,7 +844,7 @@
   EXPECT_EQ(observer_->total_read_, data_one.size());
   EXPECT_EQ(observer_->data_, data_one);
   EXPECT_EQ(observer_->read_mtu_,
-            FakeBluetoothMediaTransportClient::kDefaultReadMtu);
+            bluez::FakeBluetoothMediaTransportClient::kDefaultReadMtu);
 }
 
 // Tests the case where the remote device pauses and resume audio streaming.
@@ -879,7 +881,7 @@
 
   EXPECT_EQ(observer_->data_, data_one);
   EXPECT_EQ(observer_->read_mtu_,
-            FakeBluetoothMediaTransportClient::kDefaultReadMtu);
+            bluez::FakeBluetoothMediaTransportClient::kDefaultReadMtu);
   EXPECT_EQ(observer_->state_changed_count_, 3);
   EXPECT_EQ(observer_->total_read_, data_one.size());
 
@@ -899,7 +901,7 @@
 
   EXPECT_EQ(observer_->data_, data_two);
   EXPECT_EQ(observer_->read_mtu_,
-            FakeBluetoothMediaTransportClient::kDefaultReadMtu);
+            bluez::FakeBluetoothMediaTransportClient::kDefaultReadMtu);
   EXPECT_EQ(observer_->state_changed_count_, 6);
   EXPECT_EQ(observer_->total_read_, data_two.size());
 }
@@ -937,7 +939,7 @@
 
   EXPECT_EQ(observer_->data_, data_one);
   EXPECT_EQ(observer_->read_mtu_,
-            FakeBluetoothMediaTransportClient::kDefaultReadMtu);
+            bluez::FakeBluetoothMediaTransportClient::kDefaultReadMtu);
   EXPECT_EQ(observer_->state_changed_count_, 3);
   EXPECT_EQ(observer_->total_read_, data_one.size());
 
@@ -948,7 +950,7 @@
 
   EXPECT_EQ(observer_->data_, data_two);
   EXPECT_EQ(observer_->read_mtu_,
-            FakeBluetoothMediaTransportClient::kDefaultReadMtu);
+            bluez::FakeBluetoothMediaTransportClient::kDefaultReadMtu);
   EXPECT_EQ(observer_->state_changed_count_, 3);
   EXPECT_EQ(observer_->total_read_, data_one.size() + data_two.size());
 }
diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc
index 079cce6f..ec58701 100644
--- a/device/bluetooth/bluetooth_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_chromeos_unittest.cc
@@ -6,12 +6,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
@@ -20,6 +14,12 @@
 #include "device/bluetooth/bluetooth_device_chromeos.h"
 #include "device/bluetooth/bluetooth_discovery_session.h"
 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
 #include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -45,17 +45,18 @@
 };
 
 class FakeBluetoothProfileServiceProviderDelegate
-    : public chromeos::BluetoothProfileServiceProvider::Delegate {
+    : public bluez::BluetoothProfileServiceProvider::Delegate {
  public:
   FakeBluetoothProfileServiceProviderDelegate() {}
 
-  // BluetoothProfileServiceProvider::Delegate:
+  // bluez::BluetoothProfileServiceProvider::Delegate:
   void Released() override {}
 
-  void NewConnection(const dbus::ObjectPath&,
-                     scoped_ptr<dbus::FileDescriptor>,
-                     const BluetoothProfileServiceProvider::Delegate::Options&,
-                     const ConfirmationCallback&) override {}
+  void NewConnection(
+      const dbus::ObjectPath&,
+      scoped_ptr<dbus::FileDescriptor>,
+      const bluez::BluetoothProfileServiceProvider::Delegate::Options&,
+      const ConfirmationCallback&) override {}
 
   void RequestDisconnection(const dbus::ObjectPath&,
                             const ConfirmationCallback&) override {}
@@ -153,25 +154,28 @@
 class BluetoothChromeOSTest : public testing::Test {
  public:
   void SetUp() override {
-    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
-        chromeos::DBusThreadManager::GetSetterForTesting();
-    // We need to initialize DBusThreadManager early to prevent
+    scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
+        bluez::BluezDBusManager::GetSetterForTesting();
+    // We need to initialize BluezDBusManager early to prevent
     // Bluetooth*::Create() methods from picking the real instead of fake
     // implementations.
-    fake_bluetooth_adapter_client_ = new FakeBluetoothAdapterClient;
+    fake_bluetooth_adapter_client_ = new bluez::FakeBluetoothAdapterClient;
     dbus_setter->SetBluetoothAdapterClient(
-        scoped_ptr<BluetoothAdapterClient>(fake_bluetooth_adapter_client_));
-    fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient;
+        scoped_ptr<bluez::BluetoothAdapterClient>(
+            fake_bluetooth_adapter_client_));
+    fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient;
     dbus_setter->SetBluetoothDeviceClient(
-        scoped_ptr<BluetoothDeviceClient>(fake_bluetooth_device_client_));
+        scoped_ptr<bluez::BluetoothDeviceClient>(
+            fake_bluetooth_device_client_));
     dbus_setter->SetBluetoothInputClient(
-        scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
+        scoped_ptr<bluez::BluetoothInputClient>(
+            new bluez::FakeBluetoothInputClient));
     dbus_setter->SetBluetoothAgentManagerClient(
-        scoped_ptr<BluetoothAgentManagerClient>(
-            new FakeBluetoothAgentManagerClient));
+        scoped_ptr<bluez::BluetoothAgentManagerClient>(
+            new bluez::FakeBluetoothAgentManagerClient));
     dbus_setter->SetBluetoothGattServiceClient(
-        scoped_ptr<BluetoothGattServiceClient>(
-            new FakeBluetoothGattServiceClient));
+        scoped_ptr<bluez::BluetoothGattServiceClient>(
+            new bluez::FakeBluetoothGattServiceClient));
 
     fake_bluetooth_adapter_client_->SetSimulationIntervalMs(10);
 
@@ -196,7 +200,7 @@
     }
     discovery_sessions_.clear();
     adapter_ = nullptr;
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   // Generic callbacks
@@ -325,8 +329,8 @@
 
  protected:
   base::MessageLoop message_loop_;
-  FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_;
-  FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
+  bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_;
+  bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
   scoped_refptr<BluetoothAdapter> adapter_;
 
   int callback_count_;
@@ -354,16 +358,16 @@
   // and initializes with an existing adapter if there is one.
   EXPECT_TRUE(adapter_->IsPresent());
   EXPECT_FALSE(adapter_->IsPowered());
-  EXPECT_EQ(FakeBluetoothAdapterClient::kAdapterAddress,
+  EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress,
             adapter_->GetAddress());
   EXPECT_FALSE(adapter_->IsDiscovering());
 
   // There should be a device
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   EXPECT_EQ(2U, devices.size());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
             devices[1]->GetAddress());
 }
 
@@ -385,7 +389,7 @@
 
   // We should have had a device announced.
   EXPECT_EQ(2, observer.device_added_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
             observer.last_device_address());
 
   // Other callbacks shouldn't be called if the values are false.
@@ -412,7 +416,7 @@
 
   // We should have had a device removed.
   EXPECT_EQ(2, observer.device_removed_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
             observer.last_device_address());
 
   // Other callbacks shouldn't be called since the values are false.
@@ -435,7 +439,7 @@
   EXPECT_EQ(0, observer.present_changed_count());
 
   EXPECT_TRUE(adapter_->IsPresent());
-  EXPECT_EQ(FakeBluetoothAdapterClient::kAdapterAddress,
+  EXPECT_EQ(bluez::FakeBluetoothAdapterClient::kAdapterAddress,
             adapter_->GetAddress());
 
   // Try removing the first adapter, we should now act as if the adapter
@@ -449,7 +453,7 @@
 
   // We should have had a device removed.
   EXPECT_EQ(2, observer.device_removed_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress,
             observer.last_device_address());
 
   // Other callbacks shouldn't be called since the values are false.
@@ -720,7 +724,7 @@
   message_loop_.Run();
 
   EXPECT_EQ(2, observer.device_added_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress,
             observer.last_device_address());
 
   // Next we should get another two devices...
@@ -732,7 +736,7 @@
     message_loop_.Run();
 
   EXPECT_EQ(1, observer.device_removed_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kVanishingDeviceAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress,
             observer.last_device_address());
 }
 
@@ -752,7 +756,7 @@
 
   // Stop the timers that the simulation uses
   fake_bluetooth_device_client_->EndDiscoverySimulation(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   ASSERT_TRUE(adapter_->IsPowered());
   ASSERT_TRUE(adapter_->IsDiscovering());
@@ -946,21 +950,23 @@
 
   // Stop the timers that the simulation uses
   fake_bluetooth_device_client_->EndDiscoverySimulation(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   ASSERT_TRUE(adapter_->IsPowered());
   ASSERT_TRUE(adapter_->IsDiscovering());
 
   // Stop device discovery behind the adapter. The adapter and the observer
   // should be notified of the change and the reference count should be reset.
-  // Even though FakeBluetoothAdapterClient does its own reference counting and
+  // Even though bluez::FakeBluetoothAdapterClient does its own reference
+  // counting and
   // we called 3 BluetoothAdapter::StartDiscoverySession 3 times, the
-  // FakeBluetoothAdapterClient's count should be only 1 and a single call to
-  // FakeBluetoothAdapterClient::StopDiscovery should work.
+  // bluez::FakeBluetoothAdapterClient's count should be only 1 and a single
+  // call to
+  // bluez::FakeBluetoothAdapterClient::StopDiscovery should work.
   fake_bluetooth_adapter_client_->StopDiscovery(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(),
-      base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                 base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                base::Unretained(this)));
   message_loop_.Run();
   EXPECT_EQ(2, observer.discovering_changed_count());
   EXPECT_EQ(4, callback_count_);
@@ -993,7 +999,7 @@
     EXPECT_TRUE(discovery_sessions_[i]->IsActive());
 
   fake_bluetooth_device_client_->EndDiscoverySimulation(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   // Make the adapter disappear and appear. This will make it come back as
   // discovering. When this happens, the reference count should become and
@@ -1018,7 +1024,8 @@
   EXPECT_TRUE(observer.last_discovering());
   EXPECT_TRUE(adapter_->IsDiscovering());
 
-  // Start and stop discovery. At this point, FakeBluetoothAdapterClient has
+  // Start and stop discovery. At this point, bluez::FakeBluetoothAdapterClient
+  // has
   // a reference count that is equal to 1. Pretend that this was done by an
   // application other than us. Starting and stopping discovery will succeed
   // but it won't cause the discovery state to change.
@@ -1063,9 +1070,9 @@
   // the discovery state won't change since our BluetoothAdapter also just
   // requested it via D-Bus.
   fake_bluetooth_adapter_client_->StopDiscovery(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(),
-      base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                 base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                base::Unretained(this)));
   message_loop_.Run();
   EXPECT_EQ(5, observer.discovering_changed_count());
   EXPECT_EQ(10, callback_count_);
@@ -1124,7 +1131,7 @@
 
   // Stop the timers that the simulation uses
   fake_bluetooth_device_client_->EndDiscoverySimulation(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   ASSERT_TRUE(adapter_->IsPowered());
   ASSERT_TRUE(adapter_->IsDiscovering());
@@ -1141,9 +1148,9 @@
   // memory errors as the sessions that we explicitly deleted should get
   // cleaned up.
   fake_bluetooth_adapter_client_->StopDiscovery(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), GetCallback(),
-      base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                 base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                base::Unretained(this)));
   message_loop_.Run();
   EXPECT_EQ(2, observer.discovering_changed_count());
   EXPECT_EQ(4, callback_count_);
@@ -1176,7 +1183,7 @@
   EXPECT_EQ(0, callback_count_);
 
   fake_bluetooth_device_client_->EndDiscoverySimulation(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath));
 
   // The underlying adapter has started discovery, but our call hasn't returned
   // yet.
@@ -2092,12 +2099,13 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
 
   // Verify the other device properties.
-  EXPECT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName),
-            devices[0]->GetName());
+  EXPECT_EQ(
+      base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
+      devices[0]->GetName());
   EXPECT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[0]->GetDeviceType());
   EXPECT_TRUE(devices[0]->IsPaired());
   EXPECT_FALSE(devices[0]->IsConnected());
@@ -2124,7 +2132,7 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
   ASSERT_EQ(BluetoothDevice::DEVICE_COMPUTER, devices[0]->GetDeviceType());
 
@@ -2132,9 +2140,9 @@
   // we change the class of the device.
   TestBluetoothAdapterObserver observer(adapter_);
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   properties->bluetooth_class.ReplaceValue(0x002580);
 
@@ -2150,18 +2158,19 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
-  ASSERT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName),
-            devices[0]->GetName());
+  ASSERT_EQ(
+      base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
+      devices[0]->GetName());
 
   // Install an observer; expect the DeviceChanged method to be called when
   // we change the alias of the device.
   TestBluetoothAdapterObserver observer(adapter_);
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   static const std::string new_name("New Device Name");
   properties->alias.ReplaceValue(new_name);
@@ -2178,18 +2187,19 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
-  ASSERT_EQ(base::UTF8ToUTF16(FakeBluetoothDeviceClient::kPairedDeviceName),
-            devices[0]->GetName());
+  ASSERT_EQ(
+      base::UTF8ToUTF16(bluez::FakeBluetoothDeviceClient::kPairedDeviceName),
+      devices[0]->GetName());
 
   // Install an observer; expect the DeviceAddressChanged method to be called
   // when we change the alias of the device.
   TestBluetoothAdapterObserver observer(adapter_);
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   static const char* kNewAddress = "D9:1F:FC:11:22:33";
   properties->address.ReplaceValue(kNewAddress);
@@ -2207,7 +2217,7 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
 
   BluetoothDevice::UUIDList uuids = devices[0]->GetUUIDs();
@@ -2219,9 +2229,9 @@
   // we change the class of the device.
   TestBluetoothAdapterObserver observer(adapter_);
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   std::vector<std::string> new_uuids;
   new_uuids.push_back(uuids[0].canonical_value());
@@ -2252,12 +2262,12 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   // During discovery, rssi is a valid value (-75)
   properties->rssi.ReplaceValue(-75);
@@ -2287,12 +2297,12 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
 
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   // During discovery, tx_power is a valid value (0)
   properties->tx_power.ReplaceValue(0);
@@ -2320,7 +2330,7 @@
 
   BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
   ASSERT_EQ(2U, devices.size());
-  ASSERT_EQ(FakeBluetoothDeviceClient::kPairedDeviceAddress,
+  ASSERT_EQ(bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress,
             devices[0]->GetAddress());
 
   std::string address = devices[0]->GetAddress();
@@ -2345,7 +2355,7 @@
   DiscoverDevices();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConnectUnpairableAddress);
+      bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2362,9 +2372,9 @@
   ASSERT_FALSE(device->IsConnecting());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kConnectUnpairablePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath));
   ASSERT_TRUE(properties->trusted.value());
 
   // Install an observer; expect the DeviceRemoved method to be called
@@ -2375,12 +2385,12 @@
   EXPECT_EQ(0, error_callback_count_);
 
   EXPECT_EQ(1, observer.device_removed_count());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kConnectUnpairableAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress,
             observer.last_device_address());
 
   // GetDevices shouldn't return the device either.
   device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConnectUnpairableAddress);
+      bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
   EXPECT_FALSE(device != nullptr);
 }
 
@@ -2388,7 +2398,7 @@
   GetAdapter();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(device->IsPaired());
 
@@ -2417,7 +2427,7 @@
   DiscoverDevices();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConnectUnpairableAddress);
+      bluez::FakeBluetoothDeviceClient::kConnectUnpairableAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2441,9 +2451,9 @@
   EXPECT_FALSE(device->IsConnecting());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kConnectUnpairablePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kConnectUnpairablePath));
   EXPECT_TRUE(properties->trusted.value());
 
   // Verify is a HID device and is not connectable.
@@ -2457,7 +2467,7 @@
   GetAdapter();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(device->IsPaired());
 
@@ -2495,7 +2505,7 @@
   DiscoverDevices();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLegacyAutopairAddress);
+      bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2521,7 +2531,7 @@
   GetAdapter();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(device->IsPaired());
 
@@ -2555,7 +2565,7 @@
   GetAdapter();
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(device->IsPaired());
   ASSERT_FALSE(device->IsConnected());
@@ -2574,6 +2584,87 @@
   EXPECT_FALSE(device->IsConnected());
 }
 
+TEST_F(BluetoothChromeOSTest, PairTrustedDevice) {
+  fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
+  GetAdapter();
+
+  fake_bluetooth_device_client_->CreateDevice(
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::
+                           kConnectedTrustedNotPairedDevicePath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::
+                              kConnectedTrustedNotPairedDeviceAddress);
+  ASSERT_TRUE(device != nullptr);
+
+  // On the DBus level the device is trusted but not paired. But the current
+  // implementation of |BluetoothDevice::IsPaired()| returns true in this case.
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(
+          dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::
+                               kConnectedTrustedNotPairedDevicePath));
+  EXPECT_FALSE(properties->paired.value());
+  EXPECT_TRUE(properties->trusted.value());
+  ASSERT_TRUE(device->IsPaired());
+
+  // The |kConnectedTrustedNotPairedDevicePath| requests a passkey confirmation.
+  // Obs.: This is the flow when CrOS triggers pairing with a iOS device.
+  TestBluetoothAdapterObserver observer(adapter_);
+  TestPairingDelegate pairing_delegate;
+  adapter_->AddPairingDelegate(
+      &pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
+  device->Pair(&pairing_delegate, GetCallback(),
+               base::Bind(&BluetoothChromeOSTest::ConnectErrorCallback,
+                          base::Unretained(this)));
+  EXPECT_EQ(1, pairing_delegate.call_count_);
+  EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
+  EXPECT_EQ(123456U, pairing_delegate.last_passkey_);
+
+  // Confirm the passkey.
+  device->ConfirmPairing();
+  message_loop_.Run();
+  EXPECT_EQ(1, callback_count_);
+  EXPECT_EQ(0, error_callback_count_);
+
+  // Make sure the paired property has been set to true.
+  properties = fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+      bluez::FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath));
+  EXPECT_TRUE(properties->paired.value());
+}
+
+TEST_F(BluetoothChromeOSTest, PairAlreadyPairedDevice) {
+  GetAdapter();
+
+  fake_bluetooth_device_client_->CreateDevice(
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
+  BluetoothDevice* device = adapter_->GetDevice(
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
+  ASSERT_TRUE(device != nullptr);
+
+  // On the DBus level a device can be trusted but not paired.
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
+  EXPECT_TRUE(properties->paired.value());
+  EXPECT_TRUE(properties->trusted.value());
+  ASSERT_TRUE(device->IsPaired());
+
+  TestBluetoothAdapterObserver observer(adapter_);
+  TestPairingDelegate pairing_delegate;
+  adapter_->AddPairingDelegate(
+      &pairing_delegate, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
+  device->Pair(&pairing_delegate, GetCallback(),
+               base::Bind(&BluetoothChromeOSTest::ConnectErrorCallback,
+                          base::Unretained(this)));
+
+  // For already paired devices a call to |Pair| should succeed without calling
+  // the pairing delegate.
+  EXPECT_EQ(0, pairing_delegate.call_count_);
+  EXPECT_EQ(1, callback_count_);
+  EXPECT_EQ(0, error_callback_count_);
+}
+
 TEST_F(BluetoothChromeOSTest, PairLegacyAutopair) {
   fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
 
@@ -2583,7 +2674,7 @@
   // The Legacy Autopair device requires no PIN or Passkey to pair because
   // the daemon provides 0000 to the device for us.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLegacyAutopairAddress);
+      bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2620,9 +2711,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kLegacyAutopairPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2634,7 +2725,7 @@
 
   // Requires that we display a randomly generated PIN on the screen.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kDisplayPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kDisplayPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2673,9 +2764,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPinCodePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2688,7 +2779,7 @@
   // Requires that we display a randomly generated Passkey on the screen,
   // and notifies us as it's typed in.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kDisplayPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kDisplayPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2748,9 +2839,9 @@
   EXPECT_FALSE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kDisplayPasskeyPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kDisplayPasskeyPath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2762,7 +2853,7 @@
 
   // Requires that the user enters a PIN for them.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2802,9 +2893,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2816,7 +2907,7 @@
 
   // Requests that we confirm a displayed passkey.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2853,9 +2944,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2868,7 +2959,7 @@
   // Requires that the user enters a Passkey, this would be some kind of
   // device that has a display, but doesn't use "just works" - maybe a car?
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2904,9 +2995,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2918,8 +3009,8 @@
 
   // Uses just-works pairing, since this is an outgoing pairing, no delegate
   // interaction is required.
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kJustWorksAddress);
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2951,9 +3042,9 @@
   EXPECT_TRUE(device->IsConnectable());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
       fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath));
+          dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -2961,10 +3052,10 @@
   fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
 
   GetAdapter();
-  DiscoverDevice(FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
+  DiscoverDevice(bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
 
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kUnpairableDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kUnpairableDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -2995,11 +3086,11 @@
   fake_bluetooth_device_client_->SetSimulationIntervalMs(10);
 
   GetAdapter();
-  DiscoverDevice(FakeBluetoothDeviceClient::kVanishingDeviceAddress);
+  DiscoverDevice(bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress);
 
   // The vanishing device times out during pairing
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kVanishingDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kVanishingDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3035,7 +3126,7 @@
   // Everything seems to go according to plan with the unconnectable device;
   // it pairs, but then you can't make connections to it after.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kUnconnectableDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3067,10 +3158,9 @@
 
   // Make sure the trusted property has been set to true still (since pairing
   // worked).
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(
-              FakeBluetoothDeviceClient::kUnconnectableDevicePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kUnconnectableDevicePath));
   EXPECT_TRUE(properties->trusted.value());
 }
 
@@ -3082,7 +3172,7 @@
 
   // Reject the pairing after we receive a request for the PIN code.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3120,7 +3210,7 @@
 
   // Cancel the pairing after we receive a request for the PIN code.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3158,7 +3248,7 @@
 
   // Reject the pairing after we receive a request for the passkey.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3196,7 +3286,7 @@
 
   // Cancel the pairing after we receive a request for the passkey.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3234,7 +3324,7 @@
 
   // Reject the pairing after we receive a request for passkey confirmation.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3272,7 +3362,7 @@
 
   // Cancel the pairing after we receive a request for the passkey.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3310,7 +3400,7 @@
 
   // Cancel the pairing while we're waiting for the remote host.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLegacyAutopairAddress);
+      bluez::FakeBluetoothDeviceClient::kLegacyAutopairAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
@@ -3351,19 +3441,19 @@
 
   // Requires that we provide a PIN code.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   EXPECT_EQ(1, pairing_delegate.call_count_);
   EXPECT_EQ(1, pairing_delegate.request_pincode_count_);
@@ -3382,9 +3472,9 @@
   EXPECT_TRUE(device->IsPaired());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
   ASSERT_TRUE(properties->trusted.value());
 
   // No pairing context should remain on the device.
@@ -3405,19 +3495,19 @@
 
   // Requests that we confirm a displayed passkey.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   EXPECT_EQ(1, pairing_delegate.call_count_);
   EXPECT_EQ(1, pairing_delegate.confirm_passkey_count_);
@@ -3437,9 +3527,9 @@
   EXPECT_TRUE(device->IsPaired());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
   ASSERT_TRUE(properties->trusted.value());
 
   // No pairing context should remain on the device.
@@ -3460,19 +3550,19 @@
 
   // Requests that we provide a Passkey.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   EXPECT_EQ(1, pairing_delegate.call_count_);
   EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
@@ -3491,9 +3581,9 @@
   EXPECT_TRUE(device->IsPaired());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath));
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
   ASSERT_TRUE(properties->trusted.value());
 
   // No pairing context should remain on the device.
@@ -3515,17 +3605,17 @@
   // Uses just-works pairing so, sinec this an incoming pairing, require
   // authorization from the user.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kJustWorksAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath), true,
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true,
       GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
                                 base::Unretained(this)));
 
@@ -3546,9 +3636,9 @@
   EXPECT_TRUE(device->IsPaired());
 
   // Make sure the trusted property has been set to true.
-  FakeBluetoothDeviceClient::Properties* properties =
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
       fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath));
+          dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
   ASSERT_TRUE(properties->trusted.value());
 
   // No pairing context should remain on the device.
@@ -3565,19 +3655,19 @@
   // Requires that we provide a PIN Code, without a pairing delegate,
   // that will be rejected.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPinCodeAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPinCodeAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPinCodePath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPinCodePath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   message_loop_.Run();
 
@@ -3604,19 +3694,19 @@
   // Requests that we confirm a displayed passkey, without a pairing delegate,
   // that will be rejected.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kConfirmPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kConfirmPasskeyPath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kConfirmPasskeyPath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   message_loop_.Run();
 
@@ -3643,19 +3733,19 @@
   // Requests that we provide a displayed passkey, without a pairing delegate,
   // that will be rejected.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   message_loop_.Run();
 
@@ -3682,17 +3772,17 @@
   // Uses just-works pairing and thus requires authorization for incoming
   // pairings, without a pairing delegate, that will be rejected.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kJustWorksAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kJustWorksAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kJustWorksPath), true,
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kJustWorksPath), true,
       GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
                                 base::Unretained(this)));
 
@@ -3725,19 +3815,19 @@
 
   // Requests that we provide a Passkey.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath));
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kRequestPasskeyAddress);
+      bluez::FakeBluetoothDeviceClient::kRequestPasskeyAddress);
   ASSERT_TRUE(device != nullptr);
   ASSERT_FALSE(device->IsPaired());
 
   TestBluetoothAdapterObserver observer(adapter_);
 
   fake_bluetooth_device_client_->SimulatePairing(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kRequestPasskeyPath), true,
-      GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
-                                base::Unretained(this)));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kRequestPasskeyPath),
+      true, GetCallback(), base::Bind(&BluetoothChromeOSTest::DBusErrorCallback,
+                                      base::Unretained(this)));
 
   EXPECT_EQ(1, pairing_delegate.call_count_);
   EXPECT_EQ(1, pairing_delegate.request_passkey_count_);
@@ -3769,10 +3859,10 @@
   // Use the built-in paired device for this test, grab its Properties
   // structure so we can adjust the underlying modalias property.
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
-  FakeBluetoothDeviceClient::Properties* properties =
-      fake_bluetooth_device_client_->GetProperties(
-          dbus::ObjectPath(FakeBluetoothDeviceClient::kPairedDevicePath));
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
+  bluez::FakeBluetoothDeviceClient::Properties* properties =
+      fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
+          bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
 
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(properties != nullptr);
@@ -3820,8 +3910,8 @@
 
 TEST_F(BluetoothChromeOSTest, GetConnectionInfoForDisconnectedDevice) {
   GetAdapter();
-  BluetoothDevice* device =
-      adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress);
+  BluetoothDevice* device = adapter_->GetDevice(
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
 
   // Calling GetConnectionInfo for an unconnected device should return a result
   // in which all fields are filled with BluetoothDevice::kUnknownPower.
@@ -3836,8 +3926,8 @@
 
 TEST_F(BluetoothChromeOSTest, GetConnectionInfoForConnectedDevice) {
   GetAdapter();
-  BluetoothDevice* device =
-      adapter_->GetDevice(FakeBluetoothDeviceClient::kPairedDeviceAddress);
+  BluetoothDevice* device = adapter_->GetDevice(
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
 
   device->Connect(nullptr, GetCallback(),
                   base::Bind(&BluetoothChromeOSTest::ConnectErrorCallback,
@@ -3882,8 +3972,9 @@
   EXPECT_TRUE(adapter_->IsDiscoverable());
   EXPECT_TRUE(adapter_->IsDiscovering());
   EXPECT_EQ(2U, adapter_->GetDevices().size());
-  EXPECT_NE(nullptr, adapter_->GetDevice(
-                         FakeBluetoothDeviceClient::kPairedDeviceAddress));
+  EXPECT_NE(nullptr,
+            adapter_->GetDevice(
+                bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
   EXPECT_NE(dbus::ObjectPath(""), static_cast<BluetoothAdapterChromeOS*>(
                                       adapter_.get())->object_path());
 
@@ -3960,7 +4051,7 @@
   FakeBluetoothProfileServiceProviderDelegate profile_delegate;
   adapter_chrome_os->UseProfile(
       BluetoothUUID(), dbus::ObjectPath(""),
-      BluetoothProfileManagerClient::Options(), &profile_delegate,
+      bluez::BluetoothProfileManagerClient::Options(), &profile_delegate,
       base::Bind(&BluetoothChromeOSTest::ProfileRegisteredCallback,
                  base::Unretained(this)),
       base::Bind(&BluetoothChromeOSTest::ErrorCompletionCallback,
@@ -3980,7 +4071,8 @@
   adapter_chrome_os->DeviceRemoved(dbus::ObjectPath(""));
   adapter_chrome_os->DevicePropertyChanged(dbus::ObjectPath(""), "");
   adapter_chrome_os->InputPropertyChanged(dbus::ObjectPath(""), "");
-  // BluetoothAgentServiceProvider::Delegate omitted, dbus will be shutdown,
+  // bluez::BluetoothAgentServiceProvider::Delegate omitted, dbus will be
+  // shutdown,
   //   with the exception of Released.
   adapter_chrome_os->Released();
 
@@ -4037,7 +4129,7 @@
   // UseProfile to be set first, do so again here just before calling them.
   adapter_chrome_os->UseProfile(
       BluetoothUUID(), dbus::ObjectPath(""),
-      BluetoothProfileManagerClient::Options(), &profile_delegate,
+      bluez::BluetoothProfileManagerClient::Options(), &profile_delegate,
       base::Bind(&BluetoothChromeOSTest::ProfileRegisteredCallback,
                  base::Unretained(this)),
       base::Bind(&BluetoothChromeOSTest::ErrorCompletionCallback,
@@ -4072,8 +4164,9 @@
   EXPECT_EQ(1, error_callback_count_--) << "StartDiscoverySession error";
 
   EXPECT_EQ(0U, adapter_->GetDevices().size());
-  EXPECT_EQ(nullptr, adapter_->GetDevice(
-                         FakeBluetoothDeviceClient::kPairedDeviceAddress));
+  EXPECT_EQ(nullptr,
+            adapter_->GetDevice(
+                bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
   TestPairingDelegate pairing_delegate2;
   adapter_->AddPairingDelegate(
       &pairing_delegate2, BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
diff --git a/device/bluetooth/bluetooth_device.cc b/device/bluetooth/bluetooth_device.cc
index 3516da0a..2f1513b 100644
--- a/device/bluetooth/bluetooth_device.cc
+++ b/device/bluetooth/bluetooth_device.cc
@@ -342,4 +342,10 @@
                       base::BinaryValue::CreateWithCopiedBuffer(buffer, size));
 }
 
+void BluetoothDevice::Pair(PairingDelegate* pairing_delegate,
+                           const base::Closure& callback,
+                           const ConnectErrorCallback& error_callback) {
+  NOTREACHED();
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 1fed2155..bfbf0dc 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -330,6 +330,15 @@
                        const base::Closure& callback,
                        const ConnectErrorCallback& error_callback) = 0;
 
+  // Pairs the device. This method triggers pairing unconditially, i.e. it
+  // ignores the |IsPaired()| value.
+  //
+  // In most cases |Connect()| should be preferred. This method is only
+  // implemented on ChromeOS and Linux.
+  virtual void Pair(PairingDelegate* pairing_delegate,
+                    const base::Closure& callback,
+                    const ConnectErrorCallback& error_callback);
+
   // Sends the PIN code |pincode| to the remote device during pairing.
   //
   // PIN Codes are generally required for Bluetooth 2.0 and earlier devices
diff --git a/device/bluetooth/bluetooth_device_android.cc b/device/bluetooth/bluetooth_device_android.cc
index 244ab02..2d9c954 100644
--- a/device/bluetooth/bluetooth_device_android.cc
+++ b/device/bluetooth/bluetooth_device_android.cc
@@ -28,6 +28,8 @@
 }
 
 BluetoothDeviceAndroid::~BluetoothDeviceAndroid() {
+  Java_ChromeBluetoothDevice_onBluetoothDeviceAndroidDestruction(
+      AttachCurrentThread(), j_device_.obj());
 }
 
 bool BluetoothDeviceAndroid::UpdateAdvertisedUUIDs(jobject advertised_uuids) {
diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc
index 9acaec0..2b27d9d 100644
--- a/device/bluetooth/bluetooth_device_chromeos.cc
+++ b/device/bluetooth/bluetooth_device_chromeos.cc
@@ -11,11 +11,6 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/bus.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_gatt_connection_chromeos.h"
@@ -25,6 +20,11 @@
 #include "device/bluetooth/bluetooth_socket_chromeos.h"
 #include "device/bluetooth/bluetooth_socket_thread.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 using device::BluetoothDevice;
@@ -54,9 +54,9 @@
                    uint16* vendor_id,
                    uint16* product_id,
                    uint16* device_id) {
-  chromeos::BluetoothDeviceClient::Properties* properties =
-      chromeos::DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path);
   DCHECK(properties);
 
   std::string modalias = properties->modalias.value();
@@ -116,6 +116,25 @@
                             UMA_PAIRING_RESULT_COUNT);
 }
 
+BluetoothDevice::ConnectErrorCode DBusErrorToConnectError(
+    const std::string& error_name) {
+  BluetoothDevice::ConnectErrorCode error_code = BluetoothDevice::ERROR_UNKNOWN;
+  if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
+    error_code = BluetoothDevice::ERROR_FAILED;
+  } else if (error_name == bluetooth_device::kErrorFailed) {
+    error_code = BluetoothDevice::ERROR_FAILED;
+  } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
+    error_code = BluetoothDevice::ERROR_AUTH_FAILED;
+  } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
+    error_code = BluetoothDevice::ERROR_AUTH_CANCELED;
+  } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
+    error_code = BluetoothDevice::ERROR_AUTH_REJECTED;
+  } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
+    error_code = BluetoothDevice::ERROR_AUTH_TIMEOUT;
+  }
+  return error_code;
+}
+
 }  // namespace
 
 namespace chromeos {
@@ -132,11 +151,14 @@
       ui_task_runner_(ui_task_runner),
       socket_thread_(socket_thread),
       weak_ptr_factory_(this) {
-  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver(
+      this);
 
   // Add all known GATT services.
   const std::vector<dbus::ObjectPath> gatt_services =
-      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices();
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattServiceClient()
+          ->GetServices();
   for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin();
        it != gatt_services.end(); ++it) {
     GattServiceAdded(*it);
@@ -144,8 +166,9 @@
 }
 
 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
-  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
-      RemoveObserver(this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattServiceClient()
+      ->RemoveObserver(this);
 
   // Copy the GATT services list here and clear the original so that when we
   // send GattServiceRemoved(), GetGattServices() returns no services.
@@ -161,18 +184,18 @@
 }
 
 uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   return properties->bluetooth_class.value();
 }
 
 std::string BluetoothDeviceChromeOS::GetDeviceName() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   return properties->alias.value();
@@ -191,9 +214,9 @@
 }
 
 std::string BluetoothDeviceChromeOS::GetAddress() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   return CanonicalizeAddress(properties->address.value());
@@ -225,9 +248,9 @@
 }
 
 bool BluetoothDeviceChromeOS::IsPaired() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   // Trusted devices are devices that don't support pairing but that the
@@ -237,9 +260,9 @@
 }
 
 bool BluetoothDeviceChromeOS::IsConnected() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   return properties->connected.value();
@@ -251,9 +274,9 @@
 }
 
 bool BluetoothDeviceChromeOS::IsConnectable() const {
-  BluetoothInputClient::Properties* input_properties =
-      DBusThreadManager::Get()->GetBluetoothInputClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothInputClient::Properties* input_properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
+          object_path_);
   // GetProperties returns NULL when the device does not implement the given
   // interface. Non HID devices are normally connectable.
   if (!input_properties)
@@ -267,9 +290,9 @@
 }
 
 BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   std::vector<device::BluetoothUUID> uuids;
@@ -284,9 +307,9 @@
 }
 
 int16 BluetoothDeviceChromeOS::GetInquiryRSSI() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   if (!properties->rssi.is_valid())
@@ -296,9 +319,9 @@
 }
 
 int16 BluetoothDeviceChromeOS::GetInquiryTxPower() const {
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   DCHECK(properties);
 
   if (!properties->tx_power.is_valid())
@@ -323,7 +346,7 @@
     const ConnectionInfoCallback& callback) {
   // DBus method call should gracefully return an error if the device is not
   // currently connected.
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->GetConnInfo(
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetConnInfo(
       object_path_, base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfo,
                                weak_ptr_factory_.GetWeakPtr(), callback),
       base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfoError,
@@ -347,17 +370,29 @@
     // Initiate high-security connection with pairing.
     BeginPairing(pairing_delegate);
 
-    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-        Pair(object_path_,
-             base::Bind(&BluetoothDeviceChromeOS::OnPair,
-                        weak_ptr_factory_.GetWeakPtr(),
-                        callback, error_callback),
-             base::Bind(&BluetoothDeviceChromeOS::OnPairError,
-                        weak_ptr_factory_.GetWeakPtr(),
-                        error_callback));
+    bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair(
+        object_path_,
+        base::Bind(&BluetoothDeviceChromeOS::OnPairDuringConnect,
+                   weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
+        base::Bind(&BluetoothDeviceChromeOS::OnPairDuringConnectError,
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 }
 
+void BluetoothDeviceChromeOS::Pair(
+    BluetoothDevice::PairingDelegate* pairing_delegate,
+    const base::Closure& callback,
+    const ConnectErrorCallback& error_callback) {
+  DCHECK(pairing_delegate);
+  BeginPairing(pairing_delegate);
+
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair(
+      object_path_, base::Bind(&BluetoothDeviceChromeOS::OnPair,
+                               weak_ptr_factory_.GetWeakPtr(), callback),
+      base::Bind(&BluetoothDeviceChromeOS::OnPairError,
+                 weak_ptr_factory_.GetWeakPtr(), error_callback));
+}
+
 void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
   if (!pairing_.get())
     return;
@@ -398,12 +433,10 @@
   if (!canceled) {
     VLOG(1) << object_path_.value() << ": No pairing context or callback. "
             << "Sending explicit cancel";
-    DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-        CancelPairing(
-            object_path_,
-            base::Bind(&base::DoNothing),
-            base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
-                       weak_ptr_factory_.GetWeakPtr()));
+    bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->CancelPairing(
+        object_path_, base::Bind(&base::DoNothing),
+        base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
+                   weak_ptr_factory_.GetWeakPtr()));
   }
 
   // Since there is no callback to this method it's possible that the pairing
@@ -416,20 +449,16 @@
 void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
                                          const ErrorCallback& error_callback) {
   VLOG(1) << object_path_.value() << ": Disconnecting";
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-      Disconnect(
-          object_path_,
-          base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback),
-          base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     error_callback));
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Disconnect(
+      object_path_, base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
+                               weak_ptr_factory_.GetWeakPtr(), callback),
+      base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
+                 weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
   VLOG(1) << object_path_.value() << ": Removing device";
-  DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveDevice(
+  bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveDevice(
       adapter()->object_path(), object_path_, base::Bind(&base::DoNothing),
       base::Bind(&BluetoothDeviceChromeOS::OnForgetError,
                  weak_ptr_factory_.GetWeakPtr(), error_callback));
@@ -508,9 +537,10 @@
     return;
   }
 
-  BluetoothGattServiceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
-          GetProperties(object_path);
+  bluez::BluetoothGattServiceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattServiceClient()
+          ->GetProperties(object_path);
   DCHECK(properties);
   if (properties->device.value() != object_path_) {
     VLOG(2) << "Remote GATT service does not belong to this device.";
@@ -577,17 +607,13 @@
     const base::Closure& callback,
     const ConnectErrorCallback& error_callback) {
   VLOG(1) << object_path_.value() << ": Connecting";
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-      Connect(
-          object_path_,
-          base::Bind(&BluetoothDeviceChromeOS::OnConnect,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     after_pairing,
-                     callback),
-          base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     after_pairing,
-                     error_callback));
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Connect(
+      object_path_,
+      base::Bind(&BluetoothDeviceChromeOS::OnConnect,
+                 weak_ptr_factory_.GetWeakPtr(), after_pairing, callback),
+      base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
+                 weak_ptr_factory_.GetWeakPtr(), after_pairing,
+                 error_callback));
 }
 
 void BluetoothDeviceChromeOS::OnConnect(bool after_pairing,
@@ -646,7 +672,7 @@
   error_callback.Run(error_code);
 }
 
-void BluetoothDeviceChromeOS::OnPair(
+void BluetoothDeviceChromeOS::OnPairDuringConnect(
     const base::Closure& callback,
     const ConnectErrorCallback& error_callback) {
   VLOG(1) << object_path_.value() << ": Paired";
@@ -656,7 +682,7 @@
   ConnectInternal(true, callback, error_callback);
 }
 
-void BluetoothDeviceChromeOS::OnPairError(
+void BluetoothDeviceChromeOS::OnPairDuringConnectError(
     const ConnectErrorCallback& error_callback,
     const std::string& error_name,
     const std::string& error_message) {
@@ -672,25 +698,31 @@
   EndPairing();
 
   // Determine the error code from error_name.
-  ConnectErrorCode error_code = ERROR_UNKNOWN;
-  if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
-    error_code = ERROR_FAILED;
-  } else if (error_name == bluetooth_device::kErrorFailed) {
-    error_code = ERROR_FAILED;
-  } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
-    error_code = ERROR_AUTH_FAILED;
-  } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
-    error_code = ERROR_AUTH_CANCELED;
-  } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
-    error_code = ERROR_AUTH_REJECTED;
-  } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
-    error_code = ERROR_AUTH_TIMEOUT;
-  }
+  ConnectErrorCode error_code = DBusErrorToConnectError(error_name);
 
   RecordPairingResult(error_code);
   error_callback.Run(error_code);
 }
 
+void BluetoothDeviceChromeOS::OnPair(const base::Closure& callback) {
+  VLOG(1) << object_path_.value() << ": Paired";
+  EndPairing();
+  callback.Run();
+}
+
+void BluetoothDeviceChromeOS::OnPairError(
+    const ConnectErrorCallback& error_callback,
+    const std::string& error_name,
+    const std::string& error_message) {
+  LOG(WARNING) << object_path_.value()
+               << ": Failed to pair device: " << error_name << ": "
+               << error_message;
+  EndPairing();
+  ConnectErrorCode error_code = DBusErrorToConnectError(error_name);
+  RecordPairingResult(error_code);
+  error_callback.Run(error_code);
+}
+
 void BluetoothDeviceChromeOS::OnCancelPairingError(
     const std::string& error_name,
     const std::string& error_message) {
@@ -703,11 +735,11 @@
   // first; there's no harm in doing this and it solves any race conditions
   // with the property becoming true or false and this call happening before
   // we get the D-Bus signal about the earlier change.
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-      GetProperties(object_path_)->trusted.Set(
-          true,
-          base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
-                     weak_ptr_factory_.GetWeakPtr()));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothDeviceClient()
+      ->GetProperties(object_path_)
+      ->trusted.Set(true, base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
+                                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
diff --git a/device/bluetooth/bluetooth_device_chromeos.h b/device/bluetooth/bluetooth_device_chromeos.h
index ad300c72..358b1cd5a 100644
--- a/device/bluetooth/bluetooth_device_chromeos.h
+++ b/device/bluetooth/bluetooth_device_chromeos.h
@@ -11,11 +11,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
 
 namespace device {
 class BluetoothSocketThread;
@@ -35,7 +35,7 @@
 // thread.
 class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceChromeOS
     : public device::BluetoothDevice,
-      public BluetoothGattServiceClient::Observer {
+      public bluez::BluetoothGattServiceClient::Observer {
  public:
   // BluetoothDevice override
   uint32 GetBluetoothClass() const override;
@@ -79,6 +79,9 @@
   void CreateGattConnection(
       const GattConnectionCallback& callback,
       const ConnectErrorCallback& error_callback) override;
+  void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate,
+            const base::Closure& callback,
+            const ConnectErrorCallback& error_callback) override;
 
   // Creates a pairing object with the given delegate |pairing_delegate| and
   // establishes it as the pairing context for this device. All pairing-related
@@ -115,7 +118,7 @@
       scoped_refptr<device::BluetoothSocketThread> socket_thread);
   ~BluetoothDeviceChromeOS() override;
 
-  // BluetoothGattServiceClient::Observer overrides.
+  // bluez::BluetoothGattServiceClient::Observer overrides.
   void GattServiceAdded(const dbus::ObjectPath& object_path) override;
   void GattServiceRemoved(const dbus::ObjectPath& object_path) override;
 
@@ -142,9 +145,17 @@
                       const std::string& error_name,
                       const std::string& error_message);
 
-  // Called by dbus:: on completion of the D-Bus method call to pair the device.
-  void OnPair(const base::Closure& callback,
-              const ConnectErrorCallback& error_callback);
+  // Called by dbus:: on completion of the D-Bus method call to pair the device,
+  // made inside |Connect()|.
+  void OnPairDuringConnect(const base::Closure& callback,
+                           const ConnectErrorCallback& error_callback);
+  void OnPairDuringConnectError(const ConnectErrorCallback& error_callback,
+                                const std::string& error_name,
+                                const std::string& error_message);
+
+  // Called by dbus: on completion of the D-Bus method call to pair the device,
+  // made inside |Pair()|.
+  void OnPair(const base::Closure& callback);
   void OnPairError(const ConnectErrorCallback& error_callback,
                    const std::string& error_name,
                    const std::string& error_message);
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc
index 33c89fb..368232d1 100644
--- a/device/bluetooth/bluetooth_device_unittest.cc
+++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -180,7 +180,9 @@
   EXPECT_EQ(0, gatt_disconnection_attempt_count_);
 
   // Delete device, connection objects should all be disconnected.
+  gatt_disconnection_attempt_count_ = 0;
   DeleteDevice(device);
+  EXPECT_EQ(1, gatt_disconnection_attempt_count_);
   EXPECT_FALSE(gatt_connections_[0]->IsConnected());
   EXPECT_FALSE(gatt_connections_[1]->IsConnected());
 
diff --git a/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc
index c81acea2..cc5860d 100644
--- a/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc
@@ -5,14 +5,6 @@
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -23,6 +15,14 @@
 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
 #include "device/bluetooth/bluetooth_gatt_service.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
 #include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -41,11 +41,11 @@
 namespace {
 
 const BluetoothUUID kHeartRateMeasurementUUID(
-    FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID);
+    bluez::FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID);
 const BluetoothUUID kBodySensorLocationUUID(
-    FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID);
+    bluez::FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID);
 const BluetoothUUID kHeartRateControlPointUUID(
-    FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID);
+    bluez::FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID);
 
 // Compares GATT characteristic/descriptor values. Returns true, if the values
 // are equal.
@@ -70,34 +70,36 @@
   }
 
   void SetUp() override {
-    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
-        chromeos::DBusThreadManager::GetSetterForTesting();
-    fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient;
+    scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
+        bluez::BluezDBusManager::GetSetterForTesting();
+    fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient;
     fake_bluetooth_gatt_service_client_ =
-        new FakeBluetoothGattServiceClient;
+        new bluez::FakeBluetoothGattServiceClient;
     fake_bluetooth_gatt_characteristic_client_ =
-        new FakeBluetoothGattCharacteristicClient;
+        new bluez::FakeBluetoothGattCharacteristicClient;
     fake_bluetooth_gatt_descriptor_client_ =
-        new FakeBluetoothGattDescriptorClient;
+        new bluez::FakeBluetoothGattDescriptorClient;
     dbus_setter->SetBluetoothDeviceClient(
-        scoped_ptr<BluetoothDeviceClient>(
+        scoped_ptr<bluez::BluetoothDeviceClient>(
             fake_bluetooth_device_client_));
     dbus_setter->SetBluetoothGattServiceClient(
-        scoped_ptr<BluetoothGattServiceClient>(
+        scoped_ptr<bluez::BluetoothGattServiceClient>(
             fake_bluetooth_gatt_service_client_));
     dbus_setter->SetBluetoothGattCharacteristicClient(
-        scoped_ptr<BluetoothGattCharacteristicClient>(
+        scoped_ptr<bluez::BluetoothGattCharacteristicClient>(
             fake_bluetooth_gatt_characteristic_client_));
     dbus_setter->SetBluetoothGattDescriptorClient(
-        scoped_ptr<BluetoothGattDescriptorClient>(
+        scoped_ptr<bluez::BluetoothGattDescriptorClient>(
             fake_bluetooth_gatt_descriptor_client_));
     dbus_setter->SetBluetoothAdapterClient(
-        scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
+        scoped_ptr<bluez::BluetoothAdapterClient>(
+            new bluez::FakeBluetoothAdapterClient));
     dbus_setter->SetBluetoothInputClient(
-        scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
+        scoped_ptr<bluez::BluetoothInputClient>(
+            new bluez::FakeBluetoothInputClient));
     dbus_setter->SetBluetoothAgentManagerClient(
-        scoped_ptr<BluetoothAgentManagerClient>(
-            new FakeBluetoothAgentManagerClient));
+        scoped_ptr<bluez::BluetoothAgentManagerClient>(
+            new bluez::FakeBluetoothAgentManagerClient));
 
     GetAdapter();
 
@@ -112,7 +114,7 @@
     adapter_ = NULL;
     update_sessions_.clear();
     gatt_conn_.reset();
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   void GetAdapter() {
@@ -175,11 +177,12 @@
 
   base::MessageLoop message_loop_;
 
-  FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
-  FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_;
-  FakeBluetoothGattCharacteristicClient*
+  bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
+  bluez::FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_;
+  bluez::FakeBluetoothGattCharacteristicClient*
       fake_bluetooth_gatt_characteristic_client_;
-  FakeBluetoothGattDescriptorClient* fake_bluetooth_gatt_descriptor_client_;
+  bluez::FakeBluetoothGattDescriptorClient*
+      fake_bluetooth_gatt_descriptor_client_;
   scoped_ptr<device::BluetoothGattConnection> gatt_conn_;
   ScopedVector<BluetoothGattNotifySession> update_sessions_;
   scoped_refptr<BluetoothAdapter> adapter_;
@@ -192,10 +195,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, GattConnection) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
   ASSERT_FALSE(device->IsConnected());
   ASSERT_FALSE(gatt_conn_.get());
@@ -213,7 +216,7 @@
   EXPECT_TRUE(device->IsConnected());
   ASSERT_TRUE(gatt_conn_.get());
   EXPECT_TRUE(gatt_conn_->IsConnected());
-  EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress,
+  EXPECT_EQ(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress,
             gatt_conn_->GetDeviceAddress());
 
   gatt_conn_->Disconnect();
@@ -255,8 +258,8 @@
   EXPECT_TRUE(gatt_conn_->IsConnected());
 
   fake_bluetooth_device_client_->RemoveDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_TRUE(gatt_conn_.get());
   EXPECT_FALSE(gatt_conn_->IsConnected());
 }
@@ -265,10 +268,10 @@
   // Create a fake LE device. We store the device pointer here because this is a
   // test. It's unsafe to do this in production as the device might get deleted.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -281,14 +284,14 @@
 
   // Expose the fake Heart Rate Service.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   EXPECT_EQ(1, observer.gatt_service_added_count());
   EXPECT_EQ(0, observer.gatt_service_removed_count());
   EXPECT_FALSE(observer.last_gatt_service_id().empty());
   EXPECT_EQ(1U, device->GetGattServices().size());
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
-      observer.last_gatt_service_uuid());
+  EXPECT_EQ(BluetoothUUID(
+                bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
+            observer.last_gatt_service_uuid());
 
   BluetoothGattService* service =
       device->GetGattService(observer.last_gatt_service_id());
@@ -308,9 +311,9 @@
   EXPECT_EQ(1, observer.gatt_service_removed_count());
   EXPECT_FALSE(observer.last_gatt_service_id().empty());
   EXPECT_TRUE(device->GetGattServices().empty());
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
-      observer.last_gatt_service_uuid());
+  EXPECT_EQ(BluetoothUUID(
+                bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
+            observer.last_gatt_service_uuid());
 
   EXPECT_EQ(NULL, device->GetGattService(observer.last_gatt_service_id()));
 
@@ -318,14 +321,14 @@
   observer.last_gatt_service_uuid() = BluetoothUUID();
   observer.last_gatt_service_id().clear();
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   EXPECT_EQ(2, observer.gatt_service_added_count());
   EXPECT_EQ(1, observer.gatt_service_removed_count());
   EXPECT_FALSE(observer.last_gatt_service_id().empty());
   EXPECT_EQ(1U, device->GetGattServices().size());
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
-      observer.last_gatt_service_uuid());
+  EXPECT_EQ(BluetoothUUID(
+                bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
+            observer.last_gatt_service_uuid());
 
   // The object |service| points to should have been deallocated. |device|
   // should contain a brand new instance.
@@ -341,25 +344,25 @@
   observer.last_gatt_service_uuid() = BluetoothUUID();
   observer.last_gatt_service_id().clear();
   fake_bluetooth_device_client_->RemoveDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
 
   EXPECT_EQ(2, observer.gatt_service_added_count());
   EXPECT_EQ(2, observer.gatt_service_removed_count());
   EXPECT_FALSE(observer.last_gatt_service_id().empty());
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
-      observer.last_gatt_service_uuid());
-  EXPECT_EQ(
-      NULL, adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress));
+  EXPECT_EQ(BluetoothUUID(
+                bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
+            observer.last_gatt_service_uuid());
+  EXPECT_EQ(NULL, adapter_->GetDevice(
+                      bluez::FakeBluetoothDeviceClient::kLowEnergyAddress));
 }
 
 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicAddedAndRemoved) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -367,7 +370,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
@@ -424,10 +427,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, GattDescriptorAddedAndRemoved) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -435,7 +438,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
@@ -496,7 +499,7 @@
   observer.last_gatt_descriptor_uuid() = BluetoothUUID();
   fake_bluetooth_gatt_descriptor_client_->ExposeDescriptor(
       dbus::ObjectPath(characteristic->GetIdentifier()),
-      FakeBluetoothGattDescriptorClient::
+      bluez::FakeBluetoothGattDescriptorClient::
           kClientCharacteristicConfigurationUUID);
   EXPECT_EQ(0, observer.gatt_service_changed_count());
   EXPECT_EQ(1U, characteristic->GetDescriptors().size());
@@ -520,10 +523,10 @@
 
   // Create the fake D-Bus objects.
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   while (!fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible())
     base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsHeartRateVisible());
@@ -531,8 +534,8 @@
 
   // Create the adapter. This should create all the GATT objects.
   GetAdapter();
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
   EXPECT_EQ(1U, device->GetGattServices().size());
 
@@ -540,9 +543,9 @@
   ASSERT_TRUE(service);
   EXPECT_FALSE(service->IsLocal());
   EXPECT_TRUE(service->IsPrimary());
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
-      service->GetUUID());
+  EXPECT_EQ(BluetoothUUID(
+                bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID),
+            service->GetUUID());
   EXPECT_EQ(service, device->GetGattServices()[0]);
   EXPECT_EQ(service, device->GetGattService(service->GetIdentifier()));
   EXPECT_FALSE(service->IsLocal());
@@ -552,10 +555,9 @@
       fake_bluetooth_gatt_characteristic_client_->
           GetBodySensorLocationPath().value());
   ASSERT_TRUE(characteristic);
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
-          kBodySensorLocationUUID),
-      characteristic->GetUUID());
+  EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient::
+                              kBodySensorLocationUUID),
+            characteristic->GetUUID());
   EXPECT_FALSE(characteristic->IsLocal());
   EXPECT_TRUE(characteristic->GetDescriptors().empty());
 
@@ -563,10 +565,9 @@
       fake_bluetooth_gatt_characteristic_client_->
           GetHeartRateControlPointPath().value());
   ASSERT_TRUE(characteristic);
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
-          kHeartRateControlPointUUID),
-      characteristic->GetUUID());
+  EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient::
+                              kHeartRateControlPointUUID),
+            characteristic->GetUUID());
   EXPECT_FALSE(characteristic->IsLocal());
   EXPECT_TRUE(characteristic->GetDescriptors().empty());
 
@@ -574,10 +575,9 @@
       fake_bluetooth_gatt_characteristic_client_->
           GetHeartRateMeasurementPath().value());
   ASSERT_TRUE(characteristic);
-  EXPECT_EQ(
-      BluetoothUUID(FakeBluetoothGattCharacteristicClient::
-          kHeartRateMeasurementUUID),
-      characteristic->GetUUID());
+  EXPECT_EQ(BluetoothUUID(bluez::FakeBluetoothGattCharacteristicClient::
+                              kHeartRateMeasurementUUID),
+            characteristic->GetUUID());
   EXPECT_FALSE(characteristic->IsLocal());
   EXPECT_EQ(1U, characteristic->GetDescriptors().size());
 
@@ -590,10 +590,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicValue) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -601,7 +601,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
@@ -805,10 +805,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, GattCharacteristicProperties) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -816,7 +816,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
 
   BluetoothGattService* service =
       device->GetGattService(observer.last_gatt_service_id());
@@ -847,10 +847,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, GattDescriptorValue) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
-  BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kLowEnergyAddress);
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+  BluetoothDevice* device =
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -858,7 +858,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
@@ -970,10 +970,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, NotifySessions) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   BluetoothDevice* device =
-      adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -981,7 +981,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
@@ -1119,10 +1119,10 @@
 
 TEST_F(BluetoothGattChromeOSTest, NotifySessionsMadeInactive) {
   fake_bluetooth_device_client_->CreateDevice(
-      dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   BluetoothDevice* device =
-      adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress);
+      adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress);
   ASSERT_TRUE(device);
 
   TestBluetoothAdapterObserver observer(adapter_);
@@ -1130,7 +1130,7 @@
   // Expose the fake Heart Rate service. This will asynchronously expose
   // characteristics.
   fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
-      dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath));
+      dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
   ASSERT_EQ(1, observer.gatt_service_added_count());
 
   BluetoothGattService* service =
diff --git a/device/bluetooth/bluetooth_gatt_connection_chromeos.cc b/device/bluetooth/bluetooth_gatt_connection_chromeos.cc
index 0c46619..57aaa4d3 100644
--- a/device/bluetooth/bluetooth_gatt_connection_chromeos.cc
+++ b/device/bluetooth/bluetooth_gatt_connection_chromeos.cc
@@ -6,9 +6,9 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 namespace chromeos {
 
@@ -23,11 +23,12 @@
   DCHECK(!device_address_.empty());
   DCHECK(object_path_.IsValid());
 
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
 }
 
 BluetoothGattConnectionChromeOS::~BluetoothGattConnectionChromeOS() {
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(
+      this);
   Disconnect();
 }
 
@@ -40,9 +41,9 @@
   if (!connected_)
     return false;
 
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
   if (!properties || !properties->connected.value())
     connected_ = false;
 
@@ -82,9 +83,9 @@
   if (!connected_)
     return;
 
-  BluetoothDeviceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothDeviceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothDeviceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
+          object_path_);
 
   if (!properties) {
     connected_ = false;
diff --git a/device/bluetooth/bluetooth_gatt_connection_chromeos.h b/device/bluetooth/bluetooth_gatt_connection_chromeos.h
index 2727a235..6e40283b 100644
--- a/device/bluetooth/bluetooth_gatt_connection_chromeos.h
+++ b/device/bluetooth/bluetooth_gatt_connection_chromeos.h
@@ -9,9 +9,9 @@
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_gatt_connection.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
 
 namespace device {
 
@@ -25,7 +25,7 @@
 // Chrome OS platform.
 class BluetoothGattConnectionChromeOS
     : public device::BluetoothGattConnection,
-      public BluetoothDeviceClient::Observer {
+      public bluez::BluetoothDeviceClient::Observer {
  public:
   explicit BluetoothGattConnectionChromeOS(
       scoped_refptr<device::BluetoothAdapter> adapter,
@@ -38,8 +38,7 @@
   void Disconnect() override;
 
  private:
-
-  // chromeos::BluetoothDeviceClient::Observer overrides.
+  // bluez::Bluetooth$1Client::Observer overrides.
   void DeviceRemoved(const dbus::ObjectPath& object_path) override;
   void DevicePropertyChanged(const dbus::ObjectPath& object_path,
                              const std::string& property_name) override;
diff --git a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc
index ba7b843..02f7ed8b 100644
--- a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc
+++ b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.cc
@@ -6,11 +6,11 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_gatt_service.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 namespace chromeos {
 
@@ -32,12 +32,13 @@
   DCHECK(!characteristic_id_.empty());
   DCHECK(object_path_.IsValid());
 
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->AddObserver(
-      this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->AddObserver(this);
 }
 
 BluetoothGattNotifySessionChromeOS::~BluetoothGattNotifySessionChromeOS() {
-  DBusThreadManager::Get()
+  bluez::BluezDBusManager::Get()
       ->GetBluetoothGattCharacteristicClient()
       ->RemoveObserver(this);
   Stop(base::Bind(&base::DoNothing));
@@ -58,11 +59,12 @@
   // actually active, since the characteristic might have stopped sending
   // notifications yet this method was called before we processed the
   // observer event (e.g. because somebody else called this method in their
-  // BluetoothGattCharacteristicClient::Observer implementation, which was
+  // bluez::BluetoothGattCharacteristicClient::Observer implementation, which
+  // was
   // called before ours). Check the client to see if notifications are still
   // being sent.
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattCharacteristicClient()
           ->GetProperties(object_path_);
   if (!properties || !properties->notifying.value())
@@ -115,8 +117,8 @@
   if (!active_)
     return;
 
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattCharacteristicClient()
           ->GetProperties(object_path_);
   if (!properties) {
diff --git a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h
index 245a72f..ef6e8da4 100644
--- a/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h
+++ b/device/bluetooth/bluetooth_gatt_notify_session_chromeos.h
@@ -8,8 +8,8 @@
 #include <string>
 
 #include "base/callback.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
 
 namespace device {
 
@@ -25,7 +25,7 @@
 // BluetoothGattNotifySession for the Chrome OS platform.
 class BluetoothGattNotifySessionChromeOS
     : public device::BluetoothGattNotifySession,
-      public BluetoothGattCharacteristicClient::Observer {
+      public bluez::BluetoothGattCharacteristicClient::Observer {
  public:
   ~BluetoothGattNotifySessionChromeOS() override;
 
@@ -44,7 +44,7 @@
       const std::string& characteristic_identifier,
       const dbus::ObjectPath& characteristic_path);
 
-  // BluetoothGattCharacteristicClient::Observer overrides.
+  // bluez::BluetoothGattCharacteristicClient::Observer overrides.
   void GattCharacteristicRemoved(const dbus::ObjectPath& object_path) override;
   void GattCharacteristicPropertyChanged(
       const dbus::ObjectPath& object_path,
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.cc b/device/bluetooth/bluetooth_pairing_chromeos.cc
index dc73f6d..c69bc94 100644
--- a/device/bluetooth/bluetooth_pairing_chromeos.cc
+++ b/device/bluetooth/bluetooth_pairing_chromeos.cc
@@ -56,24 +56,25 @@
 
   if (!pincode_callback_.is_null()) {
     pincode_callback_.Run(
-        BluetoothAgentServiceProvider::Delegate::CANCELLED, "");
+        bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, "");
   }
 
   if (!passkey_callback_.is_null()) {
     passkey_callback_.Run(
-        BluetoothAgentServiceProvider::Delegate::CANCELLED, 0);
+        bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED, 0);
   }
 
   if (!confirmation_callback_.is_null()) {
     confirmation_callback_.Run(
-        BluetoothAgentServiceProvider::Delegate::CANCELLED);
+        bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED);
   }
 
   pairing_delegate_ = NULL;
 }
 
 void BluetoothPairingChromeOS::RequestPinCode(
-    const BluetoothAgentServiceProvider::Delegate::PinCodeCallback& callback) {
+    const bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback&
+        callback) {
   UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
                             UMA_PAIRING_METHOD_REQUEST_PINCODE,
                             UMA_PAIRING_METHOD_COUNT);
@@ -92,7 +93,7 @@
   if (pincode_callback_.is_null())
     return;
 
-  pincode_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS,
+  pincode_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS,
                         pincode);
   pincode_callback_.Reset();
 
@@ -120,7 +121,8 @@
 }
 
 void BluetoothPairingChromeOS::RequestPasskey(
-    const BluetoothAgentServiceProvider::Delegate::PasskeyCallback& callback) {
+    const bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback&
+        callback) {
   UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
                             UMA_PAIRING_METHOD_REQUEST_PASSKEY,
                             UMA_PAIRING_METHOD_COUNT);
@@ -139,7 +141,7 @@
   if (passkey_callback_.is_null())
     return;
 
-  passkey_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS,
+  passkey_callback_.Run(bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS,
                         passkey);
   passkey_callback_.Reset();
 
@@ -174,7 +176,7 @@
 
 void BluetoothPairingChromeOS::RequestConfirmation(
     uint32 passkey,
-    const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
+    const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
         callback) {
   UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
                             UMA_PAIRING_METHOD_CONFIRM_PASSKEY,
@@ -187,7 +189,7 @@
 }
 
 void BluetoothPairingChromeOS::RequestAuthorization(
-    const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
+    const bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
         callback) {
   UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingMethod",
                             UMA_PAIRING_METHOD_NONE,
@@ -207,7 +209,8 @@
   if (confirmation_callback_.is_null())
     return;
 
-  confirmation_callback_.Run(BluetoothAgentServiceProvider::Delegate::SUCCESS);
+  confirmation_callback_.Run(
+      bluez::BluetoothAgentServiceProvider::Delegate::SUCCESS);
   confirmation_callback_.Reset();
 
   // If this is not an outgoing connection to the device, clean up the pairing
@@ -219,12 +222,12 @@
 
 bool BluetoothPairingChromeOS::RejectPairing() {
   return RunPairingCallbacks(
-      BluetoothAgentServiceProvider::Delegate::REJECTED);
+      bluez::BluetoothAgentServiceProvider::Delegate::REJECTED);
 }
 
 bool BluetoothPairingChromeOS::CancelPairing() {
   return RunPairingCallbacks(
-      BluetoothAgentServiceProvider::Delegate::CANCELLED);
+      bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED);
 }
 
 BluetoothDevice::PairingDelegate*
@@ -239,7 +242,7 @@
 }
 
 bool BluetoothPairingChromeOS::RunPairingCallbacks(
-    BluetoothAgentServiceProvider::Delegate::Status status) {
+    bluez::BluetoothAgentServiceProvider::Delegate::Status status) {
   pairing_delegate_used_ = true;
 
   bool callback_run = false;
diff --git a/device/bluetooth/bluetooth_pairing_chromeos.h b/device/bluetooth/bluetooth_pairing_chromeos.h
index b50a328e..0a4ddb6 100644
--- a/device/bluetooth/bluetooth_pairing_chromeos.h
+++ b/device/bluetooth/bluetooth_pairing_chromeos.h
@@ -5,8 +5,8 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_PAIRING_CHROMEOS_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_PAIRING_CHROMEOS_H_
 
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
 #include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
 
 namespace chromeos {
 
@@ -36,7 +36,8 @@
   // calls on this object are translated into the appropriate response to
   // |callback|.
   void RequestPinCode(
-      const BluetoothAgentServiceProvider::Delegate::PinCodeCallback& callback);
+      const bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback&
+          callback);
 
   // Indicates whether the device is currently pairing and expecting a
   // PIN Code to be returned.
@@ -57,7 +58,8 @@
   // calls on this object are translated into the appropriate response to
   // |callback|.
   void RequestPasskey(
-      const BluetoothAgentServiceProvider::Delegate::PasskeyCallback& callback);
+      const bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback&
+          callback);
 
   // Sends the Passkey |passkey| to the remote device during pairing.
   //
@@ -79,18 +81,16 @@
   // from the current pairing delegate. The ConfirmPairing(), RejectPairing()
   // and CancelPairing() method calls on this object are translated into the
   // appropriate response to |callback|.
-  void RequestConfirmation(
-      uint32 passkey,
-      const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
-          callback);
+  void RequestConfirmation(uint32 passkey,
+                           const bluez::BluetoothAgentServiceProvider::
+                               Delegate::ConfirmationCallback& callback);
 
   // Requests authorization that the current device be allowed to pair with
   // this device from the current pairing delegate. The ConfirmPairing(),
   // RejectPairing() and CancelPairing() method calls on this object are
   // translated into the appropriate response to |callback|.
-  void RequestAuthorization(
-      const BluetoothAgentServiceProvider::Delegate::ConfirmationCallback&
-          callback);
+  void RequestAuthorization(const bluez::BluetoothAgentServiceProvider::
+                                Delegate::ConfirmationCallback& callback);
 
   // Confirms to the remote device during pairing that a passkey provided by
   // the ConfirmPasskey() delegate call is displayed on both devices.
@@ -115,7 +115,7 @@
   // Internal method to respond to the relevant callback for a RejectPairing
   // or CancelPairing call.
   bool RunPairingCallbacks(
-      BluetoothAgentServiceProvider::Delegate::Status status);
+      bluez::BluetoothAgentServiceProvider::Delegate::Status status);
 
   // The underlying BluetoothDeviceChromeOS that owns this pairing context.
   BluetoothDeviceChromeOS* device_;
@@ -131,11 +131,13 @@
 
   // During pairing these callbacks are set to those provided by method calls
   // made on the BluetoothAdapterChromeOS instance by its respective
-  // BluetoothAgentServiceProvider instance, and are called by our own
+  // bluez::BluetoothAgentServiceProvider instance, and are called by our own
   // method calls such as SetPinCode() and SetPasskey().
-  BluetoothAgentServiceProvider::Delegate::PinCodeCallback pincode_callback_;
-  BluetoothAgentServiceProvider::Delegate::PasskeyCallback passkey_callback_;
-  BluetoothAgentServiceProvider::Delegate::ConfirmationCallback
+  bluez::BluetoothAgentServiceProvider::Delegate::PinCodeCallback
+      pincode_callback_;
+  bluez::BluetoothAgentServiceProvider::Delegate::PasskeyCallback
+      passkey_callback_;
+  bluez::BluetoothAgentServiceProvider::Delegate::ConfirmationCallback
       confirmation_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothPairingChromeOS);
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc
index 5be8c788..7374f160 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.cc
@@ -8,13 +8,13 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_gatt_notify_session_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace chromeos {
@@ -44,13 +44,15 @@
       weak_ptr_factory_(this) {
   VLOG(1) << "Creating remote GATT characteristic with identifier: "
           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
-  DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
-      AddObserver(this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattDescriptorClient()
+      ->AddObserver(this);
 
   // Add all known GATT characteristic descriptors.
   const std::vector<dbus::ObjectPath>& gatt_descs =
-      DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
-          GetDescriptors();
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattDescriptorClient()
+          ->GetDescriptors();
   for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_descs.begin();
        iter != gatt_descs.end(); ++iter)
     GattDescriptorAdded(*iter);
@@ -58,8 +60,9 @@
 
 BluetoothRemoteGattCharacteristicChromeOS::
     ~BluetoothRemoteGattCharacteristicChromeOS() {
-  DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
-      RemoveObserver(this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattDescriptorClient()
+      ->RemoveObserver(this);
 
   // Clean up all the descriptors. There isn't much point in notifying service
   // observers for each descriptor that gets removed, so just delete them.
@@ -81,9 +84,10 @@
 
 device::BluetoothUUID
 BluetoothRemoteGattCharacteristicChromeOS::GetUUID() const {
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattCharacteristicClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
   return device::BluetoothUUID(properties->uuid.value());
 }
@@ -94,8 +98,8 @@
 
 const std::vector<uint8>&
 BluetoothRemoteGattCharacteristicChromeOS::GetValue() const {
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattCharacteristicClient()
           ->GetProperties(object_path_);
 
@@ -111,9 +115,10 @@
 
 device::BluetoothGattCharacteristic::Properties
 BluetoothRemoteGattCharacteristicChromeOS::GetProperties() const {
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattCharacteristicClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
 
   Properties props = PROPERTY_NONE;
@@ -154,8 +159,8 @@
 }
 
 bool BluetoothRemoteGattCharacteristicChromeOS::IsNotifying() const {
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattCharacteristicClient()
           ->GetProperties(object_path_);
   DCHECK(properties);
@@ -201,10 +206,12 @@
           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
           << ".";
 
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->ReadValue(
-      object_path_, callback,
-      base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError,
-                 weak_ptr_factory_.GetWeakPtr(), error_callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->ReadValue(
+          object_path_, callback,
+          base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError,
+                     weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothRemoteGattCharacteristicChromeOS::WriteRemoteCharacteristic(
@@ -215,13 +222,12 @@
           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
           << ", with value: " << new_value << ".";
 
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->WriteValue(
-      object_path_,
-      new_value,
-      callback,
-      base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 error_callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->WriteValue(
+          object_path_, new_value, callback,
+          base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnError,
+                     weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothRemoteGattCharacteristicChromeOS::StartNotifySession(
@@ -267,15 +273,16 @@
   }
 
   notify_call_pending_ = true;
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->StartNotify(
-      object_path_,
-      base::Bind(
-          &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifySuccess,
-          weak_ptr_factory_.GetWeakPtr(),
-          callback),
-      base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifyError,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 error_callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->StartNotify(
+          object_path_,
+          base::Bind(
+              &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifySuccess,
+              weak_ptr_factory_.GetWeakPtr(), callback),
+          base::Bind(
+              &BluetoothRemoteGattCharacteristicChromeOS::OnStartNotifyError,
+              weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothRemoteGattCharacteristicChromeOS::RemoveNotifySession(
@@ -304,15 +311,16 @@
 
   DCHECK(num_notify_sessions_ == 1);
   notify_call_pending_ = true;
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->StopNotify(
-      object_path_,
-      base::Bind(
-          &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifySuccess,
-          weak_ptr_factory_.GetWeakPtr(),
-          callback),
-      base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifyError,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->StopNotify(
+          object_path_,
+          base::Bind(
+              &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifySuccess,
+              weak_ptr_factory_.GetWeakPtr(), callback),
+          base::Bind(
+              &BluetoothRemoteGattCharacteristicChromeOS::OnStopNotifyError,
+              weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void BluetoothRemoteGattCharacteristicChromeOS::GattDescriptorAdded(
@@ -323,9 +331,10 @@
     return;
   }
 
-  BluetoothGattDescriptorClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
-          GetProperties(object_path);
+  bluez::BluetoothGattDescriptorClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattDescriptorClient()
+          ->GetProperties(object_path);
   DCHECK(properties);
   if (properties->characteristic.value() != object_path_) {
     VLOG(3) << "Remote GATT descriptor does not belong to this characteristic.";
@@ -375,8 +384,8 @@
     return;
   }
 
-  BluetoothGattDescriptorClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattDescriptorClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattDescriptorClient()
           ->GetProperties(object_path);
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h
index a23a1178..361b3197 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h
@@ -12,10 +12,10 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
 
 namespace device {
 
@@ -34,7 +34,7 @@
 // platform.
 class BluetoothRemoteGattCharacteristicChromeOS
     : public device::BluetoothGattCharacteristic,
-      public BluetoothGattDescriptorClient::Observer {
+      public bluez::BluetoothGattDescriptorClient::Observer {
  public:
   // device::BluetoothGattCharacteristic overrides.
   std::string GetIdentifier() const override;
@@ -78,7 +78,7 @@
       const dbus::ObjectPath& object_path);
   ~BluetoothRemoteGattCharacteristicChromeOS() override;
 
-  // BluetoothGattDescriptorClient::Observer overrides.
+  // bluez::BluetoothGattDescriptorClient::Observer overrides.
   void GattDescriptorAdded(const dbus::ObjectPath& object_path) override;
   void GattDescriptorRemoved(const dbus::ObjectPath& object_path) override;
   void GattDescriptorPropertyChanged(const dbus::ObjectPath& object_path,
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc
index da38566..f864c3b 100644
--- a/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.cc
@@ -7,10 +7,10 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 namespace chromeos {
 
@@ -47,9 +47,10 @@
 }
 
 device::BluetoothUUID BluetoothRemoteGattDescriptorChromeOS::GetUUID() const {
-  BluetoothGattDescriptorClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothGattDescriptorClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattDescriptorClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
   return device::BluetoothUUID(properties->uuid.value());
 }
@@ -60,8 +61,8 @@
 
 const std::vector<uint8>&
 BluetoothRemoteGattDescriptorChromeOS::GetValue() const {
-  BluetoothGattDescriptorClient::Properties* properties =
-      DBusThreadManager::Get()
+  bluez::BluetoothGattDescriptorClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
           ->GetBluetoothGattDescriptorClient()
           ->GetProperties(object_path_);
 
@@ -89,7 +90,7 @@
           << "descriptor: " << GetIdentifier() << ", UUID: "
           << GetUUID().canonical_value();
 
-  DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->ReadValue(
+  bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient()->ReadValue(
       object_path_, callback,
       base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError,
                  weak_ptr_factory_.GetWeakPtr(), error_callback));
@@ -104,13 +105,11 @@
           << GetUUID().canonical_value() << ", with value: "
           << new_value << ".";
 
-  DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->WriteValue(
-      object_path_,
-      new_value,
-      callback,
-      base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 error_callback));
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattDescriptorClient()
+      ->WriteValue(object_path_, new_value, callback,
+                   base::Bind(&BluetoothRemoteGattDescriptorChromeOS::OnError,
+                              weak_ptr_factory_.GetWeakPtr(), error_callback));
 }
 
 void BluetoothRemoteGattDescriptorChromeOS::OnError(
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc
index cea23ec3..8a57fa2 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc
@@ -6,12 +6,12 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_device_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 
 namespace chromeos {
 
@@ -41,24 +41,29 @@
           << object_path.value() << ", UUID: " << GetUUID().canonical_value();
   DCHECK(adapter_);
 
-  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-      AddObserver(this);
+  bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver(
+      this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->AddObserver(this);
 
   // Add all known GATT characteristics.
   const std::vector<dbus::ObjectPath>& gatt_chars =
-      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-          GetCharacteristics();
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattCharacteristicClient()
+          ->GetCharacteristics();
   for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin();
        iter != gatt_chars.end(); ++iter)
     GattCharacteristicAdded(*iter);
 }
 
 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
-  DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
-      RemoveObserver(this);
-  DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-      RemoveObserver(this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattServiceClient()
+      ->RemoveObserver(this);
+  bluez::BluezDBusManager::Get()
+      ->GetBluetoothGattCharacteristicClient()
+      ->RemoveObserver(this);
 
   // Clean up all the characteristics. Copy the characteristics list here and
   // clear the original so that when we send GattCharacteristicRemoved(),
@@ -79,9 +84,10 @@
 }
 
 device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const {
-  BluetoothGattServiceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothGattServiceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattServiceClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
   return device::BluetoothUUID(properties->uuid.value());
 }
@@ -91,9 +97,10 @@
 }
 
 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
-  BluetoothGattServiceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
-          GetProperties(object_path_);
+  bluez::BluetoothGattServiceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattServiceClient()
+          ->GetProperties(object_path_);
   DCHECK(properties);
   return properties->primary.value();
 }
@@ -227,9 +234,10 @@
 
   VLOG(1) << "Service property changed: \"" << property_name << "\", "
           << object_path.value();
-  BluetoothGattServiceClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
-          object_path);
+  bluez::BluetoothGattServiceClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattServiceClient()
+          ->GetProperties(object_path);
   DCHECK(properties);
 
   if (property_name != properties->characteristics.name()) {
@@ -255,9 +263,10 @@
     return;
   }
 
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-          GetProperties(object_path);
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattCharacteristicClient()
+          ->GetProperties(object_path);
   DCHECK(properties);
   if (properties->service.value() != object_path_) {
     VLOG(2) << "Remote GATT characteristic does not belong to this service.";
@@ -312,9 +321,10 @@
   // "Characteristic Extended Properties" descriptor. In this case, kick off
   // a service changed observer event to let observers refresh the
   // characteristics.
-  BluetoothGattCharacteristicClient::Properties* properties =
-      DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
-          GetProperties(object_path);
+  bluez::BluetoothGattCharacteristicClient::Properties* properties =
+      bluez::BluezDBusManager::Get()
+          ->GetBluetoothGattCharacteristicClient()
+          ->GetProperties(object_path);
 
   DCHECK(properties);
   DCHECK(adapter_);
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h
index 9aa8fdd..bc35cb7 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h
@@ -12,11 +12,11 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_gatt_service.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
 
 namespace device {
 
@@ -36,8 +36,8 @@
 // for remote GATT services on the Chrome OS platform.
 class BluetoothRemoteGattServiceChromeOS
     : public device::BluetoothGattService,
-      public BluetoothGattServiceClient::Observer,
-      public BluetoothGattCharacteristicClient::Observer {
+      public bluez::BluetoothGattServiceClient::Observer,
+      public bluez::BluetoothGattCharacteristicClient::Observer {
  public:
   // device::BluetoothGattService overrides.
   std::string GetIdentifier() const override;
@@ -104,11 +104,11 @@
                                      const dbus::ObjectPath& object_path);
   ~BluetoothRemoteGattServiceChromeOS() override;
 
-  // BluetoothGattServiceClient::Observer override.
+  // bluez::BluetoothGattServiceClient::Observer override.
   void GattServicePropertyChanged(const dbus::ObjectPath& object_path,
                                   const std::string& property_name) override;
 
-  // BluetoothGattCharacteristicClient::Observer override.
+  // bluez::BluetoothGattCharacteristicClient::Observer override.
   void GattCharacteristicAdded(const dbus::ObjectPath& object_path) override;
   void GattCharacteristicRemoved(const dbus::ObjectPath& object_path) override;
   void GattCharacteristicPropertyChanged(
diff --git a/device/bluetooth/bluetooth_socket_chromeos.cc b/device/bluetooth/bluetooth_socket_chromeos.cc
index da15484..b3e357d0 100644
--- a/device/bluetooth/bluetooth_socket_chromeos.cc
+++ b/device/bluetooth/bluetooth_socket_chromeos.cc
@@ -20,10 +20,6 @@
 #include "base/task_runner_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/worker_pool.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/bus.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
@@ -35,6 +31,10 @@
 #include "device/bluetooth/bluetooth_socket.h"
 #include "device/bluetooth/bluetooth_socket_net.h"
 #include "device/bluetooth/bluetooth_socket_thread.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -107,7 +107,7 @@
   device_address_ = device->GetAddress();
   device_path_ = device->object_path();
   uuid_ = uuid;
-  options_.reset(new BluetoothProfileManagerClient::Options());
+  options_.reset(new bluez::BluetoothProfileManagerClient::Options());
   if (security_level == SECURITY_LEVEL_LOW)
     options_->require_authentication.reset(new bool(false));
 
@@ -135,7 +135,7 @@
   adapter_->AddObserver(this);
 
   uuid_ = uuid;
-  options_.reset(new BluetoothProfileManagerClient::Options());
+  options_.reset(new bluez::BluetoothProfileManagerClient::Options());
   if (service_options.name)
     options_->name.reset(new std::string(*service_options.name));
 
@@ -165,7 +165,7 @@
   // In the case below, where an asynchronous task gets posted on the socket
   // thread in BluetoothSocketNet::Close, a reference will be held to this
   // socket by the callback. This may cause the BluetoothAdapter to outlive
-  // DBusThreadManager during shutdown if that callback executes too late.
+  // BluezDBusManager during shutdown if that callback executes too late.
   if (adapter_.get()) {
     adapter_->RemoveObserver(this);
     adapter_ = nullptr;
@@ -264,7 +264,7 @@
   VLOG(1) << uuid_.canonical_value() << ": Got profile, connecting to "
           << device_path_.value();
 
-  DBusThreadManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
+  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
       device_path_, uuid_.canonical_value(),
       base::Bind(&BluetoothSocketChromeOS::OnConnectProfile, this,
                  success_callback),
@@ -355,7 +355,7 @@
 void BluetoothSocketChromeOS::NewConnection(
     const dbus::ObjectPath& device_path,
     scoped_ptr<dbus::FileDescriptor> fd,
-    const BluetoothProfileServiceProvider::Delegate::Options& options,
+    const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
     const ConfirmationCallback& callback) {
   DCHECK(ui_task_runner()->RunsTasksOnCurrentThread());
 
@@ -460,7 +460,7 @@
 void BluetoothSocketChromeOS::DoNewConnection(
     const dbus::ObjectPath& device_path,
     scoped_ptr<dbus::FileDescriptor> fd,
-    const BluetoothProfileServiceProvider::Delegate::Options& options,
+    const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
     const ConfirmationCallback& callback) {
   DCHECK(socket_thread()->task_runner()->RunsTasksOnCurrentThread());
   base::ThreadRestrictions::AssertIOAllowed();
diff --git a/device/bluetooth/bluetooth_socket_chromeos.h b/device/bluetooth/bluetooth_socket_chromeos.h
index 98d4d02..a1c76ee2 100644
--- a/device/bluetooth/bluetooth_socket_chromeos.h
+++ b/device/bluetooth/bluetooth_socket_chromeos.h
@@ -10,14 +10,14 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluetooth_socket.h"
 #include "device/bluetooth/bluetooth_socket_net.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
 namespace dbus {
 class FileDescriptor;
@@ -33,10 +33,10 @@
 // Chrome OS platform.
 //
 // This class is not thread-safe, but is only called from the UI thread.
-class CHROMEOS_EXPORT BluetoothSocketChromeOS
+class DEVICE_BLUETOOTH_EXPORT BluetoothSocketChromeOS
     : public device::BluetoothSocketNet,
       public device::BluetoothAdapter::Observer,
-      public BluetoothProfileServiceProvider::Delegate {
+      public bluez::BluetoothProfileServiceProvider::Delegate {
  public:
   enum SecurityLevel {
     SECURITY_LEVEL_LOW,
@@ -112,12 +112,12 @@
   void OnInternalRegisterProfile(BluetoothAdapterProfileChromeOS* profile);
   void OnInternalRegisterProfileError(const std::string& error_message);
 
-  // BluetoothProfileServiceProvider::Delegate:
+  // bluez::BluetoothProfileServiceProvider::Delegate:
   void Released() override;
   void NewConnection(
       const dbus::ObjectPath& device_path,
       scoped_ptr<dbus::FileDescriptor> fd,
-      const BluetoothProfileServiceProvider::Delegate::Options& options,
+      const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
       const ConfirmationCallback& callback) override;
   void RequestDisconnection(const dbus::ObjectPath& device_path,
                             const ConfirmationCallback& callback) override;
@@ -131,7 +131,7 @@
   void DoNewConnection(
       const dbus::ObjectPath& device_path,
       scoped_ptr<dbus::FileDescriptor> fd,
-      const BluetoothProfileServiceProvider::Delegate::Options& options,
+      const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
       const ConfirmationCallback& callback);
 
   // Method run on the UI thread after a new connection has been accepted and
@@ -166,7 +166,7 @@
   device::BluetoothUUID uuid_;
 
   // Copy of the profile options used for registering the profile.
-  scoped_ptr<BluetoothProfileManagerClient::Options> options_;
+  scoped_ptr<bluez::BluetoothProfileManagerClient::Options> options_;
 
   // The profile registered with the adapter for this socket.
   BluetoothAdapterProfileChromeOS* profile_;
@@ -188,7 +188,7 @@
 
     dbus::ObjectPath device_path;
     scoped_ptr<dbus::FileDescriptor> fd;
-    BluetoothProfileServiceProvider::Delegate::Options options;
+    bluez::BluetoothProfileServiceProvider::Delegate::Options options;
     ConfirmationCallback callback;
     bool accepting;
     bool cancelled;
diff --git a/device/bluetooth/bluetooth_socket_chromeos_unittest.cc b/device/bluetooth/bluetooth_socket_chromeos_unittest.cc
index 697365d5..0bdc3bef 100644
--- a/device/bluetooth/bluetooth_socket_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_socket_chromeos_unittest.cc
@@ -5,14 +5,6 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -22,6 +14,14 @@
 #include "device/bluetooth/bluetooth_socket_chromeos.h"
 #include "device/bluetooth/bluetooth_socket_thread.h"
 #include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -51,24 +51,27 @@
         last_reason_(BluetoothSocket::kSystemError) {}
 
   void SetUp() override {
-    scoped_ptr<DBusThreadManagerSetter> dbus_setter =
-        DBusThreadManager::GetSetterForTesting();
+    scoped_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
+        bluez::BluezDBusManager::GetSetterForTesting();
 
     dbus_setter->SetBluetoothAdapterClient(
-        scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient));
+        scoped_ptr<bluez::BluetoothAdapterClient>(
+            new bluez::FakeBluetoothAdapterClient));
     dbus_setter->SetBluetoothAgentManagerClient(
-        scoped_ptr<BluetoothAgentManagerClient>(
-            new FakeBluetoothAgentManagerClient));
+        scoped_ptr<bluez::BluetoothAgentManagerClient>(
+            new bluez::FakeBluetoothAgentManagerClient));
     dbus_setter->SetBluetoothDeviceClient(
-        scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
+        scoped_ptr<bluez::BluetoothDeviceClient>(
+            new bluez::FakeBluetoothDeviceClient));
     dbus_setter->SetBluetoothGattServiceClient(
-        scoped_ptr<BluetoothGattServiceClient>(
-            new FakeBluetoothGattServiceClient));
+        scoped_ptr<bluez::BluetoothGattServiceClient>(
+            new bluez::FakeBluetoothGattServiceClient));
     dbus_setter->SetBluetoothInputClient(
-        scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
+        scoped_ptr<bluez::BluetoothInputClient>(
+            new bluez::FakeBluetoothInputClient));
     dbus_setter->SetBluetoothProfileManagerClient(
-        scoped_ptr<BluetoothProfileManagerClient>(
-            new FakeBluetoothProfileManagerClient));
+        scoped_ptr<bluez::BluetoothProfileManagerClient>(
+            new bluez::FakeBluetoothProfileManagerClient));
 
     BluetoothSocketThread::Get();
 
@@ -91,7 +94,7 @@
   void TearDown() override {
     adapter_ = nullptr;
     BluetoothSocketThread::CleanupForTesting();
-    DBusThreadManager::Shutdown();
+    bluez::BluezDBusManager::Shutdown();
   }
 
   void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
@@ -183,11 +186,11 @@
 
 TEST_F(BluetoothSocketChromeOSTest, Connect) {
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
 
   device->ConnectToService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback,
                  base::Unretained(this)),
       base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
@@ -294,7 +297,7 @@
 
 TEST_F(BluetoothSocketChromeOSTest, Listen) {
   adapter_->CreateRfcommService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       BluetoothAdapter::ServiceOptions(),
       base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
                  base::Unretained(this)),
@@ -319,17 +322,16 @@
   //
   // This is done before the Accept() call to simulate a pending call at the
   // point that Accept() is called.
-  FakeBluetoothDeviceClient* fake_bluetooth_device_client =
-      static_cast<FakeBluetoothDeviceClient*>(
-          DBusThreadManager::Get()->GetBluetoothDeviceClient());
+  bluez::FakeBluetoothDeviceClient* fake_bluetooth_device_client =
+      static_cast<bluez::FakeBluetoothDeviceClient*>(
+          bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient());
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
   ASSERT_TRUE(device != nullptr);
   fake_bluetooth_device_client->ConnectProfile(
       static_cast<BluetoothDeviceChromeOS*>(device)->object_path(),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
-      base::Bind(&base::DoNothing),
-      base::Bind(&DoNothingDBusErrorCallback));
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
+      base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback));
 
   message_loop_.RunUntilIdle();
 
@@ -375,9 +377,8 @@
 
   fake_bluetooth_device_client->ConnectProfile(
       static_cast<BluetoothDeviceChromeOS*>(device)->object_path(),
-      FakeBluetoothProfileManagerClient::kRfcommUuid,
-      base::Bind(&base::DoNothing),
-      base::Bind(&DoNothingDBusErrorCallback));
+      bluez::FakeBluetoothProfileManagerClient::kRfcommUuid,
+      base::Bind(&base::DoNothing), base::Bind(&DoNothingDBusErrorCallback));
 
   message_loop_.Run();
 
@@ -416,13 +417,13 @@
 TEST_F(BluetoothSocketChromeOSTest, ListenBeforeAdapterStart) {
   // Start off with an invisible adapter, register the profile, then make
   // the adapter visible.
-  FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
-      static_cast<FakeBluetoothAdapterClient*>(
-          DBusThreadManager::Get()->GetBluetoothAdapterClient());
+  bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
+      static_cast<bluez::FakeBluetoothAdapterClient*>(
+          bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient());
   fake_bluetooth_adapter_client->SetVisible(false);
 
   adapter_->CreateRfcommService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       BluetoothAdapter::ServiceOptions(),
       base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
                  base::Unretained(this)),
@@ -441,12 +442,14 @@
   error_callback_count_ = 0;
 
   // But there shouldn't be a profile registered yet.
-  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
-      static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
-  FakeBluetoothProfileServiceProvider* profile_service_provider =
+  bluez::FakeBluetoothProfileManagerClient*
+      fake_bluetooth_profile_manager_client =
+          static_cast<bluez::FakeBluetoothProfileManagerClient*>(
+              bluez::BluezDBusManager::Get()
+                  ->GetBluetoothProfileManagerClient());
+  bluez::FakeBluetoothProfileServiceProvider* profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
-          FakeBluetoothProfileManagerClient::kRfcommUuid);
+          bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
   EXPECT_TRUE(profile_service_provider == nullptr);
 
   // Make the adapter visible. This should register a profile.
@@ -456,7 +459,7 @@
 
   profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
-          FakeBluetoothProfileManagerClient::kRfcommUuid);
+          bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
   EXPECT_TRUE(profile_service_provider != nullptr);
 
   // Cleanup the socket.
@@ -471,12 +474,12 @@
 
 TEST_F(BluetoothSocketChromeOSTest, ListenAcrossAdapterRestart) {
   // The fake adapter starts off visible by default.
-  FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
-      static_cast<FakeBluetoothAdapterClient*>(
-          DBusThreadManager::Get()->GetBluetoothAdapterClient());
+  bluez::FakeBluetoothAdapterClient* fake_bluetooth_adapter_client =
+      static_cast<bluez::FakeBluetoothAdapterClient*>(
+          bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient());
 
   adapter_->CreateRfcommService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       BluetoothAdapter::ServiceOptions(),
       base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
                  base::Unretained(this)),
@@ -495,12 +498,14 @@
   error_callback_count_ = 0;
 
   // Make sure the profile was registered with the daemon.
-  FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
-      static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
-  FakeBluetoothProfileServiceProvider* profile_service_provider =
+  bluez::FakeBluetoothProfileManagerClient*
+      fake_bluetooth_profile_manager_client =
+          static_cast<bluez::FakeBluetoothProfileManagerClient*>(
+              bluez::BluezDBusManager::Get()
+                  ->GetBluetoothProfileManagerClient());
+  bluez::FakeBluetoothProfileServiceProvider* profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
-          FakeBluetoothProfileManagerClient::kRfcommUuid);
+          bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
   EXPECT_TRUE(profile_service_provider != nullptr);
 
   // Make the adapter invisible, and fiddle with the profile fake to unregister
@@ -516,7 +521,7 @@
 
   profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(
-          FakeBluetoothProfileManagerClient::kRfcommUuid);
+          bluez::FakeBluetoothProfileManagerClient::kRfcommUuid);
   EXPECT_TRUE(profile_service_provider != nullptr);
 
   // Cleanup the socket.
@@ -531,11 +536,11 @@
 
 TEST_F(BluetoothSocketChromeOSTest, PairedConnectFails) {
   BluetoothDevice* device = adapter_->GetDevice(
-      FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress);
+      bluez::FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress);
   ASSERT_TRUE(device != nullptr);
 
   device->ConnectToService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback,
                  base::Unretained(this)),
       base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
@@ -547,7 +552,7 @@
   EXPECT_TRUE(last_socket_.get() == nullptr);
 
   device->ConnectToService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       base::Bind(&BluetoothSocketChromeOSTest::ConnectToServiceSuccessCallback,
                  base::Unretained(this)),
       base::Bind(&BluetoothSocketChromeOSTest::ErrorCallback,
@@ -561,7 +566,7 @@
 
 TEST_F(BluetoothSocketChromeOSTest, SocketListenTwice) {
   adapter_->CreateRfcommService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       BluetoothAdapter::ServiceOptions(),
       base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
                  base::Unretained(this)),
@@ -594,7 +599,7 @@
   EXPECT_EQ(1U, error_callback_count_);
 
   adapter_->CreateRfcommService(
-      BluetoothUUID(FakeBluetoothProfileManagerClient::kRfcommUuid),
+      BluetoothUUID(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid),
       BluetoothAdapter::ServiceOptions(),
       base::Bind(&BluetoothSocketChromeOSTest::CreateServiceSuccessCallback,
                  base::Unretained(this)),
diff --git a/chromeos/dbus/bluetooth_adapter_client.cc b/device/bluetooth/dbus/bluetooth_adapter_client.cc
similarity index 88%
rename from chromeos/dbus/bluetooth_adapter_client.cc
rename to device/bluetooth/dbus/bluetooth_adapter_client.cc
index 741dc03..26081ea3 100644
--- a/chromeos/dbus/bluetooth_adapter_client.cc
+++ b/device/bluetooth/dbus/bluetooth_adapter_client.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 "chromeos/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -12,13 +12,11 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
-BluetoothAdapterClient::DiscoveryFilter::DiscoveryFilter() {
-}
+BluetoothAdapterClient::DiscoveryFilter::DiscoveryFilter() {}
 
-BluetoothAdapterClient::DiscoveryFilter::~DiscoveryFilter() {
-}
+BluetoothAdapterClient::DiscoveryFilter::~DiscoveryFilter() {}
 
 void BluetoothAdapterClient::DiscoveryFilter::CopyFrom(
     const DiscoveryFilter& filter) {
@@ -69,14 +67,11 @@
   RegisterProperty(bluetooth_adapter::kModaliasProperty, &modalias);
 }
 
-BluetoothAdapterClient::Properties::~Properties() {
-}
-
+BluetoothAdapterClient::Properties::~Properties() {}
 
 // The BluetoothAdapterClient implementation used in production.
-class BluetoothAdapterClientImpl
-    : public BluetoothAdapterClient,
-      public dbus::ObjectManager::Interface {
+class BluetoothAdapterClientImpl : public BluetoothAdapterClient,
+                                   public dbus::ObjectManager::Interface {
  public:
   BluetoothAdapterClientImpl()
       : object_manager_(NULL), weak_ptr_factory_(this) {}
@@ -110,29 +105,24 @@
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
     Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
+        object_proxy, interface_name,
         base::Bind(&BluetoothAdapterClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+                   weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
   // BluetoothAdapterClient override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_adapter::kBluetoothAdapterInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path, bluetooth_adapter::kBluetoothAdapterInterface));
   }
 
   // BluetoothAdapterClient override.
   void StartDiscovery(const dbus::ObjectPath& object_path,
                       const base::Closure& callback,
                       const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_adapter::kBluetoothAdapterInterface,
-        bluetooth_adapter::kStartDiscovery);
+    dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface,
+                                 bluetooth_adapter::kStartDiscovery);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -142,8 +132,7 @@
     }
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAdapterClientImpl::OnError,
@@ -154,9 +143,8 @@
   void StopDiscovery(const dbus::ObjectPath& object_path,
                      const base::Closure& callback,
                      const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_adapter::kBluetoothAdapterInterface,
-        bluetooth_adapter::kStopDiscovery);
+    dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface,
+                                 bluetooth_adapter::kStopDiscovery);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -166,8 +154,7 @@
     }
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAdapterClientImpl::OnError,
@@ -179,9 +166,8 @@
                     const dbus::ObjectPath& device_path,
                     const base::Closure& callback,
                     const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_adapter::kBluetoothAdapterInterface,
-        bluetooth_adapter::kRemoveDevice);
+    dbus::MethodCall method_call(bluetooth_adapter::kBluetoothAdapterInterface,
+                                 bluetooth_adapter::kRemoveDevice);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendObjectPath(device_path);
@@ -194,8 +180,7 @@
     }
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAdapterClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAdapterClientImpl::OnError,
@@ -318,8 +303,7 @@
   }
 
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -350,20 +334,17 @@
   // than we do.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<BluetoothAdapterClientImpl>
-      weak_ptr_factory_;
+  base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl);
 };
 
-BluetoothAdapterClient::BluetoothAdapterClient() {
-}
+BluetoothAdapterClient::BluetoothAdapterClient() {}
 
-BluetoothAdapterClient::~BluetoothAdapterClient() {
-}
+BluetoothAdapterClient::~BluetoothAdapterClient() {}
 
 BluetoothAdapterClient* BluetoothAdapterClient::Create() {
   return new BluetoothAdapterClientImpl;
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_adapter_client.h b/device/bluetooth/dbus/bluetooth_adapter_client.h
similarity index 93%
rename from chromeos/dbus/bluetooth_adapter_client.h
rename to device/bluetooth/dbus/bluetooth_adapter_client.h
index 45301277..5a024eb 100644
--- a/chromeos/dbus/bluetooth_adapter_client.h
+++ b/device/bluetooth/dbus/bluetooth_adapter_client.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 CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,16 +11,16 @@
 #include "base/callback.h"
 #include "base/observer_list.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothAdapterClient is used to communicate with objects representing
 // local Bluetooth Adapters.
-class CHROMEOS_EXPORT BluetoothAdapterClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterClient : public BluezDBusClient {
  public:
   // A DiscoveryFilter represents a filter passed to the SetDiscoveryFilter
   // method.
@@ -84,7 +84,7 @@
 
     // List of 128-bit UUIDs that represent the available local services.
     // Read-only.
-    dbus::Property<std::vector<std::string> > uuids;
+    dbus::Property<std::vector<std::string>> uuids;
 
     // Local Device ID information in Linux kernel modalias format. Read-only.
     dbus::Property<std::string> modalias;
@@ -179,6 +179,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/bluetooth_agent_manager_client.cc
similarity index 84%
rename from chromeos/dbus/bluetooth_agent_manager_client.cc
rename to device/bluetooth/dbus/bluetooth_agent_manager_client.cc
index af7bb16..6caee9b 100644
--- a/chromeos/dbus/bluetooth_agent_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_agent_manager_client.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 "chromeos/dbus/bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -11,14 +11,13 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char BluetoothAgentManagerClient::kNoResponseError[] =
     "org.chromium.Error.NoResponse";
 
 // The BluetoothAgentManagerClient implementation used in production.
-class BluetoothAgentManagerClientImpl
-    : public BluetoothAgentManagerClient {
+class BluetoothAgentManagerClientImpl : public BluetoothAgentManagerClient {
  public:
   BluetoothAgentManagerClientImpl() : weak_ptr_factory_(this) {}
 
@@ -30,16 +29,15 @@
                      const base::Closure& callback,
                      const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(
-    bluetooth_agent_manager::kBluetoothAgentManagerInterface,
-    bluetooth_agent_manager::kRegisterAgent);
+        bluetooth_agent_manager::kBluetoothAgentManagerInterface,
+        bluetooth_agent_manager::kRegisterAgent);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendObjectPath(agent_path);
     writer.AppendString(capability);
 
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAgentManagerClientImpl::OnError,
@@ -58,15 +56,13 @@
     writer.AppendObjectPath(agent_path);
 
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAgentManagerClientImpl::OnError,
                    weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
-
   // BluetoothAgentManagerClient override.
   void RequestDefaultAgent(const dbus::ObjectPath& agent_path,
                            const base::Closure& callback,
@@ -79,8 +75,7 @@
     writer.AppendObjectPath(agent_path);
 
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothAgentManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothAgentManagerClientImpl::OnError,
@@ -98,8 +93,7 @@
 
  private:
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -127,20 +121,17 @@
   // than we do.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<BluetoothAgentManagerClientImpl>
-      weak_ptr_factory_;
+  base::WeakPtrFactory<BluetoothAgentManagerClientImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClientImpl);
 };
 
-BluetoothAgentManagerClient::BluetoothAgentManagerClient() {
-}
+BluetoothAgentManagerClient::BluetoothAgentManagerClient() {}
 
-BluetoothAgentManagerClient::~BluetoothAgentManagerClient() {
-}
+BluetoothAgentManagerClient::~BluetoothAgentManagerClient() {}
 
 BluetoothAgentManagerClient* BluetoothAgentManagerClient::Create() {
   return new BluetoothAgentManagerClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_agent_manager_client.h b/device/bluetooth/dbus/bluetooth_agent_manager_client.h
similarity index 84%
rename from chromeos/dbus/bluetooth_agent_manager_client.h
rename to device/bluetooth/dbus/bluetooth_agent_manager_client.h
index f43f4f8..c43568a 100644
--- a/chromeos/dbus/bluetooth_agent_manager_client.h
+++ b/device/bluetooth/dbus/bluetooth_agent_manager_client.h
@@ -2,23 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothAgentManagerClient is used to communicate with the agent manager
 // object of the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothAgentManagerClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothAgentManagerClient
+    : public BluezDBusClient {
  public:
   ~BluetoothAgentManagerClient() override;
 
@@ -63,6 +64,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothAgentManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_agent_service_provider.cc b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc
similarity index 90%
rename from chromeos/dbus/bluetooth_agent_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_agent_service_provider.cc
index 97eb273..7392f2b 100644
--- a/chromeos/dbus/bluetooth_agent_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_agent_service_provider.cc
@@ -2,24 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
-
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 // The BluetoothAgentServiceProvider implementation used in production.
-class BluetoothAgentServiceProviderImpl
-    : public BluetoothAgentServiceProvider {
+class BluetoothAgentServiceProviderImpl : public BluetoothAgentServiceProvider {
  public:
   BluetoothAgentServiceProviderImpl(dbus::Bus* bus,
                                     const dbus::ObjectPath& object_path,
@@ -34,8 +32,7 @@
     exported_object_ = bus_->GetExportedObject(object_path_);
 
     exported_object_->ExportMethod(
-        bluetooth_agent::kBluetoothAgentInterface,
-        bluetooth_agent::kRelease,
+        bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kRelease,
         base::Bind(&BluetoothAgentServiceProviderImpl::Release,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
@@ -98,8 +95,7 @@
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        bluetooth_agent::kBluetoothAgentInterface,
-        bluetooth_agent::kCancel,
+        bluetooth_agent::kBluetoothAgentInterface, bluetooth_agent::kCancel,
         base::Bind(&BluetoothAgentServiceProviderImpl::Cancel,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
@@ -148,9 +144,7 @@
 
     Delegate::PinCodeCallback callback = base::Bind(
         &BluetoothAgentServiceProviderImpl::OnPinCode,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->RequestPinCode(device_path, callback);
   }
@@ -166,8 +160,7 @@
     dbus::MessageReader reader(method_call);
     dbus::ObjectPath device_path;
     std::string pincode;
-    if (!reader.PopObjectPath(&device_path) ||
-        !reader.PopString(&pincode)) {
+    if (!reader.PopObjectPath(&device_path) || !reader.PopString(&pincode)) {
       LOG(WARNING) << "DisplayPinCode called with incorrect paramters: "
                    << method_call->ToString();
       return;
@@ -195,9 +188,7 @@
 
     Delegate::PasskeyCallback callback = base::Bind(
         &BluetoothAgentServiceProviderImpl::OnPasskey,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->RequestPasskey(device_path, callback);
   }
@@ -214,8 +205,7 @@
     dbus::ObjectPath device_path;
     uint32 passkey;
     uint16 entered;
-    if (!reader.PopObjectPath(&device_path) ||
-        !reader.PopUint32(&passkey) ||
+    if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey) ||
         !reader.PopUint16(&entered)) {
       LOG(WARNING) << "DisplayPasskey called with incorrect paramters: "
                    << method_call->ToString();
@@ -239,8 +229,7 @@
     dbus::MessageReader reader(method_call);
     dbus::ObjectPath device_path;
     uint32 passkey;
-    if (!reader.PopObjectPath(&device_path) ||
-        !reader.PopUint32(&passkey)) {
+    if (!reader.PopObjectPath(&device_path) || !reader.PopUint32(&passkey)) {
       LOG(WARNING) << "RequestConfirmation called with incorrect paramters: "
                    << method_call->ToString();
       return;
@@ -248,9 +237,7 @@
 
     Delegate::ConfirmationCallback callback = base::Bind(
         &BluetoothAgentServiceProviderImpl::OnConfirmation,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->RequestConfirmation(device_path, passkey, callback);
   }
@@ -258,8 +245,8 @@
   // Called by dbus:: when the Bluetooth daemon requires that the user
   // confirm an incoming just-works pairing.
   void RequestAuthorization(
-        dbus::MethodCall* method_call,
-        dbus::ExportedObject::ResponseSender response_sender) {
+      dbus::MethodCall* method_call,
+      dbus::ExportedObject::ResponseSender response_sender) {
     DCHECK(OnOriginThread());
     DCHECK(delegate_);
 
@@ -273,9 +260,7 @@
 
     Delegate::ConfirmationCallback callback = base::Bind(
         &BluetoothAgentServiceProviderImpl::OnConfirmation,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->RequestAuthorization(device_path, callback);
   }
@@ -291,8 +276,7 @@
     dbus::MessageReader reader(method_call);
     dbus::ObjectPath device_path;
     std::string uuid;
-    if (!reader.PopObjectPath(&device_path) ||
-        !reader.PopString(&uuid)) {
+    if (!reader.PopObjectPath(&device_path) || !reader.PopString(&uuid)) {
       LOG(WARNING) << "AuthorizeService called with incorrect paramters: "
                    << method_call->ToString();
       return;
@@ -300,9 +284,7 @@
 
     Delegate::ConfirmationCallback callback = base::Bind(
         &BluetoothAgentServiceProviderImpl::OnConfirmation,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->AuthorizeService(device_path, uuid, callback);
   }
@@ -323,8 +305,8 @@
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
                   bool success) {
-    LOG_IF(WARNING, !success) << "Failed to export "
-                              << interface_name << "." << method_name;
+    LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+                              << method_name;
   }
 
   // Called by the Delegate to response to a method requesting a PIN code.
@@ -443,22 +425,20 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl);
 };
 
-BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {
-}
+BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {}
 
-BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {
-}
+BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {}
 
 // static
 BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create(
     dbus::Bus* bus,
     const dbus::ObjectPath& object_path,
     Delegate* delegate) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
     return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate);
   } else {
     return new FakeBluetoothAgentServiceProvider(object_path, delegate);
   }
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_agent_service_provider.h b/device/bluetooth/dbus/bluetooth_agent_service_provider.h
similarity index 93%
rename from chromeos/dbus/bluetooth_agent_service_provider.h
rename to device/bluetooth/dbus/bluetooth_agent_service_provider.h
index 411cc1d..e31ef8f9 100644
--- a/chromeos/dbus/bluetooth_agent_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_agent_service_provider.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 CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
 
 #include <string>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothAgentServiceProvider is used to provide a D-Bus object that
 // the bluetooth daemon can communicate with during a remote device pairing
@@ -28,7 +28,7 @@
 // make calls to this agent object and they will be passed on to your Delegate
 // object for handling. Responses should be returned using the callbacks
 // supplied to those methods.
-class CHROMEOS_EXPORT BluetoothAgentServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothAgentServiceProvider {
  public:
   // Interface for reacting to agent requests.
   class Delegate {
@@ -40,11 +40,7 @@
     // granted; rejected indicates the user rejected the request or denied
     // permission; cancelled indicates the user cancelled the request
     // without confirming either way.
-    enum Status {
-      SUCCESS,
-      REJECTED,
-      CANCELLED
-    };
+    enum Status { SUCCESS, REJECTED, CANCELLED };
 
     // The PinCodeCallback is used for the RequestPinCode() method, it should
     // be called with two arguments, the |status| of the request (success,
@@ -117,7 +113,8 @@
     // As the user enters the passkey onto the device, |entered| will be
     // updated to reflect the number of digits entered so far.
     virtual void DisplayPasskey(const dbus::ObjectPath& device_path,
-                                uint32 passkey, uint16 entered) = 0;
+                                uint32 passkey,
+                                uint16 entered) = 0;
 
     // This method will be called when the Bluetooth daemon requires that the
     // user confirm that the Passkey |passkey| is displayed on the screen
@@ -176,6 +173,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
new file mode 100644
index 0000000..29a4ce8
--- /dev/null
+++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
@@ -0,0 +1,84 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/dbus/bluetooth_dbus_client_bundle.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "chromeos/chromeos_switches.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
+
+namespace bluez {
+
+BluetoothDBusClientBundle::BluetoothDBusClientBundle(bool use_stubs)
+    : use_stubs_(use_stubs) {
+  if (!use_stubs) {
+    bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create());
+    bluetooth_le_advertising_manager_client_.reset(
+        BluetoothLEAdvertisingManagerClient::Create());
+    bluetooth_agent_manager_client_.reset(
+        BluetoothAgentManagerClient::Create());
+    bluetooth_device_client_.reset(BluetoothDeviceClient::Create());
+    bluetooth_input_client_.reset(BluetoothInputClient::Create());
+    bluetooth_media_client_.reset(BluetoothMediaClient::Create());
+    bluetooth_media_transport_client_.reset(
+        BluetoothMediaTransportClient::Create());
+    bluetooth_profile_manager_client_.reset(
+        BluetoothProfileManagerClient::Create());
+    bluetooth_gatt_characteristic_client_.reset(
+        BluetoothGattCharacteristicClient::Create());
+    bluetooth_gatt_descriptor_client_.reset(
+        BluetoothGattDescriptorClient::Create());
+    bluetooth_gatt_manager_client_.reset(BluetoothGattManagerClient::Create());
+    bluetooth_gatt_service_client_.reset(BluetoothGattServiceClient::Create());
+  } else {
+    bluetooth_adapter_client_.reset(new FakeBluetoothAdapterClient);
+    bluetooth_le_advertising_manager_client_.reset(
+        new FakeBluetoothLEAdvertisingManagerClient);
+    bluetooth_agent_manager_client_.reset(new FakeBluetoothAgentManagerClient);
+    bluetooth_device_client_.reset(new FakeBluetoothDeviceClient);
+    bluetooth_input_client_.reset(new FakeBluetoothInputClient);
+    bluetooth_media_client_.reset(new FakeBluetoothMediaClient);
+    bluetooth_media_transport_client_.reset(
+        new FakeBluetoothMediaTransportClient);
+    bluetooth_profile_manager_client_.reset(
+        new FakeBluetoothProfileManagerClient);
+    bluetooth_gatt_characteristic_client_.reset(
+        new FakeBluetoothGattCharacteristicClient);
+    bluetooth_gatt_descriptor_client_.reset(
+        new FakeBluetoothGattDescriptorClient);
+    bluetooth_gatt_manager_client_.reset(new FakeBluetoothGattManagerClient);
+    bluetooth_gatt_service_client_.reset(new FakeBluetoothGattServiceClient);
+  }
+}
+
+BluetoothDBusClientBundle::~BluetoothDBusClientBundle() {}
+
+}  // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h
new file mode 100644
index 0000000..bc1a63c
--- /dev/null
+++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.h
@@ -0,0 +1,113 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "device/bluetooth/bluetooth_export.h"
+
+namespace bluez {
+
+class BluetoothAdapterClient;
+class BluetoothAgentManagerClient;
+class BluetoothDeviceClient;
+class BluetoothGattCharacteristicClient;
+class BluetoothGattDescriptorClient;
+class BluetoothGattManagerClient;
+class BluetoothGattServiceClient;
+class BluetoothInputClient;
+class BluetoothLEAdvertisingManagerClient;
+class BluetoothMediaClient;
+class BluetoothMediaTransportClient;
+class BluetoothProfileManagerClient;
+
+// The bundle of all D-Bus clients used in DBusThreadManager. The bundle
+// is used to delete them at once in the right order before shutting down the
+// system bus. See also the comment in the destructor of DBusThreadManager.
+class DEVICE_BLUETOOTH_EXPORT BluetoothDBusClientBundle {
+ public:
+  explicit BluetoothDBusClientBundle(bool use_stubs);
+  ~BluetoothDBusClientBundle();
+
+  // Returns true if |client| is stubbed.
+  bool IsUsingStub() { return use_stubs_; }
+
+  BluetoothAdapterClient* bluetooth_adapter_client() {
+    return bluetooth_adapter_client_.get();
+  }
+
+  BluetoothLEAdvertisingManagerClient*
+  bluetooth_le_advertising_manager_client() {
+    return bluetooth_le_advertising_manager_client_.get();
+  }
+
+  BluetoothAgentManagerClient* bluetooth_agent_manager_client() {
+    return bluetooth_agent_manager_client_.get();
+  }
+
+  BluetoothDeviceClient* bluetooth_device_client() {
+    return bluetooth_device_client_.get();
+  }
+
+  BluetoothGattCharacteristicClient* bluetooth_gatt_characteristic_client() {
+    return bluetooth_gatt_characteristic_client_.get();
+  }
+
+  BluetoothGattDescriptorClient* bluetooth_gatt_descriptor_client() {
+    return bluetooth_gatt_descriptor_client_.get();
+  }
+
+  BluetoothGattManagerClient* bluetooth_gatt_manager_client() {
+    return bluetooth_gatt_manager_client_.get();
+  }
+
+  BluetoothGattServiceClient* bluetooth_gatt_service_client() {
+    return bluetooth_gatt_service_client_.get();
+  }
+
+  BluetoothInputClient* bluetooth_input_client() {
+    return bluetooth_input_client_.get();
+  }
+
+  BluetoothMediaClient* bluetooth_media_client() {
+    return bluetooth_media_client_.get();
+  }
+
+  BluetoothMediaTransportClient* bluetooth_media_transport_client() {
+    return bluetooth_media_transport_client_.get();
+  }
+
+  BluetoothProfileManagerClient* bluetooth_profile_manager_client() {
+    return bluetooth_profile_manager_client_.get();
+  }
+
+ private:
+  friend class BluezDBusManagerSetter;
+
+  bool use_stubs_;
+
+  scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_;
+  scoped_ptr<BluetoothLEAdvertisingManagerClient>
+      bluetooth_le_advertising_manager_client_;
+  scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_;
+  scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_;
+  scoped_ptr<BluetoothGattCharacteristicClient>
+      bluetooth_gatt_characteristic_client_;
+  scoped_ptr<BluetoothGattDescriptorClient> bluetooth_gatt_descriptor_client_;
+  scoped_ptr<BluetoothGattManagerClient> bluetooth_gatt_manager_client_;
+  scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_;
+  scoped_ptr<BluetoothInputClient> bluetooth_input_client_;
+  scoped_ptr<BluetoothMediaClient> bluetooth_media_client_;
+  scoped_ptr<BluetoothMediaTransportClient> bluetooth_media_transport_client_;
+  scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothDBusClientBundle);
+};
+
+}  // namespace bluez
+
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DBUS_CLIENT_BUNDLE_H_
diff --git a/chromeos/dbus/bluetooth_device_client.cc b/device/bluetooth/dbus/bluetooth_device_client.cc
similarity index 85%
rename from chromeos/dbus/bluetooth_device_client.cc
rename to device/bluetooth/dbus/bluetooth_device_client.cc
index 02a5c6b..65059c6 100644
--- a/chromeos/dbus/bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/bluetooth_device_client.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 "chromeos/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -13,7 +13,7 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -50,14 +50,11 @@
   RegisterProperty(bluetooth_device::kTxPowerProperty, &tx_power);
 }
 
-BluetoothDeviceClient::Properties::~Properties() {
-}
-
+BluetoothDeviceClient::Properties::~Properties() {}
 
 // The BluetoothDeviceClient implementation used in production.
-class BluetoothDeviceClientImpl
-    : public BluetoothDeviceClient,
-      public dbus::ObjectManager::Interface {
+class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
+                                  public dbus::ObjectManager::Interface {
  public:
   BluetoothDeviceClientImpl()
       : object_manager_(NULL), weak_ptr_factory_(this) {}
@@ -84,12 +81,10 @@
       dbus::ObjectProxy* object_proxy,
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
-    Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
-        base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+    Properties* properties =
+        new Properties(object_proxy, interface_name,
+                       base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged,
+                                  weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
@@ -110,19 +105,16 @@
 
   // BluetoothDeviceClient override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_device::kBluetoothDeviceInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path, bluetooth_device::kBluetoothDeviceInterface));
   }
 
   // BluetoothDeviceClient override.
   void Connect(const dbus::ObjectPath& object_path,
                const base::Closure& callback,
                const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kConnect);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kConnect);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -133,8 +125,7 @@
 
     // Connect may take an arbitrary length of time, so use no timeout.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_INFINITE,
+        &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -145,9 +136,8 @@
   void Disconnect(const dbus::ObjectPath& object_path,
                   const base::Closure& callback,
                   const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kDisconnect);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kDisconnect);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -157,8 +147,7 @@
     }
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -170,9 +159,8 @@
                       const std::string& uuid,
                       const base::Closure& callback,
                       const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kConnectProfile);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kConnectProfile);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(uuid);
@@ -186,8 +174,7 @@
 
     // Connect may take an arbitrary length of time, so use no timeout.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_INFINITE,
+        &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -199,9 +186,8 @@
                          const std::string& uuid,
                          const base::Closure& callback,
                          const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kDisconnectProfile);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kDisconnectProfile);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(uuid);
@@ -214,8 +200,7 @@
     }
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -226,9 +211,8 @@
   void Pair(const dbus::ObjectPath& object_path,
             const base::Closure& callback,
             const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kPair);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kPair);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -239,8 +223,7 @@
 
     // Pairing may take an arbitrary length of time, so use no timeout.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_INFINITE,
+        &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -251,9 +234,8 @@
   void CancelPairing(const dbus::ObjectPath& object_path,
                      const base::Closure& callback,
                      const ErrorCallback& error_callback) override {
-    dbus::MethodCall method_call(
-        bluetooth_device::kBluetoothDeviceInterface,
-        bluetooth_device::kCancelPairing);
+    dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
+                                 bluetooth_device::kCancelPairing);
 
     dbus::ObjectProxy* object_proxy =
         object_manager_->GetObjectProxy(object_path);
@@ -262,8 +244,7 @@
       return;
     }
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothDeviceClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothDeviceClientImpl::OnError,
@@ -329,8 +310,7 @@
   }
 
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -387,14 +367,12 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl);
 };
 
-BluetoothDeviceClient::BluetoothDeviceClient() {
-}
+BluetoothDeviceClient::BluetoothDeviceClient() {}
 
-BluetoothDeviceClient::~BluetoothDeviceClient() {
-}
+BluetoothDeviceClient::~BluetoothDeviceClient() {}
 
 BluetoothDeviceClient* BluetoothDeviceClient::Create() {
   return new BluetoothDeviceClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_device_client.h b/device/bluetooth/dbus/bluetooth_device_client.h
similarity index 94%
rename from chromeos/dbus/bluetooth_device_client.h
rename to device/bluetooth/dbus/bluetooth_device_client.h
index 4a0d6b4..b0991dc 100644
--- a/chromeos/dbus/bluetooth_device_client.h
+++ b/device/bluetooth/dbus/bluetooth_device_client.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 CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,16 +11,16 @@
 #include "base/callback.h"
 #include "base/observer_list.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothDeviceClient is used to communicate with objects representing
 // remote Bluetooth Devices.
-class CHROMEOS_EXPORT BluetoothDeviceClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
  public:
   // Structure of properties associated with bluetooth devices.
   struct Properties : public dbus::PropertySet {
@@ -46,7 +46,7 @@
 
     // List of 128-bit UUIDs that represent the available remote services.
     // Read-only.
-    dbus::Property<std::vector<std::string> > uuids;
+    dbus::Property<std::vector<std::string>> uuids;
 
     // Transmitted power level. This field is avaliable only for LE devices
     // that include this field in AD. Read-only.
@@ -201,6 +201,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
similarity index 84%
rename from chromeos/dbus/bluetooth_gatt_characteristic_client.cc
rename to device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
index 5e48601..6000a52 100644
--- a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.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 "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
 
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
@@ -11,7 +11,7 @@
 #include "dbus/object_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -42,8 +42,7 @@
                    &descriptors);
 }
 
-BluetoothGattCharacteristicClient::Properties::~Properties() {
-}
+BluetoothGattCharacteristicClient::Properties::~Properties() {}
 
 // The BluetoothGattCharacteristicClient implementation used in production.
 class BluetoothGattCharacteristicClientImpl
@@ -51,9 +50,7 @@
       public dbus::ObjectManager::Interface {
  public:
   BluetoothGattCharacteristicClientImpl()
-      : object_manager_(NULL),
-        weak_ptr_factory_(this) {
-  }
+      : object_manager_(NULL), weak_ptr_factory_(this) {}
 
   ~BluetoothGattCharacteristicClientImpl() override {
     object_manager_->UnregisterInterface(
@@ -84,11 +81,9 @@
   // BluetoothGattCharacteristicClient override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
     DCHECK(object_manager_);
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_gatt_characteristic::
-                kBluetoothGattCharacteristicInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path,
+        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface));
   }
 
   // BluetoothGattCharacteristicClient override.
@@ -107,14 +102,11 @@
         bluetooth_gatt_characteristic::kReadValue);
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // BluetoothGattCharacteristicClient override.
@@ -136,14 +128,11 @@
     writer.AppendArrayOfBytes(value.data(), value.size());
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // BluetoothGattCharacteristicClient override.
@@ -162,14 +151,11 @@
         bluetooth_gatt_characteristic::kStartNotify);
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // BluetoothGattCharacteristicClient override.
@@ -188,14 +174,11 @@
         bluetooth_gatt_characteristic::kStopNotify);
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // dbus::ObjectManager::Interface override.
@@ -204,11 +187,9 @@
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
     Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
+        object_proxy, interface_name,
         base::Bind(&BluetoothGattCharacteristicClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+                   weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
@@ -248,9 +229,9 @@
                                  const std::string& property_name) {
     VLOG(2) << "Remote GATT characteristic property changed: "
             << object_path.value() << ": " << property_name;
-    FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
-                      GattCharacteristicPropertyChanged(object_path,
-                                                        property_name));
+    FOR_EACH_OBSERVER(
+        BluetoothGattCharacteristicClient::Observer, observers_,
+        GattCharacteristicPropertyChanged(object_path, property_name));
   }
 
   // Called when a response for successful method call is received.
@@ -305,21 +286,18 @@
   // than we do.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl>
-      weak_ptr_factory_;
+  base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClientImpl);
 };
 
-BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() {
-}
+BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() {}
 
-BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() {
-}
+BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() {}
 
 // static
 BluetoothGattCharacteristicClient* BluetoothGattCharacteristicClient::Create() {
   return new BluetoothGattCharacteristicClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
similarity index 92%
rename from chromeos/dbus/bluetooth_gatt_characteristic_client.h
rename to device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
index b040b56..3c476eb 100644
--- a/chromeos/dbus/bluetooth_gatt_characteristic_client.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
@@ -2,24 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattCharacteristicClient is used to communicate with remote GATT
 // characteristic objects exposed by the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothGattCharacteristicClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicClient
+    : public BluezDBusClient {
  public:
   // Structure of properties associated with GATT characteristics.
   struct Properties : public dbus::PropertySet {
@@ -138,6 +139,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc
similarity index 85%
rename from chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc
index 545880a..4decdf0 100644
--- a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.cc
@@ -2,27 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_util.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 namespace {
-const char kErrorInvalidArgs[] =
-    "org.freedesktop.DBus.Error.InvalidArgs";
+const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
 const char kErrorPropertyReadOnly[] =
     "org.freedesktop.DBus.Error.PropertyReadOnly";
-const char kErrorFailed[] =
-    "org.freedesktop.DBus.Error.Failed";
+const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed";
 }  // namespace
 
 // The BluetoothGattCharacteristicServiceProvider implementation used in
@@ -52,31 +50,27 @@
     DCHECK(!uuid_.empty());
     DCHECK(object_path_.IsValid());
     DCHECK(service_path_.IsValid());
-    DCHECK(base::StartsWith(object_path_.value(),
-                            service_path_.value() + "/",
+    DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/",
                             base::CompareCase::SENSITIVE));
 
     exported_object_ = bus_->GetExportedObject(object_path_);
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesSet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGetAll,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
@@ -92,9 +86,8 @@
   // BluetoothGattCharacteristicServiceProvider override.
   void SendValueChanged(const std::vector<uint8>& value) override {
     VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value.";
-    dbus::Signal signal(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesChangedSignal);
+    dbus::Signal signal(dbus::kDBusPropertiesInterface,
+                        dbus::kDBusPropertiesChangedSignal);
     dbus::MessageWriter writer(&signal);
     dbus::MessageWriter array_writer(NULL);
     dbus::MessageWriter dict_entry_writer(NULL);
@@ -141,11 +134,10 @@
     std::string interface_name;
     std::string property_name;
     if (!reader.PopString(&interface_name) ||
-        !reader.PopString(&property_name) ||
-        reader.HasMoreData()) {
+        !reader.PopString(&property_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 'ss'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 'ss'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -166,11 +158,11 @@
       DCHECK(delegate_);
       delegate_->GetCharacteristicValue(
           base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     method_call, response_sender),
+                     weak_ptr_factory_.GetWeakPtr(), method_call,
+                     response_sender),
           base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     method_call, response_sender));
+                     weak_ptr_factory_.GetWeakPtr(), method_call,
+                     response_sender));
       return;
     }
 
@@ -191,8 +183,7 @@
       writer.CloseContainer(&variant_writer);
     } else {
       response = dbus::ErrorResponse::FromMethodCall(
-          method_call,
-          kErrorInvalidArgs,
+          method_call, kErrorInvalidArgs,
           "No such property: '" + property_name + "'.");
     }
 
@@ -214,11 +205,10 @@
     dbus::MessageReader variant_reader(NULL);
     if (!reader.PopString(&interface_name) ||
         !reader.PopString(&property_name) ||
-        !reader.PopVariant(&variant_reader) ||
-        reader.HasMoreData()) {
+        !reader.PopVariant(&variant_reader) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 'ssv'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 'ssv'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -247,8 +237,8 @@
         error_message = "No such property: '" + property_name + "'.";
       }
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, error_name, error_message);
+          dbus::ErrorResponse::FromMethodCall(method_call, error_name,
+                                              error_message);
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -271,11 +261,11 @@
     delegate_->SetCharacteristicValue(
         value,
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender),
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender),
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender));
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender));
   }
 
   // Called by dbus:: when the Bluetooth daemon fetches all properties of the
@@ -291,8 +281,8 @@
     std::string interface_name;
     if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 's'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 's'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -313,19 +303,19 @@
     DCHECK(delegate_);
     delegate_->GetCharacteristicValue(
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender),
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender),
         base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender));
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender));
   }
 
   // Called by dbus:: when a method is exported.
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
                   bool success) {
-    LOG_IF(WARNING, !success) << "Failed to export "
-                              << interface_name << "." << method_name;
+    LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+                              << method_name;
   }
 
   // Called by the Delegate in response to a method to call to get all
@@ -448,24 +438,22 @@
 };
 
 BluetoothGattCharacteristicServiceProvider::
-    BluetoothGattCharacteristicServiceProvider() {
-}
+    BluetoothGattCharacteristicServiceProvider() {}
 
 BluetoothGattCharacteristicServiceProvider::
-    ~BluetoothGattCharacteristicServiceProvider() {
-}
+    ~BluetoothGattCharacteristicServiceProvider() {}
 
 // static
 BluetoothGattCharacteristicServiceProvider*
 BluetoothGattCharacteristicServiceProvider::Create(
-      dbus::Bus* bus,
-      const dbus::ObjectPath& object_path,
-      Delegate* delegate,
-      const std::string& uuid,
-      const std::vector<std::string>& flags,
-      const std::vector<std::string>& permissions,
-      const dbus::ObjectPath& service_path) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+    dbus::Bus* bus,
+    const dbus::ObjectPath& object_path,
+    Delegate* delegate,
+    const std::string& uuid,
+    const std::vector<std::string>& flags,
+    const std::vector<std::string>& permissions,
+    const dbus::ObjectPath& service_path) {
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
     return new BluetoothGattCharacteristicServiceProviderImpl(
         bus, object_path, delegate, uuid, flags, permissions, service_path);
   }
@@ -473,4 +461,4 @@
       object_path, delegate, uuid, flags, permissions, service_path);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h
similarity index 91%
rename from chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h
rename to device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h
index 174a908..ad5d999f 100644
--- a/chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.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 CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
 
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattCharacteristicServiceProvider is used to provide a D-Bus object
 // that represents a local GATT characteristic that the Bluetooth daemon can
@@ -30,7 +30,7 @@
 // mandatory during initialization. In addition, a "SendValueChanged" method is
 // provided, which emits a DBus.Properties.PropertyChanged signal for the
 // "Value" property.
-class CHROMEOS_EXPORT BluetoothGattCharacteristicServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicServiceProvider {
  public:
   // Interface for reacting to GATT characteristic value requests.
   class Delegate {
@@ -108,6 +108,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
similarity index 85%
rename from chromeos/dbus/bluetooth_gatt_descriptor_client.cc
rename to device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
index 86d38ffe..f3ba343c 100644
--- a/chromeos/dbus/bluetooth_gatt_descriptor_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.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 "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
 
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
@@ -11,7 +11,7 @@
 #include "dbus/object_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -30,7 +30,7 @@
 BluetoothGattDescriptorClient::Properties::Properties(
     dbus::ObjectProxy* object_proxy,
     const std::string& interface_name,
-    const PropertyChangedCallback&callback)
+    const PropertyChangedCallback& callback)
     : dbus::PropertySet(object_proxy, interface_name, callback) {
   RegisterProperty(bluetooth_gatt_descriptor::kUUIDProperty, &uuid);
   RegisterProperty(bluetooth_gatt_descriptor::kCharacteristicProperty,
@@ -38,8 +38,7 @@
   RegisterProperty(kValueProperty, &value);
 }
 
-BluetoothGattDescriptorClient::Properties::~Properties() {
-}
+BluetoothGattDescriptorClient::Properties::~Properties() {}
 
 // The BluetoothGattDescriptorClient implementation used in production.
 class BluetoothGattDescriptorClientImpl
@@ -47,9 +46,7 @@
       public dbus::ObjectManager::Interface {
  public:
   BluetoothGattDescriptorClientImpl()
-      : object_manager_(NULL),
-        weak_ptr_factory_(this) {
-  }
+      : object_manager_(NULL), weak_ptr_factory_(this) {}
 
   ~BluetoothGattDescriptorClientImpl() override {
     object_manager_->UnregisterInterface(
@@ -79,10 +76,9 @@
   // BluetoothGattDescriptorClientImpl override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
     DCHECK(object_manager_);
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path,
+        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface));
   }
 
   // BluetoothGattDescriptorClientImpl override.
@@ -101,14 +97,11 @@
         bluetooth_gatt_descriptor::kReadValue);
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattDescriptorClientImpl::OnValueSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattDescriptorClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // BluetoothGattDescriptorClientImpl override.
@@ -130,14 +123,11 @@
     writer.AppendArrayOfBytes(value.data(), value.size());
 
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattDescriptorClientImpl::OnSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   callback),
+                   weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattDescriptorClientImpl::OnError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   error_callback));
+                   weak_ptr_factory_.GetWeakPtr(), error_callback));
   }
 
   // dbus::ObjectManager::Interface override.
@@ -146,11 +136,9 @@
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
     Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
+        object_proxy, interface_name,
         base::Bind(&BluetoothGattDescriptorClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+                   weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
@@ -178,8 +166,7 @@
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
-        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
-        this);
+        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface, this);
   }
 
  private:
@@ -190,9 +177,9 @@
                                  const std::string& property_name) {
     VLOG(2) << "Remote GATT descriptor property changed: "
             << object_path.value() << ": " << property_name;
-    FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_,
-                      GattDescriptorPropertyChanged(object_path,
-                                                    property_name));
+    FOR_EACH_OBSERVER(
+        BluetoothGattDescriptorClient::Observer, observers_,
+        GattDescriptorPropertyChanged(object_path, property_name));
   }
 
   // Called when a response for a successful method call is received.
@@ -252,15 +239,13 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClientImpl);
 };
 
-BluetoothGattDescriptorClient::BluetoothGattDescriptorClient() {
-}
+BluetoothGattDescriptorClient::BluetoothGattDescriptorClient() {}
 
-BluetoothGattDescriptorClient::~BluetoothGattDescriptorClient() {
-}
+BluetoothGattDescriptorClient::~BluetoothGattDescriptorClient() {}
 
 // static
 BluetoothGattDescriptorClient* BluetoothGattDescriptorClient::Create() {
   return new BluetoothGattDescriptorClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_client.h b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h
similarity index 90%
rename from chromeos/dbus/bluetooth_gatt_descriptor_client.h
rename to device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h
index 15d3d9c34a..364331e5 100644
--- a/chromeos/dbus/bluetooth_gatt_descriptor_client.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h
@@ -2,24 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattDescriptorClient is used to communicate with remote GATT
 // characteristic descriptor objects exposed by the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothGattDescriptorClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattDescriptorClient
+    : public BluezDBusClient {
  public:
   // Structure of properties associated with GATT descriptors.
   struct Properties : public dbus::PropertySet {
@@ -110,6 +111,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc
similarity index 85%
rename from chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc
index 3ed39b9..e4aa2454 100644
--- a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.cc
@@ -2,27 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_util.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 namespace {
-const char kErrorInvalidArgs[] =
-    "org.freedesktop.DBus.Error.InvalidArgs";
+const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
 const char kErrorPropertyReadOnly[] =
     "org.freedesktop.DBus.Error.PropertyReadOnly";
-const char kErrorFailed[] =
-    "org.freedesktop.DBus.Error.Failed";
+const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed";
 }  // namespace
 
 // The BluetoothGattDescriptorServiceProvider implementation used in production.
@@ -57,24 +55,21 @@
     exported_object_ = bus_->GetExportedObject(object_path_);
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Get,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesSet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::Set,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGetAll,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::GetAll,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
@@ -90,9 +85,8 @@
   // BluetoothGattDescriptorServiceProvider override.
   void SendValueChanged(const std::vector<uint8>& value) override {
     VLOG(2) << "Emitting a PropertiesChanged signal for descriptor value.";
-    dbus::Signal signal(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesChangedSignal);
+    dbus::Signal signal(dbus::kDBusPropertiesInterface,
+                        dbus::kDBusPropertiesChangedSignal);
     dbus::MessageWriter writer(&signal);
     dbus::MessageWriter array_writer(NULL);
     dbus::MessageWriter dict_entry_writer(NULL);
@@ -138,11 +132,10 @@
     std::string interface_name;
     std::string property_name;
     if (!reader.PopString(&interface_name) ||
-        !reader.PopString(&property_name) ||
-        reader.HasMoreData()) {
+        !reader.PopString(&property_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 'ss'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 'ss'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -163,11 +156,11 @@
       DCHECK(delegate_);
       delegate_->GetDescriptorValue(
           base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGet,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     method_call, response_sender),
+                     weak_ptr_factory_.GetWeakPtr(), method_call,
+                     response_sender),
           base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     method_call, response_sender));
+                     weak_ptr_factory_.GetWeakPtr(), method_call,
+                     response_sender));
       return;
     }
 
@@ -188,8 +181,7 @@
       writer.CloseContainer(&variant_writer);
     } else {
       response = dbus::ErrorResponse::FromMethodCall(
-          method_call,
-          kErrorInvalidArgs,
+          method_call, kErrorInvalidArgs,
           "No such property: '" + property_name + "'.");
     }
 
@@ -211,11 +203,10 @@
     dbus::MessageReader variant_reader(NULL);
     if (!reader.PopString(&interface_name) ||
         !reader.PopString(&property_name) ||
-        !reader.PopVariant(&variant_reader) ||
-        reader.HasMoreData()) {
+        !reader.PopVariant(&variant_reader) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 'ssv'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 'ssv'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -244,8 +235,8 @@
         error_message = "No such property: '" + property_name + "'.";
       }
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, error_name, error_message);
+          dbus::ErrorResponse::FromMethodCall(method_call, error_name,
+                                              error_message);
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -266,13 +257,12 @@
     std::vector<uint8> value(bytes, bytes + length);
     DCHECK(delegate_);
     delegate_->SetDescriptorValue(
-        value,
-        base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnSet,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender),
+        value, base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnSet,
+                          weak_ptr_factory_.GetWeakPtr(), method_call,
+                          response_sender),
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender));
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender));
   }
 
   // Called by dbus:: when the Bluetooth daemon fetches all properties of the
@@ -288,8 +278,8 @@
     std::string interface_name;
     if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 's'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 's'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -310,19 +300,19 @@
     DCHECK(delegate_);
     delegate_->GetDescriptorValue(
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnGetAll,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender),
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender),
         base::Bind(&BluetoothGattDescriptorServiceProviderImpl::OnFailure,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   method_call, response_sender));
+                   weak_ptr_factory_.GetWeakPtr(), method_call,
+                   response_sender));
   }
 
   // Called by dbus:: when a method is exported.
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
                   bool success) {
-    LOG_IF(WARNING, !success) << "Failed to export "
-                              << interface_name << "." << method_name;
+    LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+                              << method_name;
   }
 
   // Called by the Delegate in response to a method to call to get all
@@ -344,8 +334,7 @@
     writer.OpenArray("{sv}", &array_writer);
 
     array_writer.OpenDictEntry(&dict_entry_writer);
-    dict_entry_writer.AppendString(
-        bluetooth_gatt_descriptor::kUUIDProperty);
+    dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kUUIDProperty);
     dict_entry_writer.AppendVariantOfString(uuid_);
     array_writer.CloseContainer(&dict_entry_writer);
 
@@ -356,8 +345,7 @@
     array_writer.CloseContainer(&dict_entry_writer);
 
     array_writer.OpenDictEntry(&dict_entry_writer);
-    dict_entry_writer.AppendString(
-        bluetooth_gatt_descriptor::kValueProperty);
+    dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty);
     dict_entry_writer.OpenVariant("ay", &variant_writer);
     variant_writer.AppendArrayOfBytes(value.data(), value.size());
     dict_entry_writer.CloseContainer(&variant_writer);
@@ -403,8 +391,7 @@
     VLOG(2) << "Failed to get/set descriptor value. Report error.";
     scoped_ptr<dbus::ErrorResponse> error_response =
         dbus::ErrorResponse::FromMethodCall(
-            method_call, kErrorFailed,
-            "Failed to get/set descriptor value.");
+            method_call, kErrorFailed, "Failed to get/set descriptor value.");
     response_sender.Run(error_response.Pass());
   }
 
@@ -445,12 +432,10 @@
 };
 
 BluetoothGattDescriptorServiceProvider::
-    BluetoothGattDescriptorServiceProvider() {
-}
+    BluetoothGattDescriptorServiceProvider() {}
 
 BluetoothGattDescriptorServiceProvider::
-    ~BluetoothGattDescriptorServiceProvider() {
-}
+    ~BluetoothGattDescriptorServiceProvider() {}
 
 // static
 BluetoothGattDescriptorServiceProvider*
@@ -461,7 +446,7 @@
     const std::string& uuid,
     const std::vector<std::string>& permissions,
     const dbus::ObjectPath& characteristic_path) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
     return new BluetoothGattDescriptorServiceProviderImpl(
         bus, object_path, delegate, uuid, permissions, characteristic_path);
   }
@@ -469,4 +454,4 @@
       object_path, delegate, uuid, permissions, characteristic_path);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h
similarity index 92%
rename from chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h
rename to device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h
index 4b5fef8..e4925fff 100644
--- a/chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.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 CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
 
 #include <string>
 #include <vector>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattDescriptorServiceProvider is used to provide a D-Bus object that
 // represents a local GATT characteristic descriptor that the Bluetooth daemon
@@ -30,7 +30,7 @@
 // mandatory during initialization. In addition, a "SendValueChanged" method is
 // provided, which emits a DBus.Properties.PropertyChanged signal for the
 // "Value" property.
-class CHROMEOS_EXPORT BluetoothGattDescriptorServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattDescriptorServiceProvider {
  public:
   // Interface for reacting to GATT characteristic descriptor value requests.
   class Delegate {
@@ -104,6 +104,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattDescriptorServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
similarity index 90%
rename from chromeos/dbus/bluetooth_gatt_manager_client.cc
rename to device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
index 8ccbb69..7e471a5c 100644
--- a/chromeos/dbus/bluetooth_gatt_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_manager_client.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 "chromeos/dbus/bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
 
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
@@ -11,7 +11,7 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char BluetoothGattManagerClient::kNoResponseError[] =
     "org.chromium.Error.NoResponse";
@@ -20,9 +20,7 @@
 class BluetoothGattManagerClientImpl : public BluetoothGattManagerClient {
  public:
   BluetoothGattManagerClientImpl()
-      : object_proxy_(NULL),
-        weak_ptr_factory_(this) {
-  }
+      : object_proxy_(NULL), weak_ptr_factory_(this) {}
 
   ~BluetoothGattManagerClientImpl() override {}
 
@@ -47,8 +45,7 @@
 
     DCHECK(object_proxy_);
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattManagerClientImpl::OnError,
@@ -68,8 +65,7 @@
 
     DCHECK(object_proxy_);
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothGattManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothGattManagerClientImpl::OnError,
@@ -121,15 +117,13 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClientImpl);
 };
 
-BluetoothGattManagerClient::BluetoothGattManagerClient() {
-}
+BluetoothGattManagerClient::BluetoothGattManagerClient() {}
 
-BluetoothGattManagerClient::~BluetoothGattManagerClient() {
-}
+BluetoothGattManagerClient::~BluetoothGattManagerClient() {}
 
 // static
 BluetoothGattManagerClient* BluetoothGattManagerClient::Create() {
   return new BluetoothGattManagerClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_manager_client.h b/device/bluetooth/dbus/bluetooth_gatt_manager_client.h
similarity index 84%
rename from chromeos/dbus/bluetooth_gatt_manager_client.h
rename to device/bluetooth/dbus/bluetooth_gatt_manager_client.h
index 155c2b53..3fab5c3 100644
--- a/chromeos/dbus/bluetooth_gatt_manager_client.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_manager_client.h
@@ -2,24 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
 
 #include <string>
 
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattManagerClient is used to communicate with the GATT Service
 // manager object of the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothGattManagerClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattManagerClient
+    : public BluezDBusClient {
  public:
   // Options used to register a GATT service hierarchy.
-  struct CHROMEOS_EXPORT Options {
+  struct DEVICE_BLUETOOTH_EXPORT Options {
     // TODO(armansito): This parameter is not yet clearly defined. Add fields
     // later as we know more about how this will be used.
   };
@@ -67,6 +68,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif // CHROMEOS_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
similarity index 87%
rename from chromeos/dbus/bluetooth_gatt_service_client.cc
rename to device/bluetooth/dbus/bluetooth_gatt_service_client.cc
index 58266c18..dc3ef5a 100644
--- a/chromeos/dbus/bluetooth_gatt_service_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_service_client.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 "chromeos/dbus/bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
 
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
@@ -11,12 +11,12 @@
 #include "dbus/object_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 BluetoothGattServiceClient::Properties::Properties(
     dbus::ObjectProxy* object_proxy,
     const std::string& interface_name,
-    const PropertyChangedCallback&callback)
+    const PropertyChangedCallback& callback)
     : dbus::PropertySet(object_proxy, interface_name, callback) {
   RegisterProperty(bluetooth_gatt_service::kUUIDProperty, &uuid);
   RegisterProperty(bluetooth_gatt_service::kIncludesProperty, &includes);
@@ -26,17 +26,14 @@
                    &characteristics);
 }
 
-BluetoothGattServiceClient::Properties::~Properties() {
-}
+BluetoothGattServiceClient::Properties::~Properties() {}
 
 // The BluetoothGattServiceClient implementation used in production.
 class BluetoothGattServiceClientImpl : public BluetoothGattServiceClient,
                                        public dbus::ObjectManager::Interface {
  public:
   BluetoothGattServiceClientImpl()
-      : object_manager_(NULL),
-        weak_ptr_factory_(this) {
-  }
+      : object_manager_(NULL), weak_ptr_factory_(this) {}
 
   ~BluetoothGattServiceClientImpl() override {
     object_manager_->UnregisterInterface(
@@ -65,10 +62,8 @@
   // BluetoothGattServiceClientImpl override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
     DCHECK(object_manager_);
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_gatt_service::kBluetoothGattServiceInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path, bluetooth_gatt_service::kBluetoothGattServiceInterface));
   }
 
   // dbus::ObjectManager::Interface override.
@@ -77,11 +72,9 @@
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
     Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
+        object_proxy, interface_name,
         base::Bind(&BluetoothGattServiceClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+                   weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
@@ -138,15 +131,13 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClientImpl);
 };
 
-BluetoothGattServiceClient::BluetoothGattServiceClient() {
-}
+BluetoothGattServiceClient::BluetoothGattServiceClient() {}
 
-BluetoothGattServiceClient::~BluetoothGattServiceClient() {
-}
+BluetoothGattServiceClient::~BluetoothGattServiceClient() {}
 
 // static
 BluetoothGattServiceClient* BluetoothGattServiceClient::Create() {
   return new BluetoothGattServiceClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_service_client.h b/device/bluetooth/dbus/bluetooth_gatt_service_client.h
similarity index 83%
rename from chromeos/dbus/bluetooth_gatt_service_client.h
rename to device/bluetooth/dbus/bluetooth_gatt_service_client.h
index 080ca8f..5828c507 100644
--- a/chromeos/dbus/bluetooth_gatt_service_client.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_service_client.h
@@ -2,22 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
 
 #include <string>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattServiceClient is used to communicate with remote GATT service
 // objects exposed by the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothGattServiceClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattServiceClient
+    : public BluezDBusClient {
  public:
   // Structure of properties associated with GATT services.
   struct Properties : public dbus::PropertySet {
@@ -32,11 +33,11 @@
 
     // Array of object paths representing the characteristics of this service.
     // [read-only]
-    dbus::Property<std::vector<dbus::ObjectPath> > characteristics;
+    dbus::Property<std::vector<dbus::ObjectPath>> characteristics;
 
     // Array of object paths representing the included services of this service.
     // [read-only]
-    dbus::Property<std::vector<dbus::ObjectPath> > includes;
+    dbus::Property<std::vector<dbus::ObjectPath>> includes;
 
     Properties(dbus::ObjectProxy* object_proxy,
                const std::string& interface_name,
@@ -88,6 +89,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_gatt_service_service_provider.cc b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc
similarity index 85%
rename from chromeos/dbus/bluetooth_gatt_service_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc
index 7aeed9b0..06b6827f 100644
--- a/chromeos/dbus/bluetooth_gatt_service_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.cc
@@ -2,23 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_gatt_service_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 namespace {
-const char kErrorInvalidArgs[] =
-    "org.freedesktop.DBus.Error.InvalidArgs";
+const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
 const char kErrorPropertyReadOnly[] =
     "org.freedesktop.DBus.Error.PropertyReadOnly";
 }  // namespace
@@ -47,24 +46,21 @@
     exported_object_ = bus_->GetExportedObject(object_path_);
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
         base::Bind(&BluetoothGattServiceServiceProviderImpl::Get,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesSet,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
         base::Bind(&BluetoothGattServiceServiceProviderImpl::Set,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        dbus::kDBusPropertiesInterface,
-        dbus::kDBusPropertiesGetAll,
+        dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
         base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
@@ -95,11 +91,10 @@
     std::string interface_name;
     std::string property_name;
     if (!reader.PopString(&interface_name) ||
-        !reader.PopString(&property_name) ||
-        reader.HasMoreData()) {
+        !reader.PopString(&property_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 'ss'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 'ss'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -155,9 +150,8 @@
     // All of the properties on this interface are read-only, so just return
     // error.
     scoped_ptr<dbus::ErrorResponse> error_response =
-        dbus::ErrorResponse::FromMethodCall(
-            method_call, kErrorPropertyReadOnly,
-            "All properties are read-only.");
+        dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly,
+                                            "All properties are read-only.");
     response_sender.Run(error_response.Pass());
   }
 
@@ -174,8 +168,8 @@
     std::string interface_name;
     if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
       scoped_ptr<dbus::ErrorResponse> error_response =
-          dbus::ErrorResponse::FromMethodCall(
-              method_call, kErrorInvalidArgs, "Expected 's'.");
+          dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+                                              "Expected 's'.");
       response_sender.Run(error_response.Pass());
       return;
     }
@@ -221,8 +215,8 @@
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
                   bool success) {
-    LOG_IF(WARNING, !success) << "Failed to export "
-                              << interface_name << "." << method_name;
+    LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+                              << method_name;
   }
 
   // Origin thread (i.e. the UI thread in production).
@@ -256,11 +250,9 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl);
 };
 
-BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {
-}
+BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {}
 
-BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {
-}
+BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {}
 
 // static
 BluetoothGattServiceServiceProvider*
@@ -269,12 +261,12 @@
     const dbus::ObjectPath& object_path,
     const std::string& uuid,
     const std::vector<dbus::ObjectPath>& includes) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
-    return new BluetoothGattServiceServiceProviderImpl(
-        bus, object_path, uuid, includes);
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
+    return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid,
+                                                       includes);
   }
-  return new FakeBluetoothGattServiceServiceProvider(
-      object_path, uuid, includes);
+  return new FakeBluetoothGattServiceServiceProvider(object_path, uuid,
+                                                     includes);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_gatt_service_service_provider.h b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h
similarity index 81%
rename from chromeos/dbus/bluetooth_gatt_service_service_provider.h
rename to device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h
index 258c4b4..828f0969 100644
--- a/chromeos/dbus/bluetooth_gatt_service_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
 
 #include <string>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothGattServiceServiceProvider is used to provide a D-Bus object that
 // the Bluetooth daemon can communicate with to register GATT service
@@ -24,7 +24,7 @@
 // chromeos::BluetoothGattManagerClient::RegisterService method. Make sure to
 // create characteristic and descriptor objects using the appropriate service
 // providers before registering a GATT service with the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothGattServiceServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothGattServiceServiceProvider {
  public:
   virtual ~BluetoothGattServiceServiceProvider();
 
@@ -47,6 +47,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_SERVICE_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_input_client.cc b/device/bluetooth/dbus/bluetooth_input_client.cc
similarity index 83%
rename from chromeos/dbus/bluetooth_input_client.cc
rename to device/bluetooth/dbus/bluetooth_input_client.cc
index 61ff6ed..42542a8 100644
--- a/chromeos/dbus/bluetooth_input_client.cc
+++ b/device/bluetooth/dbus/bluetooth_input_client.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 "chromeos/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
 
 #include <map>
 
@@ -14,7 +14,7 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 BluetoothInputClient::Properties::Properties(
     dbus::ObjectProxy* object_proxy,
@@ -24,14 +24,11 @@
   RegisterProperty(bluetooth_input::kReconnectModeProperty, &reconnect_mode);
 }
 
-BluetoothInputClient::Properties::~Properties() {
-}
-
+BluetoothInputClient::Properties::~Properties() {}
 
 // The BluetoothInputClient implementation used in production.
-class BluetoothInputClientImpl
-    : public BluetoothInputClient,
-      public dbus::ObjectManager::Interface {
+class BluetoothInputClientImpl : public BluetoothInputClient,
+                                 public dbus::ObjectManager::Interface {
  public:
   BluetoothInputClientImpl() : object_manager_(NULL), weak_ptr_factory_(this) {}
 
@@ -57,21 +54,17 @@
       dbus::ObjectProxy* object_proxy,
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
-    Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
-        base::Bind(&BluetoothInputClientImpl::OnPropertyChanged,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   object_path));
+    Properties* properties =
+        new Properties(object_proxy, interface_name,
+                       base::Bind(&BluetoothInputClientImpl::OnPropertyChanged,
+                                  weak_ptr_factory_.GetWeakPtr(), object_path));
     return static_cast<dbus::PropertySet*>(properties);
   }
 
   // BluetoothInputClient override.
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(
-            object_path,
-            bluetooth_input::kBluetoothInputInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path, bluetooth_input::kBluetoothInputInterface));
   }
 
  protected:
@@ -124,14 +117,12 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothInputClientImpl);
 };
 
-BluetoothInputClient::BluetoothInputClient() {
-}
+BluetoothInputClient::BluetoothInputClient() {}
 
-BluetoothInputClient::~BluetoothInputClient() {
-}
+BluetoothInputClient::~BluetoothInputClient() {}
 
 BluetoothInputClient* BluetoothInputClient::Create() {
   return new BluetoothInputClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_input_client.h b/device/bluetooth/dbus/bluetooth_input_client.h
similarity index 86%
rename from chromeos/dbus/bluetooth_input_client.h
rename to device/bluetooth/dbus/bluetooth_input_client.h
index 02abf99..00595068 100644
--- a/chromeos/dbus/bluetooth_input_client.h
+++ b/device/bluetooth/dbus/bluetooth_input_client.h
@@ -2,24 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothInputClient is used to communicate with objects representing
 // Bluetooth Input (HID) devices.
-class CHROMEOS_EXPORT BluetoothInputClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothInputClient : public BluezDBusClient {
  public:
   // Structure of properties associated with bluetooth input devices.
   struct Properties : public dbus::PropertySet {
@@ -76,6 +76,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothInputClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc
similarity index 97%
rename from chromeos/dbus/bluetooth_le_advertisement_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc
index e5983229..e981124 100644
--- a/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.cc
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/stl_util.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
@@ -397,12 +397,10 @@
 };
 
 BluetoothLEAdvertisementServiceProvider::
-    BluetoothLEAdvertisementServiceProvider() {
-}
+    BluetoothLEAdvertisementServiceProvider() {}
 
 BluetoothLEAdvertisementServiceProvider::
-    ~BluetoothLEAdvertisementServiceProvider() {
-}
+    ~BluetoothLEAdvertisementServiceProvider() {}
 
 // static
 scoped_ptr<BluetoothLEAdvertisementServiceProvider>
@@ -415,7 +413,7 @@
     scoped_ptr<ManufacturerData> manufacturer_data,
     scoped_ptr<UUIDList> solicit_uuids,
     scoped_ptr<ServiceData> service_data) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
     return make_scoped_ptr(new BluetoothAdvertisementServiceProviderImpl(
         bus, object_path, delegate, type, service_uuids.Pass(),
         manufacturer_data.Pass(), solicit_uuids.Pass(), service_data.Pass()));
@@ -425,4 +423,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.h b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h
similarity index 85%
rename from chromeos/dbus/bluetooth_le_advertisement_service_provider.h
rename to device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h
index 98622a2..8f4692f8 100644
--- a/chromeos/dbus/bluetooth_le_advertisement_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.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 CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
 
 #include <stdint.h>
 
@@ -14,16 +14,16 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothAdvertisementServiceProvider is used to provide a D-Bus object that
 // the Bluetooth daemon can communicate with to advertise data.
-class CHROMEOS_EXPORT BluetoothLEAdvertisementServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothLEAdvertisementServiceProvider {
  public:
   using UUIDList = std::vector<std::string>;
   using ManufacturerData = std::map<uint16_t, std::vector<uint8_t>>;
@@ -77,6 +77,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisementServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
similarity index 97%
rename from chromeos/dbus/bluetooth_le_advertising_manager_client.cc
rename to device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
index a2eedf9..3c934e63 100644
--- a/chromeos/dbus/bluetooth_le_advertising_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.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 "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -13,7 +13,7 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char BluetoothLEAdvertisingManagerClient::kNoResponseError[] =
     "org.chromium.Error.NoResponse";
@@ -175,15 +175,13 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementManagerClientImpl);
 };
 
-BluetoothLEAdvertisingManagerClient::BluetoothLEAdvertisingManagerClient() {
-}
+BluetoothLEAdvertisingManagerClient::BluetoothLEAdvertisingManagerClient() {}
 
-BluetoothLEAdvertisingManagerClient::~BluetoothLEAdvertisingManagerClient() {
-}
+BluetoothLEAdvertisingManagerClient::~BluetoothLEAdvertisingManagerClient() {}
 
 BluetoothLEAdvertisingManagerClient*
 BluetoothLEAdvertisingManagerClient::Create() {
   return new BluetoothAdvertisementManagerClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.h b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h
similarity index 84%
rename from chromeos/dbus/bluetooth_le_advertising_manager_client.h
rename to device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h
index 5160a9f5..f4e7b34c 100644
--- a/chromeos/dbus/bluetooth_le_advertising_manager_client.h
+++ b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.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 CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,15 +11,16 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothAdvertisingManagerClient is used to communicate with the advertising
 // manager object of the BlueZ daemon.
-class CHROMEOS_EXPORT BluetoothLEAdvertisingManagerClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothLEAdvertisingManagerClient
+    : public BluezDBusClient {
  public:
   // Interface for observing changes to advertising managers.
   class Observer {
@@ -78,6 +79,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisingManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_media_client.cc b/device/bluetooth/dbus/bluetooth_media_client.cc
similarity index 92%
rename from chromeos/dbus/bluetooth_media_client.cc
rename to device/bluetooth/dbus/bluetooth_media_client.cc
index 5922753..0927d45 100644
--- a/chromeos/dbus/bluetooth_media_client.cc
+++ b/device/bluetooth/dbus/bluetooth_media_client.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 "chromeos/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -18,8 +18,7 @@
 
 // Since there is no property associated with Media objects, an empty callback
 // is used.
-void DoNothing(const std::string& property_name) {
-}
+void DoNothing(const std::string& property_name) {}
 
 // TODO(mcchou): Add these service constants into dbus/service_constants.h
 // later.
@@ -36,7 +35,7 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 // static
 const char BluetoothMediaClient::kNoResponseError[] =
@@ -46,14 +45,12 @@
 const char BluetoothMediaClient::kBluetoothAudioSinkUUID[] =
     "0000110b-0000-1000-8000-00805f9b34fb";
 
-BluetoothMediaClient::EndpointProperties::EndpointProperties() : codec(0x00) {
-}
+BluetoothMediaClient::EndpointProperties::EndpointProperties() : codec(0x00) {}
 
-BluetoothMediaClient::EndpointProperties::~EndpointProperties() {
-}
+BluetoothMediaClient::EndpointProperties::~EndpointProperties() {}
 
-class BluetoothMediaClientImpl
-    : public BluetoothMediaClient, dbus::ObjectManager::Interface {
+class BluetoothMediaClientImpl : public BluetoothMediaClient,
+                                 dbus::ObjectManager::Interface {
  public:
   BluetoothMediaClientImpl()
       : object_manager_(nullptr), weak_ptr_factory_(this) {}
@@ -145,8 +142,7 @@
     scoped_refptr<dbus::ObjectProxy> object_proxy(
         object_manager_->GetObjectProxy(object_path));
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothMediaClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothMediaClientImpl::OnError,
@@ -170,8 +166,7 @@
     scoped_refptr<dbus::ObjectProxy> object_proxy(
         object_manager_->GetObjectProxy(object_path));
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothMediaClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothMediaClientImpl::OnError,
@@ -190,8 +185,7 @@
 
  private:
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -222,14 +216,12 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClientImpl);
 };
 
-BluetoothMediaClient::BluetoothMediaClient() {
-}
+BluetoothMediaClient::BluetoothMediaClient() {}
 
-BluetoothMediaClient::~BluetoothMediaClient() {
-}
+BluetoothMediaClient::~BluetoothMediaClient() {}
 
 BluetoothMediaClient* BluetoothMediaClient::Create() {
   return new BluetoothMediaClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_media_client.h b/device/bluetooth/dbus/bluetooth_media_client.h
similarity index 88%
rename from chromeos/dbus/bluetooth_media_client.h
rename to device/bluetooth/dbus/bluetooth_media_client.h
index 1bb55478..8c7050b 100644
--- a/chromeos/dbus/bluetooth_media_client.h
+++ b/device/bluetooth/dbus/bluetooth_media_client.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 CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
 
 #include <memory>
 #include <string>
@@ -11,19 +11,19 @@
 
 #include "base/callback.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothMediaClient is used to communicate with the Media interface of a
 // local Bluetooth adapter.
-class CHROMEOS_EXPORT BluetoothMediaClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothMediaClient : public BluezDBusClient {
  public:
   // Properties used to register a Media Endpoint.
-  struct CHROMEOS_EXPORT EndpointProperties {
+  struct DEVICE_BLUETOOTH_EXPORT EndpointProperties {
     EndpointProperties();
     ~EndpointProperties();
 
@@ -102,6 +102,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothMediaClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_media_endpoint_service_provider.cc b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc
similarity index 88%
rename from chromeos/dbus/bluetooth_media_endpoint_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc
index 3d2e03e..864a04d 100644
--- a/chromeos/dbus/bluetooth_media_endpoint_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
 #include "dbus/exported_object.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
 
 namespace {
 
@@ -31,10 +31,10 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 // The BluetoothMediaEndopintServiceProvider implementation used in production.
-class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProviderImpl
+class DEVICE_BLUETOOTH_EXPORT BluetoothMediaEndpointServiceProviderImpl
     : public BluetoothMediaEndpointServiceProvider {
  public:
   BluetoothMediaEndpointServiceProviderImpl(dbus::Bus* bus,
@@ -53,17 +53,14 @@
     exported_object_ = bus_->GetExportedObject(object_path_);
 
     exported_object_->ExportMethod(
-        kBluetoothMediaEndpointInterface,
-        kSetConfiguration,
-        base::Bind(
-            &BluetoothMediaEndpointServiceProviderImpl::SetConfiguration,
-            weak_ptr_factory_.GetWeakPtr()),
+        kBluetoothMediaEndpointInterface, kSetConfiguration,
+        base::Bind(&BluetoothMediaEndpointServiceProviderImpl::SetConfiguration,
+                   weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        kBluetoothMediaEndpointInterface,
-        kSelectConfiguration,
+        kBluetoothMediaEndpointInterface, kSelectConfiguration,
         base::Bind(
             &BluetoothMediaEndpointServiceProviderImpl::SelectConfiguration,
             weak_ptr_factory_.GetWeakPtr()),
@@ -71,8 +68,7 @@
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        kBluetoothMediaEndpointInterface,
-        kClearConfiguration,
+        kBluetoothMediaEndpointInterface, kClearConfiguration,
         base::Bind(
             &BluetoothMediaEndpointServiceProviderImpl::ClearConfiguration,
             weak_ptr_factory_.GetWeakPtr()),
@@ -80,8 +76,7 @@
                    weak_ptr_factory_.GetWeakPtr()));
 
     exported_object_->ExportMethod(
-        kBluetoothMediaEndpointInterface,
-        kRelease,
+        kBluetoothMediaEndpointInterface, kRelease,
         base::Bind(&BluetoothMediaEndpointServiceProviderImpl::Release,
                    weak_ptr_factory_.GetWeakPtr()),
         base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
@@ -89,8 +84,7 @@
   }
 
   ~BluetoothMediaEndpointServiceProviderImpl() override {
-    VLOG(1) << "Cleaning up Bluetooth Media Endpoint: "
-            << object_path_.value();
+    VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value();
 
     bus_->UnregisterExportedObject(object_path_);
   }
@@ -198,9 +192,7 @@
     // back via |callback|.
     Delegate::SelectConfigurationCallback callback = base::Bind(
         &BluetoothMediaEndpointServiceProviderImpl::OnConfiguration,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->SelectConfiguration(configuration, callback);
   }
@@ -293,33 +285,29 @@
 
 BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties::
     TransportProperties()
-    : codec(kInvalidCodec),
-      state(kInvalidState) {
-}
+    : codec(kInvalidCodec), state(kInvalidState) {}
 
 BluetoothMediaEndpointServiceProvider::Delegate::TransportProperties::
-    ~TransportProperties() {
-}
+    ~TransportProperties() {}
 
 BluetoothMediaEndpointServiceProvider::BluetoothMediaEndpointServiceProvider() {
 }
 
 BluetoothMediaEndpointServiceProvider::
-    ~BluetoothMediaEndpointServiceProvider() {
-}
+    ~BluetoothMediaEndpointServiceProvider() {}
 
 BluetoothMediaEndpointServiceProvider*
-    BluetoothMediaEndpointServiceProvider::Create(
+BluetoothMediaEndpointServiceProvider::Create(
     dbus::Bus* bus,
     const dbus::ObjectPath& object_path,
     Delegate* delegate) {
   // Returns a real implementation.
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
-    return new BluetoothMediaEndpointServiceProviderImpl(
-        bus, object_path, delegate);
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
+    return new BluetoothMediaEndpointServiceProviderImpl(bus, object_path,
+                                                         delegate);
   }
   // Returns a fake implementation.
   return new FakeBluetoothMediaEndpointServiceProvider(object_path, delegate);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_media_endpoint_service_provider.h b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h
similarity index 91%
rename from chromeos/dbus/bluetooth_media_endpoint_service_provider.h
rename to device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h
index fffaa533..df17f09 100644
--- a/chromeos/dbus/bluetooth_media_endpoint_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.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 CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
 
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothMediaEndpointServiceProvider is used to provide a D-Bus object that
 // the Bluetooth daemon can commuicate with to serve as a media source/sink.
@@ -27,7 +27,7 @@
 // Bluetooth daemon will make calls to this endpoint object and they will be
 // passed to user's Delegate object for handling. For SelectConfiguration method
 // the response is returned using the SelectConfiguration callback.
-class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothMediaEndpointServiceProvider {
  public:
   // Delegate is the interface for reacting to endpoint requests. User
   // applications will implement this interface to handle either A2DP Sink or
@@ -35,7 +35,7 @@
   class Delegate {
    public:
     // Transport-specific properties.
-    struct CHROMEOS_EXPORT TransportProperties {
+    struct DEVICE_BLUETOOTH_EXPORT TransportProperties {
       TransportProperties();
       ~TransportProperties();
 
@@ -128,6 +128,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_media_transport_client.cc b/device/bluetooth/dbus/bluetooth_media_transport_client.cc
similarity index 88%
rename from chromeos/dbus/bluetooth_media_transport_client.cc
rename to device/bluetooth/dbus/bluetooth_media_transport_client.cc
index 5639930..7fc47d7 100644
--- a/chromeos/dbus/bluetooth_media_transport_client.cc
+++ b/device/bluetooth/dbus/bluetooth_media_transport_client.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 "chromeos/dbus/bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -31,7 +31,7 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 // static
 const char BluetoothMediaTransportClient::kDeviceProperty[] = "Device";
@@ -62,8 +62,7 @@
   RegisterProperty(kVolumeProperty, &volume);
 }
 
-BluetoothMediaTransportClient::Properties::~Properties() {
-}
+BluetoothMediaTransportClient::Properties::~Properties() {}
 
 class BluetoothMediaTransportClientImpl
     : public BluetoothMediaTransportClient,
@@ -83,8 +82,7 @@
       const dbus::ObjectPath& object_path,
       const std::string& interface_name) override {
     Properties* properties = new Properties(
-        object_proxy,
-        interface_name,
+        object_proxy, interface_name,
         base::Bind(&BluetoothMediaTransportClientImpl::OnPropertyChanged,
                    weak_ptr_factory_.GetWeakPtr(), object_path));
     return properties;
@@ -93,16 +91,14 @@
   void ObjectAdded(const dbus::ObjectPath& object_path,
                    const std::string& interface_name) override {
     VLOG(1) << "Remote Media Transport added: " << object_path.value();
-    FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer,
-                      observers_,
+    FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_,
                       MediaTransportAdded(object_path));
   }
 
   void ObjectRemoved(const dbus::ObjectPath& object_path,
                      const std::string& interface_name) override {
     VLOG(1) << "Remote Media Transport removed: " << object_path.value();
-    FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer,
-                      observers_,
+    FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_,
                       MediaTransportRemoved(object_path));
   }
 
@@ -121,9 +117,8 @@
 
   Properties* GetProperties(const dbus::ObjectPath& object_path) override {
     DCHECK(object_manager_);
-    return static_cast<Properties*>(
-        object_manager_->GetProperties(object_path,
-                                       kBluetoothMediaTransportInterface));
+    return static_cast<Properties*>(object_manager_->GetProperties(
+        object_path, kBluetoothMediaTransportInterface));
   }
 
   void Acquire(const dbus::ObjectPath& object_path,
@@ -141,8 +136,7 @@
 
     // Call Acquire method of Media Transport interface.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
         base::Bind(&BluetoothMediaTransportClientImpl::OnError,
@@ -165,8 +159,7 @@
 
     // Call TryAcquire method of Media Transport interface.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothMediaTransportClientImpl::OnAcquireSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
         base::Bind(&BluetoothMediaTransportClientImpl::OnError,
@@ -188,8 +181,7 @@
 
     // Call TryAcquire method of Media Transport interface.
     object_proxy->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothMediaTransportClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothMediaTransportClientImpl::OnError,
@@ -203,8 +195,7 @@
         bluetooth_object_manager::kBluetoothObjectManagerServiceName,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
-    object_manager_->RegisterInterface(kBluetoothMediaTransportInterface,
-                                       this);
+    object_manager_->RegisterInterface(kBluetoothMediaTransportInterface, this);
   }
 
  private:
@@ -220,8 +211,7 @@
   }
 
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -238,15 +228,13 @@
 
     // Parse the response.
     dbus::MessageReader reader(response);
-    if (reader.PopFileDescriptor(&fd) &&
-        reader.PopUint16(&read_mtu) &&
+    if (reader.PopFileDescriptor(&fd) && reader.PopUint16(&read_mtu) &&
         reader.PopUint16(&write_mtu)) {
       fd.CheckValidity();
       DCHECK(fd.is_valid());
 
-      VLOG(1) << "OnAcquireSuccess - fd: "<<  fd.value()
-              <<", read MTU: " << read_mtu
-              <<", write MTU: " << write_mtu;
+      VLOG(1) << "OnAcquireSuccess - fd: " << fd.value()
+              << ", read MTU: " << read_mtu << ", write MTU: " << write_mtu;
 
       // The ownership of the file descriptor is transferred to the user
       // application.
@@ -287,14 +275,12 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClientImpl);
 };
 
-BluetoothMediaTransportClient::BluetoothMediaTransportClient() {
-}
+BluetoothMediaTransportClient::BluetoothMediaTransportClient() {}
 
-BluetoothMediaTransportClient::~BluetoothMediaTransportClient() {
-}
+BluetoothMediaTransportClient::~BluetoothMediaTransportClient() {}
 
 BluetoothMediaTransportClient* BluetoothMediaTransportClient::Create() {
   return new BluetoothMediaTransportClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_media_transport_client.h b/device/bluetooth/dbus/bluetooth_media_transport_client.h
similarity index 91%
rename from chromeos/dbus/bluetooth_media_transport_client.h
rename to device/bluetooth/dbus/bluetooth_media_transport_client.h
index 4476ae7a..1314b264 100644
--- a/chromeos/dbus/bluetooth_media_transport_client.h
+++ b/device/bluetooth/dbus/bluetooth_media_transport_client.h
@@ -2,22 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
 
 #include <string>
 #include <vector>
 
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
-class CHROMEOS_EXPORT BluetoothMediaTransportClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothMediaTransportClient
+    : public BluezDBusClient {
  public:
   struct Properties : public dbus::PropertySet {
     // The path to the device object which the transport is connected to.
@@ -137,6 +138,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothMediaTransportClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/bluetooth_profile_manager_client.cc
similarity index 89%
rename from chromeos/dbus/bluetooth_profile_manager_client.cc
rename to device/bluetooth/dbus/bluetooth_profile_manager_client.cc
index 85945bc..742988a 100644
--- a/chromeos/dbus/bluetooth_profile_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_profile_manager_client.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 "chromeos/dbus/bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -11,21 +11,17 @@
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char BluetoothProfileManagerClient::kNoResponseError[] =
     "org.chromium.Error.NoResponse";
 
+BluetoothProfileManagerClient::Options::Options() {}
 
-BluetoothProfileManagerClient::Options::Options() {
-}
-
-BluetoothProfileManagerClient::Options::~Options() {
-}
+BluetoothProfileManagerClient::Options::~Options() {}
 
 // The BluetoothProfileManagerClient implementation used in production.
-class BluetoothProfileManagerClientImpl
-    : public BluetoothProfileManagerClient {
+class BluetoothProfileManagerClientImpl : public BluetoothProfileManagerClient {
  public:
   BluetoothProfileManagerClientImpl() : weak_ptr_factory_(this) {}
 
@@ -38,8 +34,8 @@
                        const base::Closure& callback,
                        const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(
-    bluetooth_profile_manager::kBluetoothProfileManagerInterface,
-    bluetooth_profile_manager::kRegisterProfile);
+        bluetooth_profile_manager::kBluetoothProfileManagerInterface,
+        bluetooth_profile_manager::kRegisterProfile);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendObjectPath(profile_path);
@@ -122,8 +118,7 @@
     // Send AutoConnect if provided.
     if (options.auto_connect.get() != NULL) {
       array_writer.OpenDictEntry(&dict_writer);
-      dict_writer.AppendString(
-          bluetooth_profile_manager::kAutoConnectOption);
+      dict_writer.AppendString(bluetooth_profile_manager::kAutoConnectOption);
       dict_writer.AppendVariantOfBool(*(options.auto_connect));
       array_writer.CloseContainer(&dict_writer);
     }
@@ -158,8 +153,7 @@
     writer.CloseContainer(&array_writer);
 
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothProfileManagerClientImpl::OnError,
@@ -171,15 +165,14 @@
                          const base::Closure& callback,
                          const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(
-      bluetooth_profile_manager::kBluetoothProfileManagerInterface,
-      bluetooth_profile_manager::kUnregisterProfile);
+        bluetooth_profile_manager::kBluetoothProfileManagerInterface,
+        bluetooth_profile_manager::kUnregisterProfile);
 
     dbus::MessageWriter writer(&method_call);
     writer.AppendObjectPath(profile_path);
 
     object_proxy_->CallMethodWithErrorCallback(
-        &method_call,
-        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess,
                    weak_ptr_factory_.GetWeakPtr(), callback),
         base::Bind(&BluetoothProfileManagerClientImpl::OnError,
@@ -197,8 +190,7 @@
 
  private:
   // Called when a response for successful method call is received.
-  void OnSuccess(const base::Closure& callback,
-                 dbus::Response* response) {
+  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
     DCHECK(response);
     callback.Run();
   }
@@ -231,14 +223,12 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClientImpl);
 };
 
-BluetoothProfileManagerClient::BluetoothProfileManagerClient() {
-}
+BluetoothProfileManagerClient::BluetoothProfileManagerClient() {}
 
-BluetoothProfileManagerClient::~BluetoothProfileManagerClient() {
-}
+BluetoothProfileManagerClient::~BluetoothProfileManagerClient() {}
 
 BluetoothProfileManagerClient* BluetoothProfileManagerClient::Create() {
   return new BluetoothProfileManagerClientImpl();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_profile_manager_client.h b/device/bluetooth/dbus/bluetooth_profile_manager_client.h
similarity index 85%
rename from chromeos/dbus/bluetooth_profile_manager_client.h
rename to device/bluetooth/dbus/bluetooth_profile_manager_client.h
index 2fa48f6..31f7fefb 100644
--- a/chromeos/dbus/bluetooth_profile_manager_client.h
+++ b/device/bluetooth/dbus/bluetooth_profile_manager_client.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 CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,27 +11,24 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/dbus_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluez_dbus_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothProfileManagerClient is used to communicate with the profile
 // manager object of the Bluetooth daemon.
-class CHROMEOS_EXPORT BluetoothProfileManagerClient : public DBusClient {
+class DEVICE_BLUETOOTH_EXPORT BluetoothProfileManagerClient
+    : public BluezDBusClient {
  public:
   // Species the role of the object within the profile. SYMMETRIC should be
   // usually used unless the profile requires you specify as a CLIENT or as a
   // SERVER.
-  enum ProfileRole {
-    SYMMETRIC,
-    CLIENT,
-    SERVER
-  };
+  enum ProfileRole { SYMMETRIC, CLIENT, SERVER };
 
   // Options used to register a Profile object.
-  struct CHROMEOS_EXPORT Options {
+  struct DEVICE_BLUETOOTH_EXPORT Options {
     Options();
     ~Options();
 
@@ -93,7 +90,6 @@
                                  const base::Closure& callback,
                                  const ErrorCallback& error_callback) = 0;
 
-
   // Creates the instance.
   static BluetoothProfileManagerClient* Create();
 
@@ -107,6 +103,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/bluetooth_profile_service_provider.cc b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc
similarity index 93%
rename from chromeos/dbus/bluetooth_profile_service_provider.cc
rename to device/bluetooth/dbus/bluetooth_profile_service_provider.cc
index c74da5d..a2a23bb8 100644
--- a/chromeos/dbus/bluetooth_profile_service_provider.cc
+++ b/device/bluetooth/dbus/bluetooth_profile_service_provider.cc
@@ -2,20 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
-
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/platform_thread.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
 #include "dbus/exported_object.h"
 #include "dbus/message.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 // The BluetoothProfileServiceProvider implementation used in production.
 class BluetoothProfileServiceProviderImpl
@@ -128,9 +127,7 @@
 
     Delegate::ConfirmationCallback callback = base::Bind(
         &BluetoothProfileServiceProviderImpl::OnConfirmation,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->NewConnection(device_path, fd.Pass(), options, callback);
   }
@@ -153,9 +150,7 @@
 
     Delegate::ConfirmationCallback callback = base::Bind(
         &BluetoothProfileServiceProviderImpl::OnConfirmation,
-        weak_ptr_factory_.GetWeakPtr(),
-        method_call,
-        response_sender);
+        weak_ptr_factory_.GetWeakPtr(), method_call, response_sender);
 
     delegate_->RequestDisconnection(device_path, callback);
   }
@@ -176,8 +171,8 @@
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
                   bool success) {
-    LOG_IF(WARNING, !success) << "Failed to export "
-                              << interface_name << "." << method_name;
+    LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+                              << method_name;
   }
 
   // Called by the Delegate in response to a method requiring confirmation.
@@ -234,22 +229,20 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProviderImpl);
 };
 
-BluetoothProfileServiceProvider::BluetoothProfileServiceProvider() {
-}
+BluetoothProfileServiceProvider::BluetoothProfileServiceProvider() {}
 
-BluetoothProfileServiceProvider::~BluetoothProfileServiceProvider() {
-}
+BluetoothProfileServiceProvider::~BluetoothProfileServiceProvider() {}
 
 // static
 BluetoothProfileServiceProvider* BluetoothProfileServiceProvider::Create(
     dbus::Bus* bus,
     const dbus::ObjectPath& object_path,
     Delegate* delegate) {
-  if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+  if (!bluez::BluezDBusManager::Get()->IsUsingStub()) {
     return new BluetoothProfileServiceProviderImpl(bus, object_path, delegate);
   } else {
     return new FakeBluetoothProfileServiceProvider(object_path, delegate);
   }
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/bluetooth_profile_service_provider.h b/device/bluetooth/dbus/bluetooth_profile_service_provider.h
similarity index 90%
rename from chromeos/dbus/bluetooth_profile_service_provider.h
rename to device/bluetooth/dbus/bluetooth_profile_service_provider.h
index de77b5d..f2db22c7 100644
--- a/chromeos/dbus/bluetooth_profile_service_provider.h
+++ b/device/bluetooth/dbus/bluetooth_profile_service_provider.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
-#define CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
+#ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
 
 #include <string>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "chromeos/chromeos_export.h"
 #include "dbus/bus.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
 
-namespace chromeos {
+namespace bluez {
 
 // BluetoothProfileServiceProvider is used to provide a D-Bus object that the
 // Bluetooth daemon can communicate with to connect application profiles.
@@ -29,7 +29,7 @@
 // Bluetooth daemon will make calls to this profile object and they will be
 // passed on to your Delegate object for handling. Responses should be returned
 // using the callbacks supplied to those methods.
-class CHROMEOS_EXPORT BluetoothProfileServiceProvider {
+class DEVICE_BLUETOOTH_EXPORT BluetoothProfileServiceProvider {
  public:
   // Interface for reacting to profile requests.
   class Delegate {
@@ -40,14 +40,10 @@
     // connection or a requested disconnection. Success indicates acceptance,
     // reject indicates the user rejected or denied the request; cancelled
     // means the user cancelled the request without confirming either way.
-    enum Status {
-      SUCCESS,
-      REJECTED,
-      CANCELLED
-    };
+    enum Status { SUCCESS, REJECTED, CANCELLED };
 
     // Connection-specific options.
-    struct CHROMEOS_EXPORT Options {
+    struct DEVICE_BLUETOOTH_EXPORT Options {
       Options() {}
       ~Options() {}
 
@@ -119,6 +115,6 @@
   DISALLOW_COPY_AND_ASSIGN(BluetoothProfileServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
-#endif  // CHROMEOS_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/dbus/bluez_dbus_client.h b/device/bluetooth/dbus/bluez_dbus_client.h
new file mode 100644
index 0000000..3dd0985
--- /dev/null
+++ b/device/bluetooth/dbus/bluez_dbus_client.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 DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_
+
+#include "base/basictypes.h"
+
+namespace dbus {
+class Bus;
+}  // namespace dbus
+
+namespace bluez {
+
+// Interface for all Bluez DBus clients handled by BluezDBusManager. It
+// restricts
+// access to the Init function to BluezDBusManager only to prevent
+// incorrect calls. Stub clients may lift that restriction however.
+class BluezDBusClient {
+ protected:
+  virtual ~BluezDBusClient() {}
+
+  // This function is called by DBusThreadManager. Only in unit tests, which
+  // don't use DBusThreadManager, this function can be called through Stub
+  // implementations (they change Init's member visibility to public).
+  virtual void Init(dbus::Bus* bus) = 0;
+
+ private:
+  friend class BluezDBusManager;
+
+  DISALLOW_ASSIGN(BluezDBusClient);
+};
+
+}  // namespace bluez
+
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_CLIENT_H_
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.cc b/device/bluetooth/dbus/bluez_dbus_manager.cc
new file mode 100644
index 0000000..376261d
--- /dev/null
+++ b/device/bluetooth/dbus/bluez_dbus_manager.cc
@@ -0,0 +1,250 @@
+// 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 "device/bluetooth/dbus/bluez_dbus_manager.h"
+
+#include "base/command_line.h"
+#include "base/sys_info.h"
+#include "base/threading/thread.h"
+#include "dbus/bus.h"
+#include "dbus/dbus_statistics.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
+
+namespace bluez {
+
+static BluezDBusManager* g_bluez_dbus_manager = nullptr;
+static bool g_using_bluez_dbus_manager_for_testing = false;
+
+BluezDBusManager::BluezDBusManager(
+    dbus::Bus* bus,
+    scoped_ptr<BluetoothDBusClientBundle> client_bundle)
+    : bus_(bus), client_bundle_(client_bundle.Pass()) {}
+
+BluezDBusManager::~BluezDBusManager() {
+  // Delete all D-Bus clients before shutting down the system bus.
+  client_bundle_.reset();
+}
+
+dbus::Bus* bluez::BluezDBusManager::GetSystemBus() {
+  return bus_;
+}
+
+BluetoothAdapterClient* bluez::BluezDBusManager::GetBluetoothAdapterClient() {
+  return client_bundle_->bluetooth_adapter_client();
+}
+
+BluetoothLEAdvertisingManagerClient*
+bluez::BluezDBusManager::GetBluetoothLEAdvertisingManagerClient() {
+  return client_bundle_->bluetooth_le_advertising_manager_client();
+}
+
+BluetoothAgentManagerClient*
+bluez::BluezDBusManager::GetBluetoothAgentManagerClient() {
+  return client_bundle_->bluetooth_agent_manager_client();
+}
+
+BluetoothDeviceClient* bluez::BluezDBusManager::GetBluetoothDeviceClient() {
+  return client_bundle_->bluetooth_device_client();
+}
+
+BluetoothGattCharacteristicClient*
+bluez::BluezDBusManager::GetBluetoothGattCharacteristicClient() {
+  return client_bundle_->bluetooth_gatt_characteristic_client();
+}
+
+BluetoothGattDescriptorClient*
+bluez::BluezDBusManager::GetBluetoothGattDescriptorClient() {
+  return client_bundle_->bluetooth_gatt_descriptor_client();
+}
+
+BluetoothGattManagerClient*
+bluez::BluezDBusManager::GetBluetoothGattManagerClient() {
+  return client_bundle_->bluetooth_gatt_manager_client();
+}
+
+BluetoothGattServiceClient*
+bluez::BluezDBusManager::GetBluetoothGattServiceClient() {
+  return client_bundle_->bluetooth_gatt_service_client();
+}
+
+BluetoothInputClient* bluez::BluezDBusManager::GetBluetoothInputClient() {
+  return client_bundle_->bluetooth_input_client();
+}
+
+BluetoothMediaClient* bluez::BluezDBusManager::GetBluetoothMediaClient() {
+  return client_bundle_->bluetooth_media_client();
+}
+
+BluetoothMediaTransportClient*
+bluez::BluezDBusManager::GetBluetoothMediaTransportClient() {
+  return client_bundle_->bluetooth_media_transport_client();
+}
+
+BluetoothProfileManagerClient*
+bluez::BluezDBusManager::GetBluetoothProfileManagerClient() {
+  return client_bundle_->bluetooth_profile_manager_client();
+}
+
+void BluezDBusManager::InitializeClients() {
+  GetBluetoothAdapterClient()->Init(GetSystemBus());
+  GetBluetoothAgentManagerClient()->Init(GetSystemBus());
+  GetBluetoothDeviceClient()->Init(GetSystemBus());
+  GetBluetoothGattCharacteristicClient()->Init(GetSystemBus());
+  GetBluetoothGattDescriptorClient()->Init(GetSystemBus());
+  GetBluetoothGattManagerClient()->Init(GetSystemBus());
+  GetBluetoothGattServiceClient()->Init(GetSystemBus());
+  GetBluetoothInputClient()->Init(GetSystemBus());
+  GetBluetoothLEAdvertisingManagerClient()->Init(GetSystemBus());
+  GetBluetoothMediaClient()->Init(GetSystemBus());
+  GetBluetoothMediaTransportClient()->Init(GetSystemBus());
+  GetBluetoothProfileManagerClient()->Init(GetSystemBus());
+
+  // This must be called after the list of clients so they've each had a
+  // chance to register with their object g_dbus_thread_managers.
+  if (GetSystemBus())
+    GetSystemBus()->GetManagedObjects();
+}
+
+// static
+void BluezDBusManager::Initialize(dbus::Bus* bus, bool use_dbus_stub) {
+  // If we initialize BluezDBusManager twice we may also be shutting it down
+  // early; do not allow that.
+  if (g_using_bluez_dbus_manager_for_testing)
+    return;
+
+  CHECK(!g_bluez_dbus_manager);
+  CreateGlobalInstance(bus, use_dbus_stub);
+}
+
+// static
+scoped_ptr<BluezDBusManagerSetter>
+bluez::BluezDBusManager::GetSetterForTesting() {
+  if (!g_using_bluez_dbus_manager_for_testing) {
+    g_using_bluez_dbus_manager_for_testing = true;
+    CreateGlobalInstance(nullptr, true);
+  }
+
+  return make_scoped_ptr(new BluezDBusManagerSetter());
+}
+
+// static
+void BluezDBusManager::CreateGlobalInstance(dbus::Bus* bus, bool use_stubs) {
+  CHECK(!g_bluez_dbus_manager);
+  g_bluez_dbus_manager = new BluezDBusManager(
+      bus, make_scoped_ptr(new BluetoothDBusClientBundle(use_stubs)));
+  g_bluez_dbus_manager->InitializeClients();
+}
+
+// static
+bool BluezDBusManager::IsInitialized() {
+  return g_bluez_dbus_manager != nullptr;
+}
+
+// static
+void BluezDBusManager::Shutdown() {
+  // Ensure that we only shutdown BluezDBusManager once.
+  CHECK(g_bluez_dbus_manager);
+  BluezDBusManager* dbus_manager = g_bluez_dbus_manager;
+  g_bluez_dbus_manager = nullptr;
+  g_using_bluez_dbus_manager_for_testing = false;
+  delete dbus_manager;
+  VLOG(1) << "BluezDBusManager Shutdown completed";
+}
+
+// static
+BluezDBusManager* bluez::BluezDBusManager::Get() {
+  CHECK(g_bluez_dbus_manager)
+      << "bluez::BluezDBusManager::Get() called before Initialize()";
+  return g_bluez_dbus_manager;
+}
+
+BluezDBusManagerSetter::BluezDBusManagerSetter() {}
+
+BluezDBusManagerSetter::~BluezDBusManagerSetter() {}
+
+void BluezDBusManagerSetter::SetBluetoothAdapterClient(
+    scoped_ptr<BluetoothAdapterClient> client) {
+  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_adapter_client_ =
+      client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothLEAdvertisingManagerClient(
+    scoped_ptr<BluetoothLEAdvertisingManagerClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_le_advertising_manager_client_ =
+      client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothAgentManagerClient(
+    scoped_ptr<BluetoothAgentManagerClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_agent_manager_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothDeviceClient(
+    scoped_ptr<BluetoothDeviceClient> client) {
+  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_device_client_ =
+      client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothGattCharacteristicClient(
+    scoped_ptr<BluetoothGattCharacteristicClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_gatt_characteristic_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothGattDescriptorClient(
+    scoped_ptr<BluetoothGattDescriptorClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_gatt_descriptor_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothGattManagerClient(
+    scoped_ptr<BluetoothGattManagerClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_gatt_manager_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothGattServiceClient(
+    scoped_ptr<BluetoothGattServiceClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_gatt_service_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothInputClient(
+    scoped_ptr<BluetoothInputClient> client) {
+  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_input_client_ =
+      client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothMediaClient(
+    scoped_ptr<BluetoothMediaClient> client) {
+  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_media_client_ =
+      client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothMediaTransportClient(
+    scoped_ptr<BluetoothMediaTransportClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_media_transport_client_ = client.Pass();
+}
+
+void BluezDBusManagerSetter::SetBluetoothProfileManagerClient(
+    scoped_ptr<BluetoothProfileManagerClient> client) {
+  bluez::BluezDBusManager::Get()
+      ->client_bundle_->bluetooth_profile_manager_client_ = client.Pass();
+}
+
+}  // namespace bluez
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.h b/device/bluetooth/dbus/bluez_dbus_manager.h
new file mode 100644
index 0000000..6f75f96
--- /dev/null
+++ b/device/bluetooth/dbus/bluez_dbus_manager.h
@@ -0,0 +1,157 @@
+// 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 DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_
+#define DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_dbus_client_bundle.h"
+
+namespace dbus {
+class Bus;
+class ObjectPath;
+}  // namespace dbus
+
+namespace bluez {
+
+// Style Note: Clients are sorted by names.
+class BluetoothAdapterClient;
+class BluetoothAgentManagerClient;
+class BluetoothDeviceClient;
+class BluetoothGattCharacteristicClient;
+class BluetoothGattDescriptorClient;
+class BluetoothGattManagerClient;
+class BluetoothGattServiceClient;
+class BluetoothInputClient;
+class BluetoothLEAdvertisingManagerClient;
+class BluetoothMediaClient;
+class BluetoothMediaTransportClient;
+class BluetoothProfileManagerClient;
+class BluezDBusManagerSetter;
+
+// BluezDBusManager manages manages D-Bus connections and D-Bus clients, which
+// depend on the D-Bus thread to ensure the right order of shutdowns for
+// the D-Bus thread, the D-Bus connections, and the D-Bus clients.
+//
+// CALLBACKS IN D-BUS CLIENTS:
+//
+// D-Bus clients managed by BluezDBusManagerSetter are guaranteed to be deleted
+// after the D-Bus thread so the clients don't need to worry if new
+// incoming messages arrive from the D-Bus thread during shutdown of the
+// clients. The UI message loop is not running during the shutdown hence
+// the UI message loop won't post tasks to D-BUS clients during the
+// shutdown. However, to be extra cautious, clients should use
+// WeakPtrFactory when creating callbacks that run on UI thread. See
+// session_manager_client.cc for examples.
+//
+class DEVICE_BLUETOOTH_EXPORT BluezDBusManager {
+ public:
+  // Sets the global instance. Must be called before any calls to Get().
+  // We explicitly initialize and shut down the global object, rather than
+  // making it a Singleton, to ensure clean startup and shutdown.
+  // This will initialize real or stub DBusClients depending on command-line
+  // arguments and whether this process runs in a ChromeOS environment.
+  static void Initialize(dbus::Bus* bus, bool use_dbus_stub);
+
+  // Returns a BluezDBusManagerSetter instance that allows tests to
+  // replace individual D-Bus clients with their own implementations.
+  // Also initializes the main BluezDBusManager for testing if necessary.
+  static scoped_ptr<BluezDBusManagerSetter> GetSetterForTesting();
+
+  // Returns true if BluezDBusManager has been initialized. Call this to
+  // avoid initializing + shutting down BluezDBusManager more than once.
+  static bool IsInitialized();
+
+  // Destroys the global instance.
+  static void Shutdown();
+
+  // Gets the global instance. Initialize() must be called first.
+  static BluezDBusManager* Get();
+
+  // Returns true if |client| is stubbed.
+  bool IsUsingStub() { return client_bundle_->IsUsingStub(); }
+
+  // Returns various D-Bus bus instances, owned by BluezDBusManager.
+  dbus::Bus* GetSystemBus();
+
+  // All returned objects are owned by BluezDBusManager.  Do not use these
+  // pointers after BluezDBusManager has been shut down.
+  BluetoothAdapterClient* GetBluetoothAdapterClient();
+  BluetoothLEAdvertisingManagerClient* GetBluetoothLEAdvertisingManagerClient();
+  BluetoothAgentManagerClient* GetBluetoothAgentManagerClient();
+  BluetoothDeviceClient* GetBluetoothDeviceClient();
+  BluetoothGattCharacteristicClient* GetBluetoothGattCharacteristicClient();
+  BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient();
+  BluetoothGattManagerClient* GetBluetoothGattManagerClient();
+  BluetoothGattServiceClient* GetBluetoothGattServiceClient();
+  BluetoothInputClient* GetBluetoothInputClient();
+  BluetoothMediaClient* GetBluetoothMediaClient();
+  BluetoothMediaTransportClient* GetBluetoothMediaTransportClient();
+  BluetoothProfileManagerClient* GetBluetoothProfileManagerClient();
+
+ private:
+  friend class BluezDBusManagerSetter;
+
+  // Creates a new BluezDBusManager using the DBusClients set in
+  // |client_bundle|.
+  explicit BluezDBusManager(
+      dbus::Bus* bus,
+      scoped_ptr<BluetoothDBusClientBundle> client_bundle);
+  ~BluezDBusManager();
+
+  // Creates a global instance of BluezDBusManager. Cannot be called more than
+  // once.
+  static void CreateGlobalInstance(dbus::Bus* bus, bool use_stubs);
+
+  // Initializes all currently stored DBusClients with the system bus and
+  // performs additional setup.
+  void InitializeClients();
+
+  dbus::Bus* bus_;
+  scoped_ptr<BluetoothDBusClientBundle> client_bundle_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluezDBusManager);
+};
+
+class DEVICE_BLUETOOTH_EXPORT BluezDBusManagerSetter {
+ public:
+  ~BluezDBusManagerSetter();
+
+  void SetBluetoothAdapterClient(scoped_ptr<BluetoothAdapterClient> client);
+  void SetBluetoothLEAdvertisingManagerClient(
+      scoped_ptr<BluetoothLEAdvertisingManagerClient> client);
+  void SetBluetoothAgentManagerClient(
+      scoped_ptr<BluetoothAgentManagerClient> client);
+  void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client);
+  void SetBluetoothGattCharacteristicClient(
+      scoped_ptr<BluetoothGattCharacteristicClient> client);
+  void SetBluetoothGattDescriptorClient(
+      scoped_ptr<BluetoothGattDescriptorClient> client);
+  void SetBluetoothGattManagerClient(
+      scoped_ptr<BluetoothGattManagerClient> client);
+  void SetBluetoothGattServiceClient(
+      scoped_ptr<BluetoothGattServiceClient> client);
+  void SetBluetoothInputClient(scoped_ptr<BluetoothInputClient> client);
+  void SetBluetoothMediaClient(scoped_ptr<BluetoothMediaClient> client);
+  void SetBluetoothMediaTransportClient(
+      scoped_ptr<BluetoothMediaTransportClient> client);
+  void SetBluetoothProfileManagerClient(
+      scoped_ptr<BluetoothProfileManagerClient> client);
+
+ private:
+  friend class BluezDBusManager;
+
+  BluezDBusManagerSetter();
+
+  DISALLOW_COPY_AND_ASSIGN(BluezDBusManagerSetter);
+};
+
+}  // namespace bluez
+
+#endif  // DEVICE_BLUETOOTH_DBUS_BLUEZ_DBUS_MANAGER_H_
diff --git a/chromeos/dbus/fake_bluetooth_adapter_client.cc b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
similarity index 84%
rename from chromeos/dbus/fake_bluetooth_adapter_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
index 054a6916..f928768 100644
--- a/chromeos/dbus/fake_bluetooth_adapter_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
 
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -22,15 +22,11 @@
 
 }  // namespace
 
-const char FakeBluetoothAdapterClient::kAdapterPath[] =
-    "/fake/hci0";
-const char FakeBluetoothAdapterClient::kAdapterName[] =
-    "Fake Adapter";
-const char FakeBluetoothAdapterClient::kAdapterAddress[] =
-    "01:1A:2B:1A:2B:03";
+const char FakeBluetoothAdapterClient::kAdapterPath[] = "/fake/hci0";
+const char FakeBluetoothAdapterClient::kAdapterName[] = "Fake Adapter";
+const char FakeBluetoothAdapterClient::kAdapterAddress[] = "01:1A:2B:1A:2B:03";
 
-const char FakeBluetoothAdapterClient::kSecondAdapterPath[] =
-    "/fake/hci1";
+const char FakeBluetoothAdapterClient::kSecondAdapterPath[] = "/fake/hci1";
 const char FakeBluetoothAdapterClient::kSecondAdapterName[] =
     "Second Fake Adapter";
 const char FakeBluetoothAdapterClient::kSecondAdapterAddress[] =
@@ -39,13 +35,11 @@
 FakeBluetoothAdapterClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothAdapterClient::Properties(
-        NULL,
-        bluetooth_adapter::kBluetoothAdapterInterface,
-        callback) {
-}
+          NULL,
+          bluetooth_adapter::kBluetoothAdapterInterface,
+          callback) {}
 
-FakeBluetoothAdapterClient::Properties::~Properties() {
-}
+FakeBluetoothAdapterClient::Properties::~Properties() {}
 
 void FakeBluetoothAdapterClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -59,11 +53,10 @@
 }
 
 void FakeBluetoothAdapterClient::Properties::Set(
-    dbus::PropertyBase *property,
+    dbus::PropertyBase* property,
     dbus::PropertySet::SetCallback callback) {
   VLOG(1) << "Set " << property->name();
-  if (property->name() == powered.name() ||
-      property->name() == alias.name() ||
+  if (property->name() == powered.name() || property->name() == alias.name() ||
       property->name() == discoverable.name() ||
       property->name() == discoverable_timeout.name()) {
     callback.Run(true);
@@ -96,11 +89,9 @@
   second_properties_->pairable.ReplaceValue(true);
 }
 
-FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {
-}
+FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {}
 
-void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothAdapterClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -148,7 +139,7 @@
 
     FakeBluetoothDeviceClient* device_client =
         static_cast<FakeBluetoothDeviceClient*>(
-            DBusThreadManager::Get()->GetBluetoothDeviceClient());
+            bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient());
     device_client->BeginDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
   }
 }
@@ -176,7 +167,7 @@
   if (discovering_count_ == 0) {
     FakeBluetoothDeviceClient* device_client =
         static_cast<FakeBluetoothDeviceClient*>(
-            DBusThreadManager::Get()->GetBluetoothDeviceClient());
+            bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient());
     device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
 
     if (simulation_interval_ms_ > 100) {
@@ -199,13 +190,13 @@
     return;
   }
 
-  VLOG(1) << "RemoveDevice: " << object_path.value()
-          << " " << device_path.value();
+  VLOG(1) << "RemoveDevice: " << object_path.value() << " "
+          << device_path.value();
   callback.Run();
 
   FakeBluetoothDeviceClient* device_client =
       static_cast<FakeBluetoothDeviceClient*>(
-          DBusThreadManager::Get()->GetBluetoothDeviceClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient());
   device_client->RemoveDevice(dbus::ObjectPath(kAdapterPath), device_path);
 }
 
@@ -244,8 +235,7 @@
   return discovery_filter_.get();
 }
 
-void FakeBluetoothAdapterClient::SetVisible(
-    bool visible) {
+void FakeBluetoothAdapterClient::SetVisible(bool visible) {
   if (visible && !visible_) {
     // Adapter becoming visible
     visible_ = visible;
@@ -262,8 +252,7 @@
   }
 }
 
-void FakeBluetoothAdapterClient::SetSecondVisible(
-    bool visible) {
+void FakeBluetoothAdapterClient::SetSecondVisible(bool visible) {
   if (visible && !second_visible_) {
     // Second adapter becoming visible
     second_visible_ = visible;
@@ -292,9 +281,9 @@
     }
   }
 
-  FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
-                    AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath),
-                                           property_name));
+  FOR_EACH_OBSERVER(
+      BluetoothAdapterClient::Observer, observers_,
+      AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath), property_name));
 }
 
 void FakeBluetoothAdapterClient::PostDelayedTask(
@@ -304,4 +293,4 @@
       base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_adapter_client.h b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
similarity index 94%
rename from chromeos/dbus/fake_bluetooth_adapter_client.h
rename to device/bluetooth/dbus/fake_bluetooth_adapter_client.h
index 987fc6f..51cd808 100644
--- a/chromeos/dbus/fake_bluetooth_adapter_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
@@ -10,17 +10,17 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_adapter_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothAdapterClient simulates the behavior of the Bluetooth Daemon
 // adapter objects and is used both in test cases in place of a mock and on
 // the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothAdapterClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAdapterClient
     : public BluetoothAdapterClient {
  public:
   struct Properties : public BluetoothAdapterClient::Properties {
@@ -113,6 +113,6 @@
   int simulation_interval_ms_;
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_ADAPTER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
similarity index 88%
rename from chromeos/dbus/fake_bluetooth_agent_manager_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
index 1b8decc..59044412 100644
--- a/chromeos/dbus/fake_bluetooth_agent_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
@@ -2,23 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
 
 #include "base/logging.h"
-#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothAgentManagerClient::FakeBluetoothAgentManagerClient()
-    : service_provider_(NULL) {
-}
+    : service_provider_(NULL) {}
 
-FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() {
-}
+FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() {}
 
-void FakeBluetoothAgentManagerClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothAgentManagerClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothAgentManagerClient::RegisterAgent(
     const dbus::ObjectPath& agent_path,
@@ -78,4 +75,4 @@
   return service_provider_;
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_agent_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
similarity index 90%
rename from chromeos/dbus/fake_bluetooth_agent_manager_client.h
rename to device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
index 68c91202c3..8d7e30c 100644
--- a/chromeos/dbus/fake_bluetooth_agent_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
@@ -8,19 +8,19 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_agent_manager_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothAgentServiceProvider;
 
 // FakeBluetoothAgentManagerClient simulates the behavior of the Bluetooth
 // Daemon's agent manager object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothAgentManagerClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAgentManagerClient
     : public BluetoothAgentManagerClient {
  public:
   FakeBluetoothAgentManagerClient();
@@ -52,6 +52,6 @@
   FakeBluetoothAgentServiceProvider* service_provider_;
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_agent_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
similarity index 84%
rename from chromeos/dbus/fake_bluetooth_agent_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
index caf2988..777deb0e0 100644
--- a/chromeos/dbus/fake_bluetooth_agent_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
@@ -2,23 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h"
 
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothAgentServiceProvider::FakeBluetoothAgentServiceProvider(
     const dbus::ObjectPath& object_path,
     Delegate* delegate)
-    : object_path_(object_path),
-      delegate_(delegate) {
+    : object_path_(object_path), delegate_(delegate) {
   VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value();
 
   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
       static_cast<FakeBluetoothAgentManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient());
   fake_bluetooth_agent_manager_client->RegisterAgentServiceProvider(this);
 }
 
@@ -27,7 +26,7 @@
 
   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
       static_cast<FakeBluetoothAgentManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient());
   fake_bluetooth_agent_manager_client->UnregisterAgentServiceProvider(this);
 }
 
@@ -62,9 +61,10 @@
 
 void FakeBluetoothAgentServiceProvider::DisplayPasskey(
     const dbus::ObjectPath& device_path,
-    uint32 passkey, int16 entered) {
-  VLOG(1) << object_path_.value() << ": DisplayPasskey " << passkey
-          << " (" << entered << " entered) for "<< device_path.value();
+    uint32 passkey,
+    int16 entered) {
+  VLOG(1) << object_path_.value() << ": DisplayPasskey " << passkey << " ("
+          << entered << " entered) for " << device_path.value();
   delegate_->DisplayPasskey(device_path, passkey, entered);
 }
 
@@ -73,7 +73,7 @@
     uint32 passkey,
     const Delegate::ConfirmationCallback& callback) {
   VLOG(1) << object_path_.value() << ": RequestConfirmation " << passkey
-          << " for "<< device_path.value();
+          << " for " << device_path.value();
   delegate_->RequestConfirmation(device_path, passkey, callback);
 }
 
@@ -99,4 +99,4 @@
   delegate_->Cancel();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_agent_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h
similarity index 79%
rename from chromeos/dbus/fake_bluetooth_agent_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h
index 9de89bf1..37e1ce6 100644
--- a/chromeos/dbus/fake_bluetooth_agent_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h
@@ -8,23 +8,23 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothAgentManagerClient;
 
 // FakeBluetoothAgentServiceProvider simulates the behavior of a local
 // Bluetooth agent object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothAgentServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothAgentServiceProvider
     : public BluetoothAgentServiceProvider {
  public:
   FakeBluetoothAgentServiceProvider(const dbus::ObjectPath& object_path,
-                                    Delegate *delegate);
+                                    Delegate* delegate);
   ~FakeBluetoothAgentServiceProvider() override;
 
   // Each of these calls the equivalent BluetoothAgentServiceProvider::Delegate
@@ -37,7 +37,8 @@
   virtual void RequestPasskey(const dbus::ObjectPath& device_path,
                               const Delegate::PasskeyCallback& callback);
   virtual void DisplayPasskey(const dbus::ObjectPath& device_path,
-                              uint32 passkey, int16 entered);
+                              uint32 passkey,
+                              int16 entered);
   virtual void RequestConfirmation(
       const dbus::ObjectPath& device_path,
       uint32 passkey,
@@ -45,10 +46,9 @@
   virtual void RequestAuthorization(
       const dbus::ObjectPath& device_path,
       const Delegate::ConfirmationCallback& callback);
-  virtual void AuthorizeService(
-      const dbus::ObjectPath& device_path,
-      const std::string& uuid,
-      const Delegate::ConfirmationCallback& callback);
+  virtual void AuthorizeService(const dbus::ObjectPath& device_path,
+                                const std::string& uuid,
+                                const Delegate::ConfirmationCallback& callback);
   virtual void Cancel();
 
  private:
@@ -63,6 +63,6 @@
   Delegate* delegate_;
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
similarity index 91%
rename from chromeos/dbus/fake_bluetooth_device_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_device_client.cc
index 8e08656..33dacabb 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_device_client.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 "chromeos/dbus/fake_bluetooth_device_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
 
 #include <fcntl.h>
 #include <sys/socket.h>
@@ -22,15 +22,15 @@
 #include "base/thread_task_runner_handle.h"
 #include "base/threading/worker_pool.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
-#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
 #include "dbus/file_descriptor.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace {
@@ -94,7 +94,7 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 const char FakeBluetoothDeviceClient::kTestPinCode[] = "123456";
 const int FakeBluetoothDeviceClient::kTestPassKey = 123456;
@@ -109,24 +109,20 @@
 const char FakeBluetoothDeviceClient::kPairingActionFail[] = "Fail";
 const char FakeBluetoothDeviceClient::kPairingActionRequest[] = "Request";
 
-const char FakeBluetoothDeviceClient::kPairedDevicePath[] =
-    "/fake/hci0/dev0";
+const char FakeBluetoothDeviceClient::kPairedDevicePath[] = "/fake/hci0/dev0";
 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] =
     "00:11:22:33:44:55";
-const char FakeBluetoothDeviceClient::kPairedDeviceName[] =
-    "Fake Device";
+const char FakeBluetoothDeviceClient::kPairedDeviceName[] = "Fake Device";
 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104;
 
-const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] =
-    "/fake/hci0/dev1";
+const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] = "/fake/hci0/dev1";
 const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] =
     "28:CF:DA:00:00:00";
 const char FakeBluetoothDeviceClient::kLegacyAutopairName[] =
     "Bluetooth 2.0 Mouse";
 const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580;
 
-const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] =
-    "/fake/hci0/dev2";
+const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] = "/fake/hci0/dev2";
 const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] =
     "28:37:37:00:00:00";
 const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] =
@@ -149,36 +145,29 @@
     "Unpairable Device";
 const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580;
 
-const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] =
-    "/fake/hci0/dev5";
+const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] = "/fake/hci0/dev5";
 const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] =
     "00:0F:F6:00:00:00";
 const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] =
     "Bluetooth 2.1+ Keyboard";
 const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540;
 
-const char FakeBluetoothDeviceClient::kRequestPinCodePath[] =
-    "/fake/hci0/dev6";
+const char FakeBluetoothDeviceClient::kRequestPinCodePath[] = "/fake/hci0/dev6";
 const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] =
     "00:24:BE:00:00:00";
-const char FakeBluetoothDeviceClient::kRequestPinCodeName[] =
-    "PIN Device";
+const char FakeBluetoothDeviceClient::kRequestPinCodeName[] = "PIN Device";
 const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408;
 
-const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] =
-    "/fake/hci0/dev7";
+const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] = "/fake/hci0/dev7";
 const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] =
     "20:7D:74:00:00:00";
-const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] =
-    "Phone";
+const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] = "Phone";
 const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c;
 
-const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] =
-    "/fake/hci0/dev8";
+const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] = "/fake/hci0/dev8";
 const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] =
     "20:7D:74:00:00:01";
-const char FakeBluetoothDeviceClient::kRequestPasskeyName[] =
-    "Passkey Device";
+const char FakeBluetoothDeviceClient::kRequestPasskeyName[] = "Passkey Device";
 const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c;
 
 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] =
@@ -197,18 +186,13 @@
     "Unpairable Device";
 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540;
 
-const char FakeBluetoothDeviceClient::kJustWorksPath[] =
-    "/fake/hci0/devB";
-const char FakeBluetoothDeviceClient::kJustWorksAddress[] =
-    "00:0C:8A:00:00:00";
-const char FakeBluetoothDeviceClient::kJustWorksName[] =
-    "Just-Works Device";
+const char FakeBluetoothDeviceClient::kJustWorksPath[] = "/fake/hci0/devB";
+const char FakeBluetoothDeviceClient::kJustWorksAddress[] = "00:0C:8A:00:00:00";
+const char FakeBluetoothDeviceClient::kJustWorksName[] = "Just-Works Device";
 const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428;
 
-const char FakeBluetoothDeviceClient::kLowEnergyPath[] =
-    "/fake/hci0/devC";
-const char FakeBluetoothDeviceClient::kLowEnergyAddress[] =
-    "00:1A:11:00:15:30";
+const char FakeBluetoothDeviceClient::kLowEnergyPath[] = "/fake/hci0/devC";
+const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = "00:1A:11:00:15:30";
 const char FakeBluetoothDeviceClient::kLowEnergyName[] =
     "Bluetooth 4.0 Heart Rate Monitor";
 const uint32 FakeBluetoothDeviceClient::kLowEnergyClass =
@@ -223,16 +207,24 @@
 const uint32 FakeBluetoothDeviceClient::kPairedUnconnectableDeviceClass =
     0x000104;
 
+const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDevicePath[] =
+    "/fake/hci0/devE";
+const char
+    FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceAddress[] =
+        "11:22:33:44:55:66";
+const char FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceName[] =
+    "Connected Pairable Device";
+const uint32 FakeBluetoothDeviceClient::kConnectedTrustedNotPairedDeviceClass =
+    0x7a020c;
+
 FakeBluetoothDeviceClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothDeviceClient::Properties(
           NULL,
           bluetooth_device::kBluetoothDeviceInterface,
-          callback) {
-}
+          callback) {}
 
-FakeBluetoothDeviceClient::Properties::~Properties() {
-}
+FakeBluetoothDeviceClient::Properties::~Properties() {}
 
 void FakeBluetoothDeviceClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -246,7 +238,7 @@
 }
 
 void FakeBluetoothDeviceClient::Properties::Set(
-    dbus::PropertyBase *property,
+    dbus::PropertyBase* property,
     dbus::PropertySet::SetCallback callback) {
   VLOG(1) << "Set " << property->name();
   if (property->name() == trusted.name()) {
@@ -320,11 +312,9 @@
   device_list_.push_back(dbus::ObjectPath(kPairedUnconnectableDevicePath));
 }
 
-FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
-}
+FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {}
 
-void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -343,8 +333,8 @@
     return std::vector<dbus::ObjectPath>();
 }
 
-FakeBluetoothDeviceClient::Properties*
-FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) {
+FakeBluetoothDeviceClient::Properties* FakeBluetoothDeviceClient::GetProperties(
+    const dbus::ObjectPath& object_path) {
   PropertiesMap::const_iterator iter = properties_map_.find(object_path);
   if (iter != properties_map_.end())
     return iter->second;
@@ -361,10 +351,9 @@
   return iter != pairing_options_map_.end() ? iter->second : nullptr;
 }
 
-void FakeBluetoothDeviceClient::Connect(
-    const dbus::ObjectPath& object_path,
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+void FakeBluetoothDeviceClient::Connect(const dbus::ObjectPath& object_path,
+                                        const base::Closure& callback,
+                                        const ErrorCallback& error_callback) {
   VLOG(1) << "Connect: " << object_path.value();
   Properties* properties = GetProperties(object_path);
 
@@ -398,7 +387,7 @@
   if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
     FakeBluetoothGattServiceClient* gatt_service_client =
         static_cast<FakeBluetoothGattServiceClient*>(
-            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+            bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient());
     gatt_service_client->ExposeHeartRateService(
         dbus::ObjectPath(kLowEnergyPath));
   }
@@ -422,7 +411,7 @@
   if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
     FakeBluetoothGattServiceClient* gatt_service_client =
         static_cast<FakeBluetoothGattServiceClient*>(
-            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+            bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient());
     gatt_service_client->HideHeartRateService();
   }
 
@@ -439,7 +428,7 @@
 
   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
       static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient());
   FakeBluetoothProfileServiceProvider* profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
   if (profile_service_provider == NULL) {
@@ -478,10 +467,8 @@
     return;
   }
 
-  base::WorkerPool::GetTaskRunner(false)->PostTask(
-      FROM_HERE,
-      base::Bind(&SimulatedProfileSocket,
-                 fds[0]));
+  base::WorkerPool::GetTaskRunner(false)
+      ->PostTask(FROM_HERE, base::Bind(&SimulatedProfileSocket, fds[0]));
 
   scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));
 
@@ -489,13 +476,9 @@
   BluetoothProfileServiceProvider::Delegate::Options options;
 
   profile_service_provider->NewConnection(
-      object_path,
-      fd.Pass(),
-      options,
+      object_path, fd.Pass(), options,
       base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
-                 base::Unretained(this),
-                 object_path,
-                 callback,
+                 base::Unretained(this), object_path, callback,
                  error_callback));
 }
 
@@ -508,7 +491,7 @@
 
   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
       static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient());
   FakeBluetoothProfileServiceProvider* profile_service_provider =
       fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
   if (profile_service_provider == NULL) {
@@ -517,18 +500,14 @@
   }
 
   profile_service_provider->RequestDisconnection(
-      object_path,
-      base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
-                 base::Unretained(this),
-                 object_path,
-                 callback,
-                 error_callback));
+      object_path, base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
+                              base::Unretained(this), object_path, callback,
+                              error_callback));
 }
 
-void FakeBluetoothDeviceClient::Pair(
-    const dbus::ObjectPath& object_path,
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+void FakeBluetoothDeviceClient::Pair(const dbus::ObjectPath& object_path,
+                                     const base::Closure& callback,
+                                     const ErrorCallback& error_callback) {
   VLOG(1) << "Pair: " << object_path.value();
   Properties* properties = GetProperties(object_path);
 
@@ -610,8 +589,8 @@
 void FakeBluetoothDeviceClient::CreateDevice(
     const dbus::ObjectPath& adapter_path,
     const dbus::ObjectPath& device_path) {
-  if (std::find(device_list_.begin(),
-                device_list_.end(), device_path) != device_list_.end())
+  if (std::find(device_list_.begin(), device_list_.end(), device_path) !=
+      device_list_.end())
     return;
 
   scoped_ptr<Properties> properties(
@@ -710,10 +689,18 @@
     std::vector<std::string> uuids;
     uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID);
     properties->uuids.ReplaceValue(uuids);
-
+  } else if (device_path ==
+             dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) {
+    properties->address.ReplaceValue(kConnectedTrustedNotPairedDeviceAddress);
+    properties->bluetooth_class.ReplaceValue(
+        kConnectedTrustedNotPairedDeviceClass);
+    properties->trusted.ReplaceValue(true);
+    properties->connected.ReplaceValue(true);
+    properties->paired.ReplaceValue(false);
+    properties->name.ReplaceValue("Connected Pairable Device");
+    properties->alias.ReplaceValue(kConnectedTrustedNotPairedDeviceName);
   } else {
     NOTREACHED();
-
   }
 
   properties_map_.insert(device_path, properties.Pass());
@@ -972,6 +959,27 @@
   paired_unconnectable->SetBoolean("incoming", false);
   predefined_devices->Append(paired_unconnectable.Pass());
 
+  scoped_ptr<base::DictionaryValue> connected_trusted_not_paired(
+      new base::DictionaryValue);
+  connected_trusted_not_paired->SetString("path",
+                                          kConnectedTrustedNotPairedDevicePath);
+  connected_trusted_not_paired->SetString(
+      "address", kConnectedTrustedNotPairedDeviceAddress);
+  connected_trusted_not_paired->SetString("name",
+                                          kConnectedTrustedNotPairedDeviceName);
+  connected_trusted_not_paired->SetString("pairingMethod", "");
+  connected_trusted_not_paired->SetString("pairingAuthToken", "");
+  connected_trusted_not_paired->SetString("pairingAction", "");
+  connected_trusted_not_paired->SetString("alias",
+                                          kConnectedTrustedNotPairedDeviceName);
+  connected_trusted_not_paired->SetInteger(
+      "classValue", kConnectedTrustedNotPairedDeviceClass);
+  connected_trusted_not_paired->SetBoolean("isTrusted", true);
+  connected_trusted_not_paired->SetBoolean("discoverable", true);
+  connected_trusted_not_paired->SetBoolean("paired", false);
+  connected_trusted_not_paired->SetBoolean("incoming", false);
+  predefined_devices->Append(connected_trusted_not_paired.Pass());
+
   return predefined_devices.Pass();
 }
 
@@ -994,13 +1002,13 @@
   // BluetoothDeviceChromeOS object, including the device_path referenced here.
   FakeBluetoothInputClient* fake_bluetooth_input_client =
       static_cast<FakeBluetoothInputClient*>(
-          DBusThreadManager::Get()->GetBluetoothInputClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothInputClient());
   fake_bluetooth_input_client->RemoveInputDevice(device_path);
 
   if (device_path == dbus::ObjectPath(kLowEnergyPath)) {
     FakeBluetoothGattServiceClient* gatt_service_client =
         static_cast<FakeBluetoothGattServiceClient*>(
-            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+            bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient());
     gatt_service_client->HideHeartRateService();
   }
 
@@ -1083,7 +1091,6 @@
     UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
                      base::RandInt(kMinRSSI, kMaxRSSI));
     return;
-
   }
 
   ++discovery_simulation_step_;
@@ -1165,7 +1172,7 @@
 
   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
       static_cast<FakeBluetoothAgentManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient());
   FakeBluetoothAgentServiceProvider* agent_service_provider =
       fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
   CHECK(agent_service_provider != NULL);
@@ -1305,7 +1312,9 @@
                                   base::Unretained(this), object_path, callback,
                                   error_callback));
 
-    } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath)) {
+    } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath) ||
+               object_path ==
+                   dbus::ObjectPath(kConnectedTrustedNotPairedDevicePath)) {
       // Request confirmation of a Passkey.
       agent_service_provider->RequestConfirmation(
           object_path, kTestPassKey,
@@ -1416,7 +1425,7 @@
   // simulate the Input interface.
   FakeBluetoothInputClient* fake_bluetooth_input_client =
       static_cast<FakeBluetoothInputClient*>(
-          DBusThreadManager::Get()->GetBluetoothInputClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothInputClient());
 
   if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500)
     fake_bluetooth_input_client->AddInputDevice(object_path);
@@ -1586,7 +1595,7 @@
 
   FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
       static_cast<FakeBluetoothAgentManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient());
   FakeBluetoothAgentServiceProvider* agent_service_provider =
       fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
 
@@ -1649,4 +1658,4 @@
   }
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/device/bluetooth/dbus/fake_bluetooth_device_client.h
similarity index 81%
rename from chromeos/dbus/fake_bluetooth_device_client.h
rename to device/bluetooth/dbus/fake_bluetooth_device_client.h
index c19e965..d44bde5 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_device_client.h
@@ -12,23 +12,23 @@
 #include "base/callback.h"
 #include "base/containers/scoped_ptr_map.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_agent_service_provider.h"
-#include "chromeos/dbus/bluetooth_device_client.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
+#include "device/bluetooth/dbus/bluetooth_device_client.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothDeviceClient simulates the behavior of the Bluetooth Daemon
 // device objects and is used both in test cases in place of a mock and on
 // the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothDeviceClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
     : public BluetoothDeviceClient {
  public:
   struct Properties : public BluetoothDeviceClient::Properties {
-    explicit Properties(const PropertyChangedCallback & callback);
+    explicit Properties(const PropertyChangedCallback& callback);
     ~Properties() override;
 
     // dbus::PropertySet override
@@ -229,6 +229,11 @@
   static const char kPairedUnconnectableDeviceAddress[];
   static const uint32 kPairedUnconnectableDeviceClass;
 
+  static const char kConnectedTrustedNotPairedDevicePath[];
+  static const char kConnectedTrustedNotPairedDeviceAddress[];
+  static const char kConnectedTrustedNotPairedDeviceName[];
+  static const uint32 kConnectedTrustedNotPairedDeviceClass;
+
  private:
   // Property callback passed when we create Properties* structures.
   void OnPropertyChanged(const dbus::ObjectPath& object_path,
@@ -237,52 +242,43 @@
   void DiscoverySimulationTimer();
   void IncomingPairingSimulationTimer();
 
-  void CompleteSimulatedPairing(
-      const dbus::ObjectPath& object_path,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback);
-  void TimeoutSimulatedPairing(
-      const dbus::ObjectPath& object_path,
-      const ErrorCallback& error_callback);
-  void CancelSimulatedPairing(
-      const dbus::ObjectPath& object_path,
-      const ErrorCallback& error_callback);
-  void RejectSimulatedPairing(
-      const dbus::ObjectPath& object_path,
-      const ErrorCallback& error_callback);
-  void FailSimulatedPairing(
-      const dbus::ObjectPath& object_path,
-      const ErrorCallback& error_callback);
-  void AddInputDeviceIfNeeded(
-      const dbus::ObjectPath& object_path,
-      Properties* properties);
+  void CompleteSimulatedPairing(const dbus::ObjectPath& object_path,
+                                const base::Closure& callback,
+                                const ErrorCallback& error_callback);
+  void TimeoutSimulatedPairing(const dbus::ObjectPath& object_path,
+                               const ErrorCallback& error_callback);
+  void CancelSimulatedPairing(const dbus::ObjectPath& object_path,
+                              const ErrorCallback& error_callback);
+  void RejectSimulatedPairing(const dbus::ObjectPath& object_path,
+                              const ErrorCallback& error_callback);
+  void FailSimulatedPairing(const dbus::ObjectPath& object_path,
+                            const ErrorCallback& error_callback);
+  void AddInputDeviceIfNeeded(const dbus::ObjectPath& object_path,
+                              Properties* properties);
 
   // Updates the inquiry RSSI property of fake device with object path
   // |object_path| to |rssi|, if the fake device exists.
   void UpdateDeviceRSSI(const dbus::ObjectPath& object_path, int16 rssi);
 
-  void PinCodeCallback(
-      const dbus::ObjectPath& object_path,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback,
-      BluetoothAgentServiceProvider::Delegate::Status status,
-      const std::string& pincode);
-  void PasskeyCallback(
-      const dbus::ObjectPath& object_path,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback,
-      BluetoothAgentServiceProvider::Delegate::Status status,
-      uint32 passkey);
+  void PinCodeCallback(const dbus::ObjectPath& object_path,
+                       const base::Closure& callback,
+                       const ErrorCallback& error_callback,
+                       BluetoothAgentServiceProvider::Delegate::Status status,
+                       const std::string& pincode);
+  void PasskeyCallback(const dbus::ObjectPath& object_path,
+                       const base::Closure& callback,
+                       const ErrorCallback& error_callback,
+                       BluetoothAgentServiceProvider::Delegate::Status status,
+                       uint32 passkey);
   void ConfirmationCallback(
       const dbus::ObjectPath& object_path,
       const base::Closure& callback,
       const ErrorCallback& error_callback,
       BluetoothAgentServiceProvider::Delegate::Status status);
-  void SimulateKeypress(
-      uint16 entered,
-      const dbus::ObjectPath& object_path,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback);
+  void SimulateKeypress(uint16 entered,
+                        const dbus::ObjectPath& object_path,
+                        const base::Closure& callback,
+                        const ErrorCallback& error_callback);
 
   void ConnectionCallback(
       const dbus::ObjectPath& object_path,
@@ -320,6 +316,6 @@
   int16 max_transmit_power_;
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
similarity index 90%
rename from chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
index 61bbb8d..10f073a 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.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 "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"
 
 #include "base/bind.h"
 #include "base/location.h"
@@ -10,11 +10,11 @@
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -26,17 +26,16 @@
 FakeBluetoothGattCharacteristicClient::DelayedCallback::DelayedCallback(
     base::Closure callback,
     size_t delay)
-    : callback_(callback), delay_(delay) {
-}
+    : callback_(callback), delay_(delay) {}
 
-FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() {
-}
+FakeBluetoothGattCharacteristicClient::DelayedCallback::~DelayedCallback() {}
 
 // static
 const char FakeBluetoothGattCharacteristicClient::
     kHeartRateMeasurementPathComponent[] = "char0000";
-const char FakeBluetoothGattCharacteristicClient::
-    kBodySensorLocationPathComponent[] = "char0001";
+const char
+    FakeBluetoothGattCharacteristicClient::kBodySensorLocationPathComponent[] =
+        "char0001";
 const char FakeBluetoothGattCharacteristicClient::
     kHeartRateControlPointPathComponent[] = "char0002";
 
@@ -53,11 +52,9 @@
     : BluetoothGattCharacteristicClient::Properties(
           NULL,
           bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
-          callback) {
-}
+          callback) {}
 
-FakeBluetoothGattCharacteristicClient::Properties::~Properties() {
-}
+FakeBluetoothGattCharacteristicClient::Properties::~Properties() {}
 
 void FakeBluetoothGattCharacteristicClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -83,8 +80,7 @@
       authenticated_(true),
       calories_burned_(0),
       extra_requests_(0),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
 
 FakeBluetoothGattCharacteristicClient::
     ~FakeBluetoothGattCharacteristicClient() {
@@ -94,8 +90,7 @@
   action_extra_requests_.clear();
 }
 
-void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -247,12 +242,11 @@
   }
   base::Closure completed_callback;
   if (value.size() != 1) {
-    completed_callback = base::Bind(error_callback,
-                                    "org.bluez.Error.InvalidValueLength",
-                                    "Invalid length for write");
+    completed_callback =
+        base::Bind(error_callback, "org.bluez.Error.InvalidValueLength",
+                   "Invalid length for write");
   } else if (value[0] > 1) {
-    completed_callback = base::Bind(error_callback,
-                                    "org.bluez.Error.Failed",
+    completed_callback = base::Bind(error_callback, "org.bluez.Error.Failed",
                                     "Invalid value given for write");
   } else if (value[0] == 1) {
     // TODO(jamuraa): make this happen when the callback happens
@@ -337,10 +331,10 @@
   // ==== Heart Rate Measurement Characteristic ====
   heart_rate_measurement_path_ =
       service_path.value() + "/" + kHeartRateMeasurementPathComponent;
-  heart_rate_measurement_properties_.reset(new Properties(base::Bind(
-      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
-      weak_ptr_factory_.GetWeakPtr(),
-      dbus::ObjectPath(heart_rate_measurement_path_))));
+  heart_rate_measurement_properties_.reset(new Properties(
+      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 dbus::ObjectPath(heart_rate_measurement_path_))));
   heart_rate_measurement_properties_->uuid.ReplaceValue(
       kHeartRateMeasurementUUID);
   heart_rate_measurement_properties_->service.ReplaceValue(service_path);
@@ -350,10 +344,10 @@
   // ==== Body Sensor Location Characteristic ====
   body_sensor_location_path_ =
       service_path.value() + "/" + kBodySensorLocationPathComponent;
-  body_sensor_location_properties_.reset(new Properties(base::Bind(
-      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
-      weak_ptr_factory_.GetWeakPtr(),
-      dbus::ObjectPath(body_sensor_location_path_))));
+  body_sensor_location_properties_.reset(new Properties(
+      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 dbus::ObjectPath(body_sensor_location_path_))));
   body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID);
   body_sensor_location_properties_->service.ReplaceValue(service_path);
   flags.clear();
@@ -363,10 +357,10 @@
   // ==== Heart Rate Control Point Characteristic ====
   heart_rate_control_point_path_ =
       service_path.value() + "/" + kHeartRateControlPointPathComponent;
-  heart_rate_control_point_properties_.reset(new Properties(base::Bind(
-      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
-      weak_ptr_factory_.GetWeakPtr(),
-      dbus::ObjectPath(heart_rate_control_point_path_))));
+  heart_rate_control_point_properties_.reset(new Properties(
+      base::Bind(&FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 dbus::ObjectPath(heart_rate_control_point_path_))));
   heart_rate_control_point_properties_->uuid.ReplaceValue(
       kHeartRateControlPointUUID);
   heart_rate_control_point_properties_->service.ReplaceValue(service_path);
@@ -383,7 +377,7 @@
   // Expose CCC descriptor for Heart Rate Measurement characteristic.
   FakeBluetoothGattDescriptorClient* descriptor_client =
       static_cast<FakeBluetoothGattDescriptorClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattDescriptorClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient());
   dbus::ObjectPath ccc_path(descriptor_client->ExposeDescriptor(
       dbus::ObjectPath(heart_rate_measurement_path_),
       FakeBluetoothGattDescriptorClient::
@@ -403,7 +397,7 @@
   // Hide the descriptors.
   FakeBluetoothGattDescriptorClient* descriptor_client =
       static_cast<FakeBluetoothGattDescriptorClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattDescriptorClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattDescriptorClient());
   descriptor_client->HideDescriptor(
       dbus::ObjectPath(heart_rate_measurement_ccc_desc_path_));
 
@@ -459,12 +453,12 @@
 void FakeBluetoothGattCharacteristicClient::OnPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
-  VLOG(2) << "Characteristic property changed: " << object_path.value()
-          << ": " << property_name;
+  VLOG(2) << "Characteristic property changed: " << object_path.value() << ": "
+          << property_name;
 
-  FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
-                    GattCharacteristicPropertyChanged(
-                        object_path, property_name));
+  FOR_EACH_OBSERVER(
+      BluetoothGattCharacteristicClient::Observer, observers_,
+      GattCharacteristicPropertyChanged(object_path, property_name));
 }
 
 void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded(
@@ -546,7 +540,7 @@
   value.energy_expanded = calories_burned_++;
 
   // Include one RR-Interval value, in seconds.
-  value.rr_interval = 60/value.bpm;
+  value.rr_interval = 60 / value.bpm;
 
   // Return the bytes in an array.
   uint8* bytes = reinterpret_cast<uint8*>(&value);
@@ -565,4 +559,4 @@
   return heart_rate_visible_;
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
similarity index 95%
rename from chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
index 8366169..dc5196d 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -12,17 +12,17 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattCharacteristicClient simulates the behavior of the
 // Bluetooth Daemon GATT characteristic objects and is used in test cases in
 // place of a mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicClient
     : public BluetoothGattCharacteristicClient {
  public:
   struct Properties : public BluetoothGattCharacteristicClient::Properties {
@@ -184,12 +184,11 @@
   // than we do.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<FakeBluetoothGattCharacteristicClient>
-      weak_ptr_factory_;
+  base::WeakPtrFactory<FakeBluetoothGattCharacteristicClient> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc
similarity index 76%
rename from chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc
index 5a548de..03f06d03 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.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 "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
 
 #include "base/logging.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothGattCharacteristicServiceProvider::
     FakeBluetoothGattCharacteristicServiceProvider(
@@ -19,27 +19,26 @@
         const std::vector<std::string>& flags,
         const std::vector<std::string>& permissions,
         const dbus::ObjectPath& service_path)
-        : object_path_(object_path),
-          uuid_(uuid),
-          service_path_(service_path),
-          delegate_(delegate) {
+    : object_path_(object_path),
+      uuid_(uuid),
+      service_path_(service_path),
+      delegate_(delegate) {
   VLOG(1) << "Creating Bluetooth GATT characteristic: " << object_path_.value();
 
   DCHECK(object_path_.IsValid());
   DCHECK(service_path_.IsValid());
   DCHECK(!uuid.empty());
   DCHECK(delegate_);
-  DCHECK(base::StartsWith(object_path_.value(),
-                          service_path_.value() + "/",
+  DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/",
                           base::CompareCase::SENSITIVE));
 
   // TODO(armansito): Do something with |flags| and |permissions|.
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
-  fake_bluetooth_gatt_manager_client->
-      RegisterCharacteristicServiceProvider(this);
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
+  fake_bluetooth_gatt_manager_client->RegisterCharacteristicServiceProvider(
+      this);
 }
 
 FakeBluetoothGattCharacteristicServiceProvider::
@@ -49,9 +48,9 @@
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
-  fake_bluetooth_gatt_manager_client->
-      UnregisterCharacteristicServiceProvider(this);
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
+  fake_bluetooth_gatt_manager_client->UnregisterCharacteristicServiceProvider(
+      this);
 }
 
 void FakeBluetoothGattCharacteristicServiceProvider::SendValueChanged(
@@ -69,7 +68,7 @@
   // Check if this characteristic is registered.
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) {
     VLOG(1) << "GATT characteristic not registered.";
     error_callback.Run();
@@ -91,7 +90,7 @@
   // Check if this characteristic is registered.
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   if (!fake_bluetooth_gatt_manager_client->IsServiceRegistered(service_path_)) {
     VLOG(1) << "GATT characteristic not registered.";
     error_callback.Run();
@@ -103,4 +102,4 @@
   delegate_->SetCharacteristicValue(value, callback, error_callback);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
similarity index 89%
rename from chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
index 8a8440b..a67d6c95 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h
@@ -8,16 +8,16 @@
 #include <string>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_service_provider.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattCharacteristicServiceProvider simulates behavior of a local
 // GATT characteristic object and is used both in test cases in place of a mock
 // and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicServiceProvider
     : public BluetoothGattCharacteristicServiceProvider {
  public:
   FakeBluetoothGattCharacteristicServiceProvider(
@@ -61,6 +61,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
similarity index 86%
rename from chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
index 5ff9bf4..dcaf1ec 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char FakeBluetoothGattDescriptorClient::
     kClientCharacteristicConfigurationPathComponent[] = "desc0000";
@@ -23,11 +23,9 @@
     : BluetoothGattDescriptorClient::Properties(
           NULL,
           bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
-          callback) {
-}
+          callback) {}
 
-FakeBluetoothGattDescriptorClient::Properties::~Properties() {
-}
+FakeBluetoothGattDescriptorClient::Properties::~Properties() {}
 
 void FakeBluetoothGattDescriptorClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -47,24 +45,20 @@
   callback.Run(false);
 }
 
-FakeBluetoothGattDescriptorClient::DescriptorData::DescriptorData() {
-}
+FakeBluetoothGattDescriptorClient::DescriptorData::DescriptorData() {}
 
-FakeBluetoothGattDescriptorClient::DescriptorData::~DescriptorData() {
-}
+FakeBluetoothGattDescriptorClient::DescriptorData::~DescriptorData() {}
 
 FakeBluetoothGattDescriptorClient::FakeBluetoothGattDescriptorClient()
-    : weak_ptr_factory_(this) {
-}
+    : weak_ptr_factory_(this) {}
 
 FakeBluetoothGattDescriptorClient::~FakeBluetoothGattDescriptorClient() {
-  for(PropertiesMap::iterator iter = properties_.begin(); iter !=
-      properties_.end(); iter++)
+  for (PropertiesMap::iterator iter = properties_.begin();
+       iter != properties_.end(); iter++)
     delete iter->second;
 }
 
-void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothGattDescriptorClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -107,7 +101,7 @@
   Properties* properties = iter->second->properties.get();
   if (properties->uuid.value() == kClientCharacteristicConfigurationUUID) {
     BluetoothGattCharacteristicClient::Properties* chrc_props =
-        DBusThreadManager::Get()
+        bluez::BluezDBusManager::Get()
             ->GetBluetoothGattCharacteristicClient()
             ->GetProperties(properties->characteristic.value());
     DCHECK(chrc_props);
@@ -151,9 +145,8 @@
 
   // CCC descriptor is the only one supported at the moment.
   DCHECK(characteristic_path.IsValid());
-  dbus::ObjectPath object_path(
-      characteristic_path.value() + "/" +
-      kClientCharacteristicConfigurationPathComponent);
+  dbus::ObjectPath object_path(characteristic_path.value() + "/" +
+                               kClientCharacteristicConfigurationPathComponent);
   DCHECK(object_path.IsValid());
   PropertiesMap::const_iterator iter = properties_.find(object_path);
   if (iter != properties_.end()) {
@@ -161,10 +154,9 @@
     return dbus::ObjectPath();
   }
 
-  Properties* properties = new Properties(base::Bind(
-      &FakeBluetoothGattDescriptorClient::OnPropertyChanged,
-      weak_ptr_factory_.GetWeakPtr(),
-      object_path));
+  Properties* properties = new Properties(
+      base::Bind(&FakeBluetoothGattDescriptorClient::OnPropertyChanged,
+                 weak_ptr_factory_.GetWeakPtr(), object_path));
   properties->uuid.ReplaceValue(uuid);
   properties->characteristic.ReplaceValue(characteristic_path);
 
@@ -195,8 +187,8 @@
 void FakeBluetoothGattDescriptorClient::OnPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
-  VLOG(2) << "Descriptor property changed: " << object_path.value()
-          << ": " << property_name;
+  VLOG(2) << "Descriptor property changed: " << object_path.value() << ": "
+          << property_name;
 
   FOR_EACH_OBSERVER(BluetoothGattDescriptorClient::Observer, observers_,
                     GattDescriptorPropertyChanged(object_path, property_name));
@@ -214,4 +206,4 @@
                     GattDescriptorRemoved(object_path));
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
similarity index 92%
rename from chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
index fe405c7..e933664a 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
@@ -10,16 +10,16 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattDescriptorClient simulates the behavior of the Bluetooth
 // Daemon GATT characteristic descriptor objects and is used in test cases in
 // place of a mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattDescriptorClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattDescriptorClient
     : public BluetoothGattDescriptorClient {
  public:
   struct Properties : public BluetoothGattDescriptorClient::Properties {
@@ -93,12 +93,11 @@
   // than we do.
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<FakeBluetoothGattDescriptorClient>
-      weak_ptr_factory_;
+  base::WeakPtrFactory<FakeBluetoothGattDescriptorClient> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
similarity index 78%
rename from chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
index 9779c3a..4376ce98 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
 
 #include "base/logging.h"
 #include "base/strings/string_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothGattDescriptorServiceProvider::
     FakeBluetoothGattDescriptorServiceProvider(
@@ -19,10 +19,10 @@
         const std::string& uuid,
         const std::vector<std::string>& permissions,
         const dbus::ObjectPath& characteristic_path)
-        : object_path_(object_path),
-          uuid_(uuid),
-          characteristic_path_(characteristic_path),
-          delegate_(delegate) {
+    : object_path_(object_path),
+      uuid_(uuid),
+      characteristic_path_(characteristic_path),
+      delegate_(delegate) {
   VLOG(1) << "Creating Bluetooth GATT descriptor: " << object_path_.value();
 
   DCHECK(object_path_.IsValid());
@@ -37,21 +37,18 @@
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
-  fake_bluetooth_gatt_manager_client->
-      RegisterDescriptorServiceProvider(this);
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
+  fake_bluetooth_gatt_manager_client->RegisterDescriptorServiceProvider(this);
 }
 
 FakeBluetoothGattDescriptorServiceProvider::
     ~FakeBluetoothGattDescriptorServiceProvider() {
-  VLOG(1) << "Cleaning up Bluetooth GATT descriptor: "
-          << object_path_.value();
+  VLOG(1) << "Cleaning up Bluetooth GATT descriptor: " << object_path_.value();
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
-  fake_bluetooth_gatt_manager_client->
-      UnregisterDescriptorServiceProvider(this);
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
+  fake_bluetooth_gatt_manager_client->UnregisterDescriptorServiceProvider(this);
 }
 
 void FakeBluetoothGattDescriptorServiceProvider::SendValueChanged(
@@ -69,7 +66,7 @@
   // Check if this descriptor is registered.
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   FakeBluetoothGattCharacteristicServiceProvider* characteristic =
       fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider(
           characteristic_path_);
@@ -100,7 +97,7 @@
   // Check if this descriptor is registered.
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   FakeBluetoothGattCharacteristicServiceProvider* characteristic =
       fake_bluetooth_gatt_manager_client->GetCharacteristicServiceProvider(
           characteristic_path_);
@@ -121,4 +118,4 @@
   delegate_->SetDescriptorValue(value, callback, error_callback);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
similarity index 88%
rename from chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
index e9099b9..7e53625e 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h
@@ -8,16 +8,16 @@
 #include <string>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_descriptor_service_provider.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattDescriptorServiceProvider simulates behavior of a local
 // GATT descriptor object and is used both in test cases in place of a mock
 // and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattDescriptorServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattDescriptorServiceProvider
     : public BluetoothGattDescriptorServiceProvider {
  public:
   FakeBluetoothGattDescriptorServiceProvider(
@@ -43,7 +43,7 @@
   const dbus::ObjectPath& object_path() const { return object_path_; }
   const std::string& uuid() const { return uuid_; }
   const dbus::ObjectPath& characteristic_path() const {
-      return characteristic_path_;
+    return characteristic_path_;
   }
 
  private:
@@ -62,6 +62,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
similarity index 87%
rename from chromeos/dbus/fake_bluetooth_gatt_manager_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
index c09232f..284a17c7 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
@@ -2,25 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h"
 
 #include "base/logging.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
-FakeBluetoothGattManagerClient::FakeBluetoothGattManagerClient() {
-}
+FakeBluetoothGattManagerClient::FakeBluetoothGattManagerClient() {}
 
-FakeBluetoothGattManagerClient::~FakeBluetoothGattManagerClient() {
-}
+FakeBluetoothGattManagerClient::~FakeBluetoothGattManagerClient() {}
 
 // DBusClient override.
-void FakeBluetoothGattManagerClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothGattManagerClient::Init(dbus::Bus* bus) {}
 
 // BluetoothGattManagerClient overrides.
 void FakeBluetoothGattManagerClient::RegisterService(
@@ -69,9 +66,8 @@
   // Return error if the GATT service wasn't registered before.
   ServiceProvider* provider = &iter->second;
   if (!provider->first) {
-    error_callback.Run(
-        bluetooth_gatt_manager::kErrorDoesNotExist,
-        "GATT service not registered: " + service_path.value());
+    error_callback.Run(bluetooth_gatt_manager::kErrorDoesNotExist,
+                       "GATT service not registered: " + service_path.value());
     return;
   }
 
@@ -108,8 +104,7 @@
 void FakeBluetoothGattManagerClient::RegisterDescriptorServiceProvider(
     FakeBluetoothGattDescriptorServiceProvider* provider) {
   // Ignore, if a service provider is already registered for the object path.
-  DescriptorMap::iterator iter =
-      descriptor_map_.find(provider->object_path());
+  DescriptorMap::iterator iter = descriptor_map_.find(provider->object_path());
   if (iter != descriptor_map_.end()) {
     VLOG(1) << "GATT descriptor service provider already registered for "
             << "object path: " << provider->object_path().value();
@@ -120,8 +115,7 @@
 
 void FakeBluetoothGattManagerClient::UnregisterServiceServiceProvider(
     FakeBluetoothGattServiceServiceProvider* provider) {
-  ServiceMap::iterator iter =
-      service_map_.find(provider->object_path());
+  ServiceMap::iterator iter = service_map_.find(provider->object_path());
   if (iter != service_map_.end() && iter->second.second == provider)
     service_map_.erase(iter);
 }
@@ -147,7 +141,7 @@
 
 FakeBluetoothGattCharacteristicServiceProvider*
 FakeBluetoothGattManagerClient::GetCharacteristicServiceProvider(
-        const dbus::ObjectPath& object_path) const {
+    const dbus::ObjectPath& object_path) const {
   CharacteristicMap::const_iterator iter =
       characteristic_map_.find(object_path);
   if (iter == characteristic_map_.end())
@@ -172,4 +166,4 @@
   return iter->second.first;
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
similarity index 81%
rename from chromeos/dbus/fake_bluetooth_gatt_manager_client.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
index 9dccaac0..32209df 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
@@ -10,11 +10,11 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothGattCharacteristicServiceProvider;
 class FakeBluetoothGattDescriptorServiceProvider;
@@ -23,7 +23,7 @@
 // FakeBluetoothGattManagerClient simulates the behavior of the Bluetooth
 // daemon's GATT manager object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattManagerClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattManagerClient
     : public BluetoothGattManagerClient {
  public:
   FakeBluetoothGattManagerClient();
@@ -60,13 +60,12 @@
 
   // Return a pointer to the service provider that corresponds to the object
   // path |object_path| if it exists.
-  FakeBluetoothGattServiceServiceProvider*
-      GetServiceServiceProvider(const dbus::ObjectPath& object_path) const;
+  FakeBluetoothGattServiceServiceProvider* GetServiceServiceProvider(
+      const dbus::ObjectPath& object_path) const;
   FakeBluetoothGattCharacteristicServiceProvider*
-      GetCharacteristicServiceProvider(
-          const dbus::ObjectPath& object_path) const;
-  FakeBluetoothGattDescriptorServiceProvider*
-      GetDescriptorServiceProvider(const dbus::ObjectPath& object_path) const;
+  GetCharacteristicServiceProvider(const dbus::ObjectPath& object_path) const;
+  FakeBluetoothGattDescriptorServiceProvider* GetDescriptorServiceProvider(
+      const dbus::ObjectPath& object_path) const;
 
   // Returns true, if a GATT service with object path |object_path| was
   // registered with the GATT manager using RegisterService.
@@ -76,12 +75,11 @@
   // Mappings for GATT service, characteristic, and descriptor service
   // providers. The fake GATT manager stores references to all instances
   // created so that they can be obtained by tests.
-  typedef std::map<
-      dbus::ObjectPath, FakeBluetoothGattCharacteristicServiceProvider*>
+  typedef std::map<dbus::ObjectPath,
+                   FakeBluetoothGattCharacteristicServiceProvider*>
       CharacteristicMap;
-  typedef std::map<
-      dbus::ObjectPath, FakeBluetoothGattDescriptorServiceProvider*>
-      DescriptorMap;
+  typedef std::map<dbus::ObjectPath,
+                   FakeBluetoothGattDescriptorServiceProvider*> DescriptorMap;
 
   // The mapping for services is from object paths to pairs of boolean and
   // service provider pointer, where the boolean denotes whether or not the
@@ -97,6 +95,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
similarity index 83%
rename from chromeos/dbus/fake_bluetooth_gatt_service_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
index 1a56642..2e7aa0a 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
 
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 namespace {
 
@@ -30,13 +30,11 @@
 FakeBluetoothGattServiceClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothGattServiceClient::Properties(
-        NULL,
-        bluetooth_gatt_service::kBluetoothGattServiceInterface,
-        callback) {
-}
+          NULL,
+          bluetooth_gatt_service::kBluetoothGattServiceInterface,
+          callback) {}
 
-FakeBluetoothGattServiceClient::Properties::~Properties() {
-}
+FakeBluetoothGattServiceClient::Properties::~Properties() {}
 
 void FakeBluetoothGattServiceClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -57,14 +55,11 @@
 }
 
 FakeBluetoothGattServiceClient::FakeBluetoothGattServiceClient()
-    : weak_ptr_factory_(this) {
-}
+    : weak_ptr_factory_(this) {}
 
-FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() {
-}
+FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() {}
 
-void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothGattServiceClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -103,8 +98,7 @@
       device_path.value() + "/" + kHeartRateServicePathComponent;
   heart_rate_service_properties_.reset(new Properties(base::Bind(
       &FakeBluetoothGattServiceClient::OnPropertyChanged,
-      base::Unretained(this),
-      dbus::ObjectPath(heart_rate_service_path_))));
+      base::Unretained(this), dbus::ObjectPath(heart_rate_service_path_))));
   heart_rate_service_properties_->uuid.ReplaceValue(kHeartRateServiceUUID);
   heart_rate_service_properties_->device.ReplaceValue(device_path);
   heart_rate_service_properties_->primary.ReplaceValue(true);
@@ -128,7 +122,8 @@
   VLOG(2) << "Hiding fake Heart Rate Service.";
   FakeBluetoothGattCharacteristicClient* char_client =
       static_cast<FakeBluetoothGattCharacteristicClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient());
+          bluez::BluezDBusManager::Get()
+              ->GetBluetoothGattCharacteristicClient());
   char_client->HideHeartRateCharacteristics();
 
   // Notify observers before deleting the properties structure so that it
@@ -143,8 +138,8 @@
   return !!heart_rate_service_properties_.get();
 }
 
-dbus::ObjectPath
-FakeBluetoothGattServiceClient::GetHeartRateServicePath() const {
+dbus::ObjectPath FakeBluetoothGattServiceClient::GetHeartRateServicePath()
+    const {
   return dbus::ObjectPath(heart_rate_service_path_);
 }
 
@@ -160,17 +155,15 @@
 void FakeBluetoothGattServiceClient::NotifyServiceAdded(
     const dbus::ObjectPath& object_path) {
   VLOG(2) << "GATT service added: " << object_path.value();
-  FOR_EACH_OBSERVER(
-      BluetoothGattServiceClient::Observer, observers_,
-      GattServiceAdded(object_path));
+  FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_,
+                    GattServiceAdded(object_path));
 }
 
 void FakeBluetoothGattServiceClient::NotifyServiceRemoved(
     const dbus::ObjectPath& object_path) {
   VLOG(2) << "GATT service removed: " << object_path.value();
-  FOR_EACH_OBSERVER(
-      BluetoothGattServiceClient::Observer, observers_,
-      GattServiceRemoved(object_path));
+  FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_,
+                    GattServiceRemoved(object_path));
 }
 
 void FakeBluetoothGattServiceClient::ExposeHeartRateCharacteristics() {
@@ -180,7 +173,8 @@
   }
   FakeBluetoothGattCharacteristicClient* char_client =
       static_cast<FakeBluetoothGattCharacteristicClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient());
+          bluez::BluezDBusManager::Get()
+              ->GetBluetoothGattCharacteristicClient());
   char_client->ExposeHeartRateCharacteristics(
       dbus::ObjectPath(heart_rate_service_path_));
 
@@ -192,4 +186,4 @@
   heart_rate_service_properties_->characteristics.ReplaceValue(char_paths);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
similarity index 94%
rename from chromeos/dbus/fake_bluetooth_gatt_service_client.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
index f719727..d25e9d2 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_service_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
@@ -11,17 +11,17 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_service_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattServiceClient simulates the behavior of the Bluetooth Daemon
 // GATT service objects and is used in test cases in place of a mock and on the
 // Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattServiceClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattServiceClient
     : public BluetoothGattServiceClient {
  public:
   struct Properties : public BluetoothGattServiceClient::Properties {
@@ -101,6 +101,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc
similarity index 69%
rename from chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc
index d06abd3..8d724058 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.cc
@@ -2,27 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h"
 
 #include "base/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothGattServiceServiceProvider::
     FakeBluetoothGattServiceServiceProvider(
         const dbus::ObjectPath& object_path,
         const std::string& uuid,
         const std::vector<dbus::ObjectPath>& includes)
-        : object_path_(object_path),
-          uuid_(uuid),
-          includes_(includes) {
+    : object_path_(object_path), uuid_(uuid), includes_(includes) {
   VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value();
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   fake_bluetooth_gatt_manager_client->RegisterServiceServiceProvider(this);
 }
 
@@ -32,8 +30,8 @@
 
   FakeBluetoothGattManagerClient* fake_bluetooth_gatt_manager_client =
       static_cast<FakeBluetoothGattManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothGattManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothGattManagerClient());
   fake_bluetooth_gatt_manager_client->UnregisterServiceServiceProvider(this);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h
similarity index 84%
rename from chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h
index a1a1253..69b71fd7c 100644
--- a/chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h
@@ -8,16 +8,16 @@
 #include <string>
 #include <vector>
 
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_gatt_service_service_provider.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothGattServiceServiceProvider simulates behavior of a local GATT
 // service object and is used both in test cases in place of a mock and on the
 // Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothGattServiceServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattServiceServiceProvider
     : public BluetoothGattServiceServiceProvider {
  public:
   FakeBluetoothGattServiceServiceProvider(
@@ -42,6 +42,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_SERVICE_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_input_client.cc b/device/bluetooth/dbus/fake_bluetooth_input_client.cc
similarity index 82%
rename from chromeos/dbus/fake_bluetooth_input_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_input_client.cc
index d32bbef..849c3be 100644
--- a/chromeos/dbus/fake_bluetooth_input_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_input_client.cc
@@ -2,31 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_input_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
 
 #include <map>
 
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "chromeos/dbus/fake_bluetooth_device_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_manager.h"
 #include "dbus/object_proxy.h"
+#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothInputClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothInputClient::Properties(
           NULL,
           bluetooth_input::kBluetoothInputInterface,
-          callback) {
-}
+          callback) {}
 
-FakeBluetoothInputClient::Properties::~Properties() {
-}
+FakeBluetoothInputClient::Properties::~Properties() {}
 
 void FakeBluetoothInputClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -40,23 +38,20 @@
 }
 
 void FakeBluetoothInputClient::Properties::Set(
-    dbus::PropertyBase *property,
+    dbus::PropertyBase* property,
     dbus::PropertySet::SetCallback callback) {
   VLOG(1) << "Set " << property->name();
   callback.Run(false);
 }
 
-
-FakeBluetoothInputClient::FakeBluetoothInputClient() {
-}
+FakeBluetoothInputClient::FakeBluetoothInputClient() {}
 
 FakeBluetoothInputClient::~FakeBluetoothInputClient() {
   // Clean up Properties structures
   STLDeleteValues(&properties_map_);
 }
 
-void FakeBluetoothInputClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothInputClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothInputClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
@@ -66,8 +61,8 @@
   observers_.RemoveObserver(observer);
 }
 
-FakeBluetoothInputClient::Properties*
-FakeBluetoothInputClient::GetProperties(const dbus::ObjectPath& object_path) {
+FakeBluetoothInputClient::Properties* FakeBluetoothInputClient::GetProperties(
+    const dbus::ObjectPath& object_path) {
   PropertiesMap::iterator iter = properties_map_.find(object_path);
   if (iter != properties_map_.end())
     return iter->second;
@@ -79,10 +74,9 @@
   if (properties_map_.find(object_path) != properties_map_.end())
     return;
 
-  Properties* properties = new Properties(base::Bind(
-      &FakeBluetoothInputClient::OnPropertyChanged,
-      base::Unretained(this),
-      object_path));
+  Properties* properties =
+      new Properties(base::Bind(&FakeBluetoothInputClient::OnPropertyChanged,
+                                base::Unretained(this), object_path));
 
   // The LegacyAutopair and DisplayPinCode devices represent a typical mouse
   // and keyboard respectively, so mark them as ReconnectMode "any". The
@@ -126,4 +120,4 @@
                     InputPropertyChanged(object_path, property_name));
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_input_client.h b/device/bluetooth/dbus/fake_bluetooth_input_client.h
similarity index 85%
rename from chromeos/dbus/fake_bluetooth_input_client.h
rename to device/bluetooth/dbus/fake_bluetooth_input_client.h
index 56633ffd..e7a3b0a 100644
--- a/chromeos/dbus/fake_bluetooth_input_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_input_client.h
@@ -7,21 +7,21 @@
 
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_input_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_input_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothInputClient simulates the behavior of the Bluetooth Daemon
 // input device objects and is used both in test cases in place of a mock and on
 // the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothInputClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothInputClient
     : public BluetoothInputClient {
  public:
   struct Properties : public BluetoothInputClient::Properties {
-    explicit Properties(const PropertyChangedCallback & callback);
+    explicit Properties(const PropertyChangedCallback& callback);
     ~Properties() override;
 
     // dbus::PropertySet override
@@ -51,7 +51,7 @@
                          const std::string& property_name);
 
   // Static properties we return.
-  typedef std::map<const dbus::ObjectPath, Properties *> PropertiesMap;
+  typedef std::map<const dbus::ObjectPath, Properties*> PropertiesMap;
   PropertiesMap properties_map_;
 
   // List of observers interested in event notifications from us.
@@ -60,6 +60,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothInputClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_INPUT_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
similarity index 79%
rename from chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
index ce46e3d..043df05c 100644
--- a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.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 "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothLEAdvertisementServiceProvider::
     FakeBluetoothLEAdvertisementServiceProvider(
@@ -19,7 +19,7 @@
   FakeBluetoothLEAdvertisingManagerClient*
       fake_bluetooth_profile_manager_client =
           static_cast<FakeBluetoothLEAdvertisingManagerClient*>(
-              DBusThreadManager::Get()
+              bluez::BluezDBusManager::Get()
                   ->GetBluetoothLEAdvertisingManagerClient());
   fake_bluetooth_profile_manager_client->RegisterAdvertisementServiceProvider(
       this);
@@ -32,7 +32,7 @@
   FakeBluetoothLEAdvertisingManagerClient*
       fake_bluetooth_profile_manager_client =
           static_cast<FakeBluetoothLEAdvertisingManagerClient*>(
-              DBusThreadManager::Get()
+              bluez::BluezDBusManager::Get()
                   ->GetBluetoothLEAdvertisingManagerClient());
   fake_bluetooth_profile_manager_client->UnregisterAdvertisementServiceProvider(
       this);
@@ -43,4 +43,4 @@
   delegate_->Released();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h
similarity index 86%
rename from chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h
index 5a19aeee..66df2c2 100644
--- a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h
@@ -8,17 +8,17 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertisement_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothAdvertisementServiceProvider simulates the behavior of a local
 // Bluetooth agent object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothLEAdvertisementServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothLEAdvertisementServiceProvider
     : public BluetoothLEAdvertisementServiceProvider {
  public:
   FakeBluetoothLEAdvertisementServiceProvider(
@@ -44,6 +44,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisementServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
similarity index 94%
rename from chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
index 88dafcb..5b586d7 100644
--- a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
@@ -13,28 +13,23 @@
 #include "fake_bluetooth_le_advertising_manager_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char FakeBluetoothLEAdvertisingManagerClient::kAdvertisingManagerPath[] =
     "/fake/hci0";
 
 FakeBluetoothLEAdvertisingManagerClient::
-    FakeBluetoothLEAdvertisingManagerClient() {
-}
+    FakeBluetoothLEAdvertisingManagerClient() {}
 
 FakeBluetoothLEAdvertisingManagerClient::
-    ~FakeBluetoothLEAdvertisingManagerClient() {
-}
+    ~FakeBluetoothLEAdvertisingManagerClient() {}
 
-void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {}
 
-void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {
-}
+void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {}
 
 void FakeBluetoothLEAdvertisingManagerClient::RemoveObserver(
-    Observer* observer) {
-}
+    Observer* observer) {}
 
 void FakeBluetoothLEAdvertisingManagerClient::RegisterAdvertisement(
     const dbus::ObjectPath& manager_object_path,
@@ -103,4 +98,4 @@
     service_provider_map_.erase(iter);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
similarity index 92%
rename from chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h
rename to device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
index 5df129c..e3090e6 100644
--- a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
@@ -11,12 +11,12 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothLEAdvertisementServiceProvider;
 
@@ -24,7 +24,7 @@
 // Bluetooth
 // Daemon's profile manager object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothLEAdvertisingManagerClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothLEAdvertisingManagerClient
     : public BluetoothLEAdvertisingManagerClient {
  public:
   FakeBluetoothLEAdvertisingManagerClient();
@@ -74,6 +74,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisingManagerClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
similarity index 85%
rename from chromeos/dbus/fake_bluetooth_media_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_media_client.cc
index 4c8f7fdf..246a140 100644
--- a/chromeos/dbus/fake_bluetooth_media_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_media_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
 
 #include <string>
 
 #include "base/stl_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
-#include "chromeos/dbus/fake_bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
 
 using dbus::ObjectPath;
 
@@ -23,21 +23,18 @@
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 // static
 const uint8_t FakeBluetoothMediaClient::kDefaultCodec = 0x00;
 
 FakeBluetoothMediaClient::FakeBluetoothMediaClient()
     : visible_(true),
-      object_path_(ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) {
-}
+      object_path_(ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) {}
 
-FakeBluetoothMediaClient::~FakeBluetoothMediaClient() {
-}
+FakeBluetoothMediaClient::~FakeBluetoothMediaClient() {}
 
-void FakeBluetoothMediaClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothMediaClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothMediaClient::AddObserver(
     BluetoothMediaClient::Observer* observer) {
@@ -122,7 +119,7 @@
   // transport.
   FakeBluetoothMediaTransportClient* transport =
       static_cast<FakeBluetoothMediaTransportClient*>(
-          DBusThreadManager::Get()->GetBluetoothMediaTransportClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient());
   transport->SetValid(endpoint, false);
 
   endpoints_.erase(endpoint->object_path());
@@ -134,4 +131,4 @@
   return ContainsKey(endpoints_, endpoint_path);
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_media_client.h b/device/bluetooth/dbus/fake_bluetooth_media_client.h
similarity index 90%
rename from chromeos/dbus/fake_bluetooth_media_client.h
rename to device/bluetooth/dbus/fake_bluetooth_media_client.h
index 3b4f4a7..3d6d84e 100644
--- a/chromeos/dbus/fake_bluetooth_media_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_media_client.h
@@ -9,15 +9,16 @@
 
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothMediaEndpointServiceProvider;
 
-class CHROMEOS_EXPORT FakeBluetoothMediaClient : public BluetoothMediaClient {
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaClient
+    : public BluetoothMediaClient {
  public:
   // The default codec is SBC(0x00).
   static const uint8_t kDefaultCodec;
@@ -71,6 +72,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
similarity index 83%
rename from chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
index a275374..83a0822e 100644
--- a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
 
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_media_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
 
 using dbus::ObjectPath;
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothMediaEndpointServiceProvider::
     FakeBluetoothMediaEndpointServiceProvider(const ObjectPath& object_path,
@@ -43,7 +43,7 @@
   // Makes the transport object valid for the given endpoint path.
   FakeBluetoothMediaTransportClient* transport =
       static_cast<FakeBluetoothMediaTransportClient*>(
-          DBusThreadManager::Get()->GetBluetoothMediaTransportClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient());
   DCHECK(transport);
   transport->SetValid(this, true);
 }
@@ -62,4 +62,4 @@
   delegate_->Released();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
similarity index 88%
rename from chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
index 5efe14f..1f4383f 100644
--- a/chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
@@ -8,16 +8,16 @@
 #include <vector>
 
 #include "base/logging.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_media_endpoint_service_provider.h"
 #include "testing/gtest/include/gtest/gtest_prod.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothMediaEndpointServiceProvider simulates the behavior of a local
 // Bluetooth Media Endpoint object.
-class CHROMEOS_EXPORT FakeBluetoothMediaEndpointServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaEndpointServiceProvider
     : public BluetoothMediaEndpointServiceProvider {
  public:
   FakeBluetoothMediaEndpointServiceProvider(const dbus::ObjectPath& object_path,
@@ -52,6 +52,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaEndpointServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_media_transport_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
similarity index 85%
rename from chromeos/dbus/fake_bluetooth_media_transport_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
index 441a66b..b71aa105 100644
--- a/chromeos/dbus/fake_bluetooth_media_transport_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.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 "chromeos/dbus/fake_bluetooth_media_transport_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
 
 #include <unistd.h>
 #include <sys/socket.h>
@@ -11,12 +11,12 @@
 
 #include "base/bind.h"
 #include "base/stl_util.h"
-#include "chromeos/dbus/bluetooth_media_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_adapter_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_client.h"
-#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
 #include "dbus/file_descriptor.h"
+#include "device/bluetooth/dbus/bluetooth_media_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
 
 using dbus::ObjectPath;
 
@@ -35,23 +35,23 @@
   static unsigned int sequence_number = 0;
   ++sequence_number;
   std::stringstream path;
-  path << chromeos::FakeBluetoothAdapterClient::kAdapterPath
-       << chromeos::FakeBluetoothMediaTransportClient::kTransportDevicePath
+  path << bluez::FakeBluetoothAdapterClient::kAdapterPath
+       << bluez::FakeBluetoothMediaTransportClient::kTransportDevicePath
        << "/fd" << sequence_number;
   return ObjectPath(path.str());
 }
 
 }  // namespace
 
-namespace chromeos {
+namespace bluez {
 
 // static
 const char FakeBluetoothMediaTransportClient::kTransportDevicePath[] =
     "/fake_audio_source";
 const uint8_t FakeBluetoothMediaTransportClient::kTransportCodec = 0x00;
 const std::vector<uint8_t>
-    FakeBluetoothMediaTransportClient::kTransportConfiguration = {
-        0x21, 0x15, 0x33, 0x2C};
+    FakeBluetoothMediaTransportClient::kTransportConfiguration = {0x21, 0x15,
+                                                                  0x33, 0x2C};
 const uint16_t FakeBluetoothMediaTransportClient::kTransportDelay = 5;
 const uint16_t FakeBluetoothMediaTransportClient::kTransportVolume = 50;
 const uint16_t FakeBluetoothMediaTransportClient::kDefaultReadMtu = 20;
@@ -60,13 +60,11 @@
 FakeBluetoothMediaTransportClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothMediaTransportClient::Properties(
-        nullptr,
-        kBluetoothMediaTransportInterface,
-        callback) {
-}
+          nullptr,
+          kBluetoothMediaTransportInterface,
+          callback) {}
 
-FakeBluetoothMediaTransportClient::Properties::~Properties() {
-}
+FakeBluetoothMediaTransportClient::Properties::~Properties() {}
 
 void FakeBluetoothMediaTransportClient::Properties::Get(
     dbus::PropertyBase* property,
@@ -93,19 +91,16 @@
   properties.reset(transport_properties);
 }
 
-FakeBluetoothMediaTransportClient::Transport::~Transport() {
-}
+FakeBluetoothMediaTransportClient::Transport::~Transport() {}
 
-FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() {
-}
+FakeBluetoothMediaTransportClient::FakeBluetoothMediaTransportClient() {}
 
 FakeBluetoothMediaTransportClient::~FakeBluetoothMediaTransportClient() {
   STLDeleteValues(&endpoint_to_transport_map_);
 }
 
 // DBusClient override.
-void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothMediaTransportClient::AddObserver(
     BluetoothMediaTransportClient::Observer* observer) {
@@ -154,7 +149,7 @@
     FakeBluetoothMediaEndpointServiceProvider* endpoint,
     bool valid) {
   FakeBluetoothMediaClient* media = static_cast<FakeBluetoothMediaClient*>(
-      DBusThreadManager::Get()->GetBluetoothMediaClient());
+      bluez::BluezDBusManager::Get()->GetBluetoothMediaClient());
   DCHECK(media);
 
   ObjectPath endpoint_path(endpoint->object_path());
@@ -210,10 +205,10 @@
     return;
 
   transport->properties->state.ReplaceValue(state);
-  FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_,
-                    MediaTransportPropertyChanged(
-                        transport->path,
-                        BluetoothMediaTransportClient::kStateProperty));
+  FOR_EACH_OBSERVER(
+      BluetoothMediaTransportClient::Observer, observers_,
+      MediaTransportPropertyChanged(
+          transport->path, BluetoothMediaTransportClient::kStateProperty));
 }
 
 void FakeBluetoothMediaTransportClient::SetVolume(
@@ -224,21 +219,23 @@
     return;
 
   transport->properties->volume.ReplaceValue(volume);
-  FOR_EACH_OBSERVER(BluetoothMediaTransportClient::Observer, observers_,
-                    MediaTransportPropertyChanged(
-                        transport->path,
-                        BluetoothMediaTransportClient::kVolumeProperty));
+  FOR_EACH_OBSERVER(
+      BluetoothMediaTransportClient::Observer, observers_,
+      MediaTransportPropertyChanged(
+          transport->path, BluetoothMediaTransportClient::kVolumeProperty));
 }
 
 void FakeBluetoothMediaTransportClient::WriteData(
-    const ObjectPath& endpoint_path, const std::vector<char>& bytes) {
+    const ObjectPath& endpoint_path,
+    const std::vector<char>& bytes) {
   VLOG(1) << "WriteData - write " << bytes.size() << " bytes";
 
   Transport* transport = GetTransport(endpoint_path);
 
   if (!transport || transport->properties->state.value() != "active") {
     VLOG(1) << "WriteData - write operation rejected, since the state isn't "
-               "active for endpoint: " << endpoint_path.value();
+               "active for endpoint: "
+            << endpoint_path.value();
     return;
   }
 
@@ -323,4 +320,4 @@
   SetState(endpoint_path, "active");
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_media_transport_client.h b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
similarity index 94%
rename from chromeos/dbus/fake_bluetooth_media_transport_client.h
rename to device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
index f1b2e53..8403c36 100644
--- a/chromeos/dbus/fake_bluetooth_media_transport_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
@@ -12,15 +12,15 @@
 #include "base/files/file.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_media_transport_client.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_media_transport_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothMediaEndpointServiceProvider;
 
-class CHROMEOS_EXPORT FakeBluetoothMediaTransportClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothMediaTransportClient
     : public BluetoothMediaTransportClient {
  public:
   struct Properties : public BluetoothMediaTransportClient::Properties {
@@ -78,8 +78,7 @@
   // Set state/volume property to a certain value.
   void SetState(const dbus::ObjectPath& endpoint_path,
                 const std::string& state);
-  void SetVolume(const dbus::ObjectPath& endpoint_path,
-                 const uint16_t& volume);
+  void SetVolume(const dbus::ObjectPath& endpoint_path, const uint16_t& volume);
 
   // Writes bytes to the input file descriptor, |input_fd|, associated with a
   // transport object which is bound to |endpoint_path|.
@@ -143,6 +142,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaTransportClient);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_TRANSPORT_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
similarity index 92%
rename from chromeos/dbus/fake_bluetooth_profile_manager_client.cc
rename to device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
index bba54a87..96254a5 100644
--- a/chromeos/dbus/fake_bluetooth_profile_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
 
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
-#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-namespace chromeos {
+namespace bluez {
 
 const char FakeBluetoothProfileManagerClient::kL2capUuid[] =
     "4d995052-33cc-4fdf-b446-75f32942a076";
@@ -23,14 +23,11 @@
 const char FakeBluetoothProfileManagerClient::kUnregisterableUuid[] =
     "00000000-0000-0000-0000-000000000000";
 
-FakeBluetoothProfileManagerClient::FakeBluetoothProfileManagerClient() {
-}
+FakeBluetoothProfileManagerClient::FakeBluetoothProfileManagerClient() {}
 
-FakeBluetoothProfileManagerClient::~FakeBluetoothProfileManagerClient() {
-}
+FakeBluetoothProfileManagerClient::~FakeBluetoothProfileManagerClient() {}
 
-void FakeBluetoothProfileManagerClient::Init(dbus::Bus* bus) {
-}
+void FakeBluetoothProfileManagerClient::Init(dbus::Bus* bus) {}
 
 void FakeBluetoothProfileManagerClient::RegisterProfile(
     const dbus::ObjectPath& profile_path,
@@ -111,4 +108,4 @@
   return service_provider_map_[iter->second];
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_profile_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
similarity index 92%
rename from chromeos/dbus/fake_bluetooth_profile_manager_client.h
rename to device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
index c142606..62af0f1 100644
--- a/chromeos/dbus/fake_bluetooth_profile_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
@@ -11,19 +11,19 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/observer_list.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_profile_manager_client.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 class FakeBluetoothProfileServiceProvider;
 
 // FakeBluetoothProfileManagerClient simulates the behavior of the Bluetooth
 // Daemon's profile manager object and is used both in test cases in place of a
 // mock and on the Linux desktop.
-class CHROMEOS_EXPORT FakeBluetoothProfileManagerClient
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothProfileManagerClient
     : public BluetoothProfileManagerClient {
  public:
   FakeBluetoothProfileManagerClient();
@@ -69,6 +69,6 @@
   ProfileMap profile_map_;
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
similarity index 80%
rename from chromeos/dbus/fake_bluetooth_profile_service_provider.cc
rename to device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
index a1f44eb..1089501 100644
--- a/chromeos/dbus/fake_bluetooth_profile_service_provider.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
@@ -2,23 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
 
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
 
-namespace chromeos {
+namespace bluez {
 
 FakeBluetoothProfileServiceProvider::FakeBluetoothProfileServiceProvider(
     const dbus::ObjectPath& object_path,
     Delegate* delegate)
-    : object_path_(object_path),
-      delegate_(delegate) {
+    : object_path_(object_path), delegate_(delegate) {
   VLOG(1) << "Creating Bluetooth Profile: " << object_path_.value();
 
   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
       static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient());
   fake_bluetooth_profile_manager_client->RegisterProfileServiceProvider(this);
 }
 
@@ -27,7 +26,7 @@
 
   FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
       static_cast<FakeBluetoothProfileManagerClient*>(
-          DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
+          bluez::BluezDBusManager::Get()->GetBluetoothProfileManagerClient());
   fake_bluetooth_profile_manager_client->UnregisterProfileServiceProvider(this);
 }
 
@@ -59,4 +58,4 @@
   delegate_->Cancel();
 }
 
-}  // namespace chromeos
+}  // namespace bluez
diff --git a/chromeos/dbus/fake_bluetooth_profile_service_provider.h b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h
similarity index 89%
rename from chromeos/dbus/fake_bluetooth_profile_service_provider.h
rename to device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h
index 2c98048..125992736 100644
--- a/chromeos/dbus/fake_bluetooth_profile_service_provider.h
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h
@@ -8,19 +8,19 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
-#include "chromeos/chromeos_export.h"
-#include "chromeos/dbus/bluetooth_profile_service_provider.h"
 #include "dbus/file_descriptor.h"
 #include "dbus/object_path.h"
+#include "device/bluetooth/bluetooth_export.h"
+#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
-namespace chromeos {
+namespace bluez {
 
 // FakeBluetoothProfileServiceProvider simulates the behavior of a local
 // Bluetooth agent object and is used both in test cases in place of a
 // mock and on the Linux desktop.
 //
 // This class is only called from the dbus origin thread and is not thread-safe.
-class CHROMEOS_EXPORT FakeBluetoothProfileServiceProvider
+class DEVICE_BLUETOOTH_EXPORT FakeBluetoothProfileServiceProvider
     : public BluetoothProfileServiceProvider {
  public:
   FakeBluetoothProfileServiceProvider(const dbus::ObjectPath& object_path,
@@ -55,6 +55,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeBluetoothProfileServiceProvider);
 };
 
-}  // namespace chromeos
+}  // namespace bluez
 
 #endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_PROFILE_SERVICE_PROVIDER_H_
diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h
index d2318e7..fed356d6 100644
--- a/device/bluetooth/test/mock_bluetooth_device.h
+++ b/device/bluetooth/test/mock_bluetooth_device.h
@@ -56,6 +56,11 @@
                     const base::Closure& callback,
                     const BluetoothDevice::ConnectErrorCallback&
                         error_callback));
+  MOCK_METHOD3(
+      Pair,
+      void(BluetoothDevice::PairingDelegate* pairing_delegate,
+           const base::Closure& callback,
+           const BluetoothDevice::ConnectErrorCallback& error_callback));
   MOCK_METHOD1(SetPinCode, void(const std::string&));
   MOCK_METHOD1(SetPasskey, void(uint32));
   MOCK_METHOD0(ConfirmPairing, void());
diff --git a/device/device_tests.gyp b/device/device_tests.gyp
index 864a320..051703a 100644
--- a/device/device_tests.gyp
+++ b/device/device_tests.gyp
@@ -62,6 +62,8 @@
         'bluetooth/test/test_bluetooth_adapter_observer.h',
         'devices_app/usb/device_impl_unittest.cc',
         'devices_app/usb/device_manager_impl_unittest.cc',
+        'devices_app/usb/fake_permission_provider.cc',
+        'devices_app/usb/fake_permission_provider.h',
         'hid/hid_connection_unittest.cc',
         'hid/hid_device_filter_unittest.cc',
         'hid/hid_report_descriptor_unittest.cc',
diff --git a/device/devices_app/usb/device_impl.cc b/device/devices_app/usb/device_impl.cc
index 1516c76..7f64cc6 100644
--- a/device/devices_app/usb/device_impl.cc
+++ b/device/devices_app/usb/device_impl.cc
@@ -31,38 +31,26 @@
   return base::Bind(&CallMojoCallback<Args...>, callback);
 }
 
+void OnPermissionCheckComplete(
+    const base::Callback<void(bool)>& callback,
+    const base::Callback<void(const base::Callback<void(bool)>&)>& action,
+    bool allowed) {
+  if (allowed)
+    action.Run(callback);
+  else
+    callback.Run(false);
+}
+
 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) {
   scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(
       std::max(static_cast<size_t>(1u), static_cast<size_t>(size)));
   return buffer;
 }
 
-}  // namespace
-
-DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device,
-                       mojo::InterfaceRequest<Device> request)
-    : binding_(this, request.Pass()), device_(device), weak_factory_(this) {}
-
-DeviceImpl::~DeviceImpl() {
-  CloseHandle();
-}
-
-void DeviceImpl::CloseHandle() {
-  if (device_handle_)
-    device_handle_->Close();
-  device_handle_ = nullptr;
-}
-
-void DeviceImpl::OnOpen(const OpenCallback& callback,
-                        scoped_refptr<UsbDeviceHandle> handle) {
-  device_handle_ = handle;
-  callback.Run(handle ? OPEN_DEVICE_ERROR_OK : OPEN_DEVICE_ERROR_ACCESS_DENIED);
-}
-
-void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback,
-                              UsbTransferStatus status,
-                              scoped_refptr<net::IOBuffer> buffer,
-                              size_t buffer_size) {
+void OnTransferIn(const DeviceImpl::MojoTransferInCallback& callback,
+                  UsbTransferStatus status,
+                  scoped_refptr<net::IOBuffer> buffer,
+                  size_t buffer_size) {
   mojo::Array<uint8_t> data;
   if (buffer) {
     // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
@@ -75,15 +63,58 @@
   callback.Run(mojo::ConvertTo<TransferStatus>(status), data.Pass());
 }
 
-void DeviceImpl::OnTransferOut(const MojoTransferOutCallback& callback,
-                               UsbTransferStatus status,
-                               scoped_refptr<net::IOBuffer> buffer,
-                               size_t buffer_size) {
+void OnControlTransferInPermissionCheckComplete(
+    scoped_refptr<UsbDeviceHandle> device_handle,
+    ControlTransferParamsPtr params,
+    int length,
+    int timeout,
+    const Device::ControlTransferInCallback& callback,
+    bool allowed) {
+  if (allowed) {
+    scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
+    device_handle->ControlTransfer(
+        USB_DIRECTION_INBOUND,
+        mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
+        mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
+        params->request, params->value, params->index, buffer, length, timeout,
+        base::Bind(&OnTransferIn, callback));
+  } else {
+    mojo::Array<uint8_t> data;
+    callback.Run(TRANSFER_STATUS_PERMISSION_DENIED, data.Pass());
+  }
+}
+
+void OnTransferOut(const DeviceImpl::MojoTransferOutCallback& callback,
+                   UsbTransferStatus status,
+                   scoped_refptr<net::IOBuffer> buffer,
+                   size_t buffer_size) {
   callback.Run(mojo::ConvertTo<TransferStatus>(status));
 }
 
-void DeviceImpl::OnIsochronousTransferIn(
-    const IsochronousTransferInCallback& callback,
+void OnControlTransferOutPermissionCheckComplete(
+    scoped_refptr<UsbDeviceHandle> device_handle,
+    ControlTransferParamsPtr params,
+    mojo::Array<uint8_t> data,
+    int timeout,
+    const Device::ControlTransferOutCallback& callback,
+    bool allowed) {
+  if (allowed) {
+    scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
+    const std::vector<uint8_t>& storage = data.storage();
+    std::copy(storage.begin(), storage.end(), buffer->data());
+    device_handle->ControlTransfer(
+        USB_DIRECTION_OUTBOUND,
+        mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
+        mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
+        params->request, params->value, params->index, buffer, data.size(),
+        timeout, base::Bind(&OnTransferOut, callback));
+  } else {
+    callback.Run(TRANSFER_STATUS_PERMISSION_DENIED);
+  }
+}
+
+void OnIsochronousTransferIn(
+    const Device::IsochronousTransferInCallback& callback,
     uint32_t packet_size,
     UsbTransferStatus status,
     scoped_refptr<net::IOBuffer> buffer,
@@ -102,14 +133,81 @@
   callback.Run(mojo::ConvertTo<TransferStatus>(status), packets.Pass());
 }
 
-void DeviceImpl::OnIsochronousTransferOut(
-    const MojoTransferOutCallback& callback,
+void OnIsochronousTransferOut(
+    const Device::IsochronousTransferOutCallback& callback,
     UsbTransferStatus status,
     scoped_refptr<net::IOBuffer> buffer,
     size_t buffer_size) {
   callback.Run(mojo::ConvertTo<TransferStatus>(status));
 }
 
+}  // namespace
+
+DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device,
+                       PermissionProviderPtr permission_provider,
+                       mojo::InterfaceRequest<Device> request)
+    : binding_(this, request.Pass()),
+      device_(device),
+      permission_provider_(permission_provider.Pass()),
+      weak_factory_(this) {
+  // This object owns itself and will be destroyed if either the message pipe
+  // it is bound to is closed or the PermissionProvider it depends on is
+  // unavailable.
+  binding_.set_connection_error_handler([this]() { delete this; });
+  permission_provider_.set_connection_error_handler([this]() { delete this; });
+}
+
+DeviceImpl::~DeviceImpl() {
+  CloseHandle();
+}
+
+void DeviceImpl::CloseHandle() {
+  if (device_handle_)
+    device_handle_->Close();
+  device_handle_ = nullptr;
+}
+
+void DeviceImpl::HasControlTransferPermission(
+    ControlTransferRecipient recipient,
+    uint16_t index,
+    const base::Callback<void(bool)>& callback) {
+  DCHECK(device_handle_);
+  const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
+
+  if (recipient == CONTROL_TRANSFER_RECIPIENT_INTERFACE ||
+      recipient == CONTROL_TRANSFER_RECIPIENT_ENDPOINT) {
+    if (!config) {
+      callback.Run(false);
+      return;
+    }
+
+    uint8_t interface_number = index & 0xff;
+    if (recipient == CONTROL_TRANSFER_RECIPIENT_ENDPOINT) {
+      if (!device_handle_->FindInterfaceByEndpoint(index & 0xff,
+                                                   &interface_number)) {
+        callback.Run(false);
+        return;
+      }
+    }
+
+    permission_provider_->HasInterfacePermission(
+        interface_number, config->configuration_value,
+        DeviceInfo::From(*device_), callback);
+  } else if (config) {
+    permission_provider_->HasConfigurationPermission(
+        config->configuration_value, DeviceInfo::From(*device_), callback);
+  } else {
+    // Client must already have device permission to have gotten this far.
+    callback.Run(true);
+  }
+}
+
+void DeviceImpl::OnOpen(const OpenCallback& callback,
+                        scoped_refptr<UsbDeviceHandle> handle) {
+  device_handle_ = handle;
+  callback.Run(handle ? OPEN_DEVICE_ERROR_OK : OPEN_DEVICE_ERROR_ACCESS_DENIED);
+}
+
 void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) {
   callback.Run(DeviceInfo::From(*device_));
 }
@@ -136,7 +234,12 @@
     return;
   }
 
-  device_handle_->SetConfiguration(value, WrapMojoCallback(callback));
+  auto set_configuration =
+      base::Bind(&UsbDeviceHandle::SetConfiguration, device_handle_, value);
+  permission_provider_->HasConfigurationPermission(
+      value, DeviceInfo::From(*device_),
+      base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback),
+                 set_configuration));
 }
 
 void DeviceImpl::ClaimInterface(uint8_t interface_number,
@@ -146,7 +249,18 @@
     return;
   }
 
-  device_handle_->ClaimInterface(interface_number, WrapMojoCallback(callback));
+  const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
+  if (!config) {
+    callback.Run(false);
+    return;
+  }
+
+  auto claim_interface = base::Bind(&UsbDeviceHandle::ClaimInterface,
+                                    device_handle_, interface_number);
+  permission_provider_->HasInterfacePermission(
+      interface_number, config->configuration_value, DeviceInfo::From(*device_),
+      base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback),
+                 claim_interface));
 }
 
 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
@@ -200,14 +314,12 @@
     return;
   }
 
-  scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
-  device_handle_->ControlTransfer(
-      USB_DIRECTION_INBOUND,
-      mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
-      mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
-      params->request, params->value, params->index, buffer, length, timeout,
-      base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
-                 callback));
+  ControlTransferRecipient recipient = params->recipient;
+  uint16_t index = params->index;
+  HasControlTransferPermission(
+      recipient, index,
+      base::Bind(&OnControlTransferInPermissionCheckComplete, device_handle_,
+                 base::Passed(&params), length, timeout, callback));
 }
 
 void DeviceImpl::ControlTransferOut(
@@ -220,16 +332,12 @@
     return;
   }
 
-  scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
-  const std::vector<uint8_t>& storage = data.storage();
-  std::copy(storage.begin(), storage.end(), buffer->data());
-  device_handle_->ControlTransfer(
-      USB_DIRECTION_OUTBOUND,
-      mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
-      mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
-      params->request, params->value, params->index, buffer, data.size(),
-      timeout, base::Bind(&DeviceImpl::OnTransferOut,
-                          weak_factory_.GetWeakPtr(), callback));
+  ControlTransferRecipient recipient = params->recipient;
+  uint16_t index = params->index;
+  HasControlTransferPermission(
+      recipient, index, base::Bind(&OnControlTransferOutPermissionCheckComplete,
+                                   device_handle_, base::Passed(&params),
+                                   base::Passed(&data), timeout, callback));
 }
 
 void DeviceImpl::GenericTransferIn(uint8_t endpoint_number,
@@ -243,10 +351,9 @@
 
   uint8_t endpoint_address = endpoint_number | 0x80;
   scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
-  device_handle_->GenericTransfer(
-      USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout,
-      base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
-                 callback));
+  device_handle_->GenericTransfer(USB_DIRECTION_INBOUND, endpoint_address,
+                                  buffer, length, timeout,
+                                  base::Bind(&OnTransferIn, callback));
 }
 
 void DeviceImpl::GenericTransferOut(
@@ -263,10 +370,9 @@
   scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
   const std::vector<uint8_t>& storage = data.storage();
   std::copy(storage.begin(), storage.end(), buffer->data());
-  device_handle_->GenericTransfer(
-      USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout,
-      base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
-                 callback));
+  device_handle_->GenericTransfer(USB_DIRECTION_OUTBOUND, endpoint_address,
+                                  buffer, data.size(), timeout,
+                                  base::Bind(&OnTransferOut, callback));
 }
 
 void DeviceImpl::IsochronousTransferIn(
@@ -286,8 +392,7 @@
   device_handle_->IsochronousTransfer(
       USB_DIRECTION_INBOUND, endpoint_address, buffer, transfer_size,
       num_packets, packet_length, timeout,
-      base::Bind(&DeviceImpl::OnIsochronousTransferIn,
-                 weak_factory_.GetWeakPtr(), callback, packet_length));
+      base::Bind(&OnIsochronousTransferIn, callback, packet_length));
 }
 
 void DeviceImpl::IsochronousTransferOut(
@@ -318,8 +423,7 @@
   device_handle_->IsochronousTransfer(
       USB_DIRECTION_OUTBOUND, endpoint_address, buffer, transfer_size,
       static_cast<uint32_t>(packets.size()), packet_size, timeout,
-      base::Bind(&DeviceImpl::OnIsochronousTransferOut,
-                 weak_factory_.GetWeakPtr(), callback));
+      base::Bind(&OnIsochronousTransferOut, callback));
 }
 
 }  // namespace usb
diff --git a/device/devices_app/usb/device_impl.h b/device/devices_app/usb/device_impl.h
index 9a7bac4..12d6b90 100644
--- a/device/devices_app/usb/device_impl.h
+++ b/device/devices_app/usb/device_impl.h
@@ -10,10 +10,11 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "device/devices_app/usb/public/interfaces/device.mojom.h"
+#include "device/devices_app/usb/public/interfaces/permission_provider.mojom.h"
 #include "device/usb/usb_device_handle.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h"
 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
-#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
 
 namespace net {
 class IOBuffer;
@@ -27,51 +28,30 @@
 // lifetime.
 class DeviceImpl : public Device {
  public:
-  DeviceImpl(scoped_refptr<UsbDevice> device,
-             mojo::InterfaceRequest<Device> request);
-  ~DeviceImpl() override;
-
- private:
   using MojoTransferInCallback =
       mojo::Callback<void(TransferStatus, mojo::Array<uint8_t>)>;
 
   using MojoTransferOutCallback = mojo::Callback<void(TransferStatus)>;
 
+  DeviceImpl(scoped_refptr<UsbDevice> device,
+             PermissionProviderPtr permission_provider,
+             mojo::InterfaceRequest<Device> request);
+  ~DeviceImpl() override;
+
+ private:
   // Closes the device if it's open. This will always set |device_handle_| to
   // null.
   void CloseHandle();
 
+  // Checks interface permissions for control transfers.
+  void HasControlTransferPermission(ControlTransferRecipient recipient,
+                                    uint16_t index,
+                                    const base::Callback<void(bool)>& callback);
+
   // Handles completion of an open request.
   void OnOpen(const OpenCallback& callback,
               scoped_refptr<device::UsbDeviceHandle> handle);
 
-  // Handles completion of an inbound transfer on the UsbDeviceHandle.
-  void OnTransferIn(const MojoTransferInCallback& callback,
-                    UsbTransferStatus status,
-                    scoped_refptr<net::IOBuffer> data,
-                    size_t size);
-
-  // Handles completion of an outbound transfer on the UsbDeviceHandle.
-  void OnTransferOut(const MojoTransferOutCallback& callback,
-                     UsbTransferStatus status,
-                     scoped_refptr<net::IOBuffer> data,
-                     size_t size);
-
-  // Handles completion of an inbound isochronous transfer on the
-  // UsbDeviceHandle.
-  void OnIsochronousTransferIn(const IsochronousTransferInCallback& callback,
-                               uint32_t packet_length,
-                               UsbTransferStatus status,
-                               scoped_refptr<net::IOBuffer> data,
-                               size_t size);
-
-  // Handles completion of an outbound isochronous transfer on the
-  // UsbDeviceHandle.
-  void OnIsochronousTransferOut(const MojoTransferOutCallback& callback,
-                                UsbTransferStatus status,
-                                scoped_refptr<net::IOBuffer> data,
-                                size_t size);
-
   // Device implementation:
   void GetDeviceInfo(const GetDeviceInfoCallback& callback) override;
   void GetConfiguration(const GetConfigurationCallback& callback) override;
@@ -117,12 +97,13 @@
       uint32_t timeout,
       const IsochronousTransferOutCallback& callback) override;
 
-  mojo::StrongBinding<Device> binding_;
+  mojo::Binding<Device> binding_;
 
   scoped_refptr<UsbDevice> device_;
   // The device handle. Will be null before the device is opened and after it
   // has been closed.
   scoped_refptr<UsbDeviceHandle> device_handle_;
+  PermissionProviderPtr permission_provider_;
 
   base::WeakPtrFactory<DeviceImpl> weak_factory_;
 
diff --git a/device/devices_app/usb/device_impl_unittest.cc b/device/devices_app/usb/device_impl_unittest.cc
index 5868a17..2b41912 100644
--- a/device/devices_app/usb/device_impl_unittest.cc
+++ b/device/devices_app/usb/device_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "device/devices_app/usb/device_impl.h"
+#include "device/devices_app/usb/fake_permission_provider.h"
 #include "device/usb/mock_usb_device.h"
 #include "device/usb/mock_usb_device_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -150,13 +151,19 @@
         new MockUsbDevice(vendor_id, product_id, manufacturer, product, serial);
     mock_handle_ = new MockUsbDeviceHandle(mock_device_.get());
 
+    PermissionProviderPtr permission_provider;
+    permission_provider_.Bind(mojo::GetProxy(&permission_provider));
     DevicePtr proxy;
-    new DeviceImpl(mock_device_, mojo::GetProxy(&proxy));
+    new DeviceImpl(mock_device_, permission_provider.Pass(),
+                   mojo::GetProxy(&proxy));
 
     // Set up mock handle calls to respond based on mock device configs
     // established by the test.
     ON_CALL(mock_device(), Open(_))
         .WillByDefault(Invoke(this, &USBDeviceImplTest::OpenMockHandle));
+    ON_CALL(mock_device(), GetActiveConfiguration())
+        .WillByDefault(
+            Invoke(this, &USBDeviceImplTest::GetActiveConfiguration));
     ON_CALL(mock_handle(), Close())
         .WillByDefault(Invoke(this, &USBDeviceImplTest::CloseMockHandle));
     ON_CALL(mock_handle(), SetConfiguration(_, _))
@@ -210,6 +217,16 @@
     is_device_open_ = false;
   }
 
+  const UsbConfigDescriptor* GetActiveConfiguration() {
+    if (current_config_ == 0) {
+      return nullptr;
+    } else {
+      const auto it = mock_configs_.find(current_config_);
+      EXPECT_TRUE(it != mock_configs_.end());
+      return &it->second;
+    }
+  }
+
   void SetConfiguration(uint8_t value,
                         const UsbDeviceHandle::ResultCallback& callback) {
     if (mock_configs_.find(value) != mock_configs_.end()) {
@@ -342,6 +359,8 @@
 
   std::set<uint8_t> claimed_interfaces_;
 
+  FakePermissionProvider permission_provider_;
+
   DISALLOW_COPY_AND_ASSIGN(USBDeviceImplTest);
 };
 
@@ -503,8 +522,18 @@
   }
 
   // Now add a mock interface #1.
-  AddMockConfig(ConfigBuilder(0).AddInterface(1, 0, 1, 2, 3));
+  AddMockConfig(ConfigBuilder(1).AddInterface(1, 0, 1, 2, 3));
 
+  EXPECT_CALL(mock_handle(), SetConfiguration(1, _));
+
+  {
+    base::RunLoop loop;
+    device->SetConfiguration(
+        1, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure()));
+    loop.Run();
+  }
+
+  EXPECT_CALL(mock_device(), GetActiveConfiguration());
   EXPECT_CALL(mock_handle(), ClaimInterface(2, _));
 
   {
@@ -515,6 +544,7 @@
     loop.Run();
   }
 
+  EXPECT_CALL(mock_device(), GetActiveConfiguration());
   EXPECT_CALL(mock_handle(), ClaimInterface(1, _));
 
   {
@@ -559,7 +589,7 @@
     loop.Run();
   }
 
-  AddMockConfig(ConfigBuilder(0)
+  AddMockConfig(ConfigBuilder(1)
                     .AddInterface(1, 0, 1, 2, 3)
                     .AddInterface(1, 42, 1, 2, 3)
                     .AddInterface(2, 0, 1, 2, 3));
@@ -597,6 +627,18 @@
     loop.Run();
   }
 
+  AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3));
+
+  EXPECT_CALL(mock_device(), GetActiveConfiguration());
+  EXPECT_CALL(mock_handle(), SetConfiguration(1, _));
+
+  {
+    base::RunLoop loop;
+    device->SetConfiguration(
+        1, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure()));
+    loop.Run();
+  }
+
   std::vector<uint8_t> fake_data;
   fake_data.push_back(41);
   fake_data.push_back(42);
@@ -623,9 +665,9 @@
     loop.Run();
   }
 
-  AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3));
   AddMockOutboundData(fake_data);
 
+  EXPECT_CALL(mock_device(), GetActiveConfiguration());
   EXPECT_CALL(mock_handle(),
               ControlTransfer(USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD,
                               UsbDeviceHandle::INTERFACE, 5, 6, 7, _, _, 0, _));
@@ -668,7 +710,7 @@
   std::vector<uint8_t> fake_inbound_data(message2.size());
   std::copy(message2.begin(), message2.end(), fake_inbound_data.begin());
 
-  AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3));
+  AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3));
   AddMockOutboundData(fake_outbound_data);
   AddMockInboundData(fake_inbound_data);
 
@@ -721,7 +763,7 @@
   std::copy(inbound_packet_data.begin(), inbound_packet_data.end(),
             fake_inbound_packets.begin());
 
-  AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3));
+  AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3));
   AddMockOutboundData(fake_outbound_packets);
   AddMockInboundData(fake_inbound_packets);
 
diff --git a/device/devices_app/usb/device_manager_impl.cc b/device/devices_app/usb/device_manager_impl.cc
index 333df78..0fc287da 100644
--- a/device/devices_app/usb/device_manager_impl.cc
+++ b/device/devices_app/usb/device_manager_impl.cc
@@ -204,7 +204,9 @@
     return;
 
   DCHECK(allowed_guids.size() == 1);
-  new DeviceImpl(device, device_request.Pass());
+  PermissionProviderPtr permission_provider;
+  permission_provider_->Bind(mojo::GetProxy(&permission_provider));
+  new DeviceImpl(device, permission_provider.Pass(), device_request.Pass());
 }
 
 void DeviceManagerImpl::OnGetDevices(EnumerationOptionsPtr options,
diff --git a/device/devices_app/usb/device_manager_impl_unittest.cc b/device/devices_app/usb/device_manager_impl_unittest.cc
index 2f25dc0..d4e43c88 100644
--- a/device/devices_app/usb/device_manager_impl_unittest.cc
+++ b/device/devices_app/usb/device_manager_impl_unittest.cc
@@ -14,11 +14,11 @@
 #include "device/core/device_client.h"
 #include "device/devices_app/usb/device_impl.h"
 #include "device/devices_app/usb/device_manager_impl.h"
+#include "device/devices_app/usb/fake_permission_provider.h"
 #include "device/usb/mock_usb_device.h"
 #include "device/usb/mock_usb_device_handle.h"
 #include "device/usb/mock_usb_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
 
 using ::testing::Invoke;
 using ::testing::_;
@@ -28,26 +28,6 @@
 
 namespace {
 
-class TestPermissionProvider : public PermissionProvider {
- public:
-  TestPermissionProvider(mojo::InterfaceRequest<PermissionProvider> request)
-      : binding_(this, request.Pass()) {}
-  ~TestPermissionProvider() override {}
-
-  void HasDevicePermission(
-      mojo::Array<DeviceInfoPtr> requested_devices,
-      const HasDevicePermissionCallback& callback) override {
-    // Permission to access all devices granted.
-    mojo::Array<mojo::String> allowed_guids(requested_devices.size());
-    for (size_t i = 0; i < requested_devices.size(); ++i)
-      allowed_guids[i] = requested_devices[i]->guid;
-    callback.Run(allowed_guids.Pass());
-  }
-
- private:
-  mojo::StrongBinding<PermissionProvider> binding_;
-};
-
 class TestDeviceClient : public DeviceClient {
  public:
   TestDeviceClient() {}
@@ -76,7 +56,7 @@
 
   DeviceManagerPtr ConnectToDeviceManager() {
     PermissionProviderPtr permission_provider;
-    new TestPermissionProvider(mojo::GetProxy(&permission_provider));
+    permission_provider_.Bind(mojo::GetProxy(&permission_provider));
     DeviceManagerPtr device_manager;
     new DeviceManagerImpl(mojo::GetProxy(&device_manager),
                           permission_provider.Pass(),
@@ -85,6 +65,7 @@
   }
 
  private:
+  FakePermissionProvider permission_provider_;
   scoped_ptr<TestDeviceClient> device_client_;
   scoped_ptr<base::MessageLoop> message_loop_;
 };
diff --git a/device/devices_app/usb/fake_permission_provider.cc b/device/devices_app/usb/fake_permission_provider.cc
new file mode 100644
index 0000000..b4760f2
--- /dev/null
+++ b/device/devices_app/usb/fake_permission_provider.cc
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/devices_app/usb/fake_permission_provider.h"
+
+namespace device {
+namespace usb {
+
+FakePermissionProvider::FakePermissionProvider() {}
+
+FakePermissionProvider::~FakePermissionProvider() {}
+
+void FakePermissionProvider::HasDevicePermission(
+    mojo::Array<DeviceInfoPtr> requested_devices,
+    const HasDevicePermissionCallback& callback) {
+  mojo::Array<mojo::String> allowed_guids(requested_devices.size());
+  for (size_t i = 0; i < requested_devices.size(); ++i)
+    allowed_guids[i] = requested_devices[i]->guid;
+  callback.Run(allowed_guids.Pass());
+}
+
+void FakePermissionProvider::HasConfigurationPermission(
+    uint8_t requested_configuration,
+    device::usb::DeviceInfoPtr device,
+    const HasInterfacePermissionCallback& callback) {
+  callback.Run(true);
+}
+void FakePermissionProvider::HasInterfacePermission(
+    uint8_t requested_interface,
+    uint8_t configuration_value,
+    device::usb::DeviceInfoPtr device,
+    const HasInterfacePermissionCallback& callback) {
+  callback.Run(true);
+}
+
+void FakePermissionProvider::Bind(
+    mojo::InterfaceRequest<PermissionProvider> request) {
+  bindings_.AddBinding(this, request.Pass());
+}
+
+}  // namespace usb
+}  // namespace device
diff --git a/device/devices_app/usb/fake_permission_provider.h b/device/devices_app/usb/fake_permission_provider.h
new file mode 100644
index 0000000..738ecbc
--- /dev/null
+++ b/device/devices_app/usb/fake_permission_provider.h
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_USB_FAKE_PERMISSION_PROVIDER_H_
+#define DEVICE_USB_FAKE_PERMISSION_PROVIDER_H_
+
+#include "device/devices_app/usb/public/interfaces/permission_provider.mojom.h"
+#include "mojo/common/weak_binding_set.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
+
+namespace device {
+namespace usb {
+
+class FakePermissionProvider : public PermissionProvider {
+ public:
+  FakePermissionProvider();
+  ~FakePermissionProvider() override;
+
+  void HasDevicePermission(
+      mojo::Array<DeviceInfoPtr> requested_devices,
+      const HasDevicePermissionCallback& callback) override;
+  void HasConfigurationPermission(
+      uint8_t requested_configuration,
+      device::usb::DeviceInfoPtr device,
+      const HasInterfacePermissionCallback& callback) override;
+  void HasInterfacePermission(
+      uint8_t requested_interface,
+      uint8_t configuration_value,
+      device::usb::DeviceInfoPtr device,
+      const HasInterfacePermissionCallback& callback) override;
+  void Bind(mojo::InterfaceRequest<PermissionProvider> request) override;
+
+ private:
+  mojo::WeakBindingSet<PermissionProvider> bindings_;
+};
+
+}  // namespace usb
+}  // namespace device
+
+#endif  // DEVICE_USB_FAKE_PERMISSION_PROVIDER_H_
diff --git a/device/devices_app/usb/public/interfaces/device.mojom b/device/devices_app/usb/public/interfaces/device.mojom
index 45797b7..5382ce37 100644
--- a/device/devices_app/usb/public/interfaces/device.mojom
+++ b/device/devices_app/usb/public/interfaces/device.mojom
@@ -115,6 +115,9 @@
   // The transfer failed due to a non-specific error.
   ERROR,
 
+  // The transfer was not allowed.
+  PERMISSION_DENIED,
+
   // The transfer timed out.
   TIMEOUT,
 
diff --git a/device/devices_app/usb/public/interfaces/permission_provider.mojom b/device/devices_app/usb/public/interfaces/permission_provider.mojom
index 1ed6d6e..f5d7111 100644
--- a/device/devices_app/usb/public/interfaces/permission_provider.mojom
+++ b/device/devices_app/usb/public/interfaces/permission_provider.mojom
@@ -11,4 +11,19 @@
   // that should be accessible to clients of the DeviceManager instance.
   HasDevicePermission(array<DeviceInfo> requested_devices)
       => (array<string> allowed_guids);
+
+  // Returns whether or not the client has permission to access
+  // |requested_configuration| on |device|.
+  HasConfigurationPermission(uint8 requested_configuration,
+                             DeviceInfo device) => (bool allowed);
+
+  // Returns whether or not the client has permission to access
+  // |requested_interface| on |device| when it is in configuration
+  // |configuration_value|.
+  HasInterfacePermission(uint8 requested_interface,
+                         uint8 configuration_value,
+                         DeviceInfo device) => (bool allowed);
+
+  // Requests a new binding to this service.
+  Bind(PermissionProvider& request);
 };
diff --git a/device/hid/hid_connection_win.cc b/device/hid/hid_connection_win.cc
index 2e5eab2..827416d 100644
--- a/device/hid/hid_connection_win.cc
+++ b/device/hid/hid_connection_win.cc
@@ -81,7 +81,7 @@
   } else if (GetLastError() == ERROR_IO_PENDING) {
     base::MessageLoop::current()->AddDestructionObserver(this);
     AddRef();
-    watcher_.StartWatching(event_.Get(), this);
+    watcher_.StartWatchingOnce(event_.Get(), this);
   } else {
     HID_PLOG(EVENT) << "HID transfer failed";
     callback_.Run(this, false);
diff --git a/device/hid/hid_service_mac.cc b/device/hid/hid_service_mac.cc
index babb91f..3dd8019 100644
--- a/device/hid/hid_service_mac.cc
+++ b/device/hid/hid_service_mac.cc
@@ -254,8 +254,7 @@
   std::vector<uint8> report_descriptor;
   if (!TryGetHidDataProperty(hid_device, CFSTR(kIOHIDReportDescriptorKey),
                              &report_descriptor)) {
-    HID_LOG(EVENT) << "Unable to get report descriptor for new device.";
-    return nullptr;
+    HID_LOG(DEBUG) << "Device report descriptor not available.";
   }
 
   return new HidDeviceInfo(
diff --git a/device/serial/BUILD.gn b/device/serial/BUILD.gn
index d3079102..fab490e2 100644
--- a/device/serial/BUILD.gn
+++ b/device/serial/BUILD.gn
@@ -48,6 +48,7 @@
   ]
   deps = [
     "//third_party/mojo/src/mojo/public/cpp/system",
+    "//third_party/re2",
   ]
 
   if (use_udev) {
diff --git a/device/serial/DEPS b/device/serial/DEPS
index fc30a89..4bebd41c 100644
--- a/device/serial/DEPS
+++ b/device/serial/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+dbus",
   "+net/base",
+  "+third_party/re2",
 ]
diff --git a/device/serial/serial.gyp b/device/serial/serial.gyp
index 650c8c6..5d43bd1 100644
--- a/device/serial/serial.gyp
+++ b/device/serial/serial.gyp
@@ -44,6 +44,7 @@
         'device_serial_mojo',
         '../../net/net.gyp:net',
         '../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+        '../../third_party/re2/re2.gyp:re2',
       ],
       'export_dependent_settings': [
         'device_serial_mojo',
diff --git a/device/serial/serial_device_enumerator_win.cc b/device/serial/serial_device_enumerator_win.cc
index 124c6b72..0d1e8f1 100644
--- a/device/serial/serial_device_enumerator_win.cc
+++ b/device/serial/serial_device_enumerator_win.cc
@@ -6,14 +6,75 @@
 
 #include <windows.h>
 
+#include <ntddser.h>
+#include <setupapi.h>
+
 #include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/win/registry.h"
+#include "third_party/re2/re2/re2.h"
 
 namespace device {
 
+namespace {
+
+// Searches the specified device info for a property with the specified key,
+// assigns the result to value, and returns whether the operation was
+// successful.
+bool GetProperty(HDEVINFO dev_info,
+                 SP_DEVINFO_DATA dev_info_data,
+                 const int key,
+                 std::string* value) {
+  // We don't know how much space the property's value will take up, so we call
+  // the property retrieval function once to fetch the size of the required
+  // value buffer, then again once we've allocated a sufficiently large buffer.
+  DWORD buffer_size = 0;
+  SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, key, nullptr,
+                                   nullptr, buffer_size, &buffer_size);
+  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+    return false;
+
+  scoped_ptr<wchar_t[]> buffer(new wchar_t[buffer_size]);
+  if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data, key, nullptr,
+                                        reinterpret_cast<PBYTE>(buffer.get()),
+                                        buffer_size, nullptr))
+    return false;
+
+  *value = base::WideToUTF8(buffer.get());
+  return true;
+}
+
+// Searches for the COM port in the device's friendly name, assigns its value to
+// com_port, and returns whether the operation was successful.
+bool GetCOMPort(const std::string friendly_name, std::string* com_port) {
+  return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port);
+}
+
+// Searches for the display name in the device's friendly name, assigns its
+// value to display_name, and returns whether the operation was successful.
+bool GetDisplayName(const std::string friendly_name,
+                    std::string* display_name) {
+  return RE2::PartialMatch(friendly_name, "(.*) \\(COM[0-9]+\\)", display_name);
+}
+
+// Searches for the vendor ID in the device's hardware ID, assigns its value to
+// vendor_id, and returns whether the operation was successful.
+bool GetVendorID(const std::string hardware_id, uint32_t* vendor_id) {
+  std::string vendor_id_str;
+  return RE2::PartialMatch(hardware_id, "VID_([0-9]+)", &vendor_id_str) &&
+         base::HexStringToUInt(vendor_id_str, vendor_id);
+}
+
+// Searches for the product ID in the device's product ID, assigns its value to
+// product_id, and returns whether the operation was successful.
+bool GetProductID(const std::string hardware_id, uint32_t* product_id) {
+  std::string product_id_str;
+  return RE2::PartialMatch(hardware_id, "PID_([0-9]+)", &product_id_str) &&
+         base::HexStringToUInt(product_id_str, product_id);
+}
+
+}  // namespace
+
 // static
 scoped_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() {
   return scoped_ptr<SerialDeviceEnumerator>(new SerialDeviceEnumeratorWin());
@@ -23,18 +84,53 @@
 
 SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() {}
 
-// TODO(rockot): Query the system for more information than just device paths.
-// This may or may not require using a different strategy than scanning the
-// registry location below.
 mojo::Array<serial::DeviceInfoPtr> SerialDeviceEnumeratorWin::GetDevices() {
-  base::win::RegistryValueIterator iter_key(
-      HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
   mojo::Array<serial::DeviceInfoPtr> devices(0);
-  for (; iter_key.Valid(); ++iter_key) {
+
+  // Make a device interface query to find all serial devices.
+  HDEVINFO dev_info =
+      SetupDiGetClassDevs(&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0, 0,
+                          DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+  if (dev_info == INVALID_HANDLE_VALUE)
+    return devices.Pass();
+
+  SP_DEVINFO_DATA dev_info_data;
+  dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+  for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
+    std::string friendly_name, com_port;
+    // SPDRP_FRIENDLYNAME looks like "USB_SERIAL_PORT (COM3)".
+    if (!GetProperty(dev_info, dev_info_data, SPDRP_FRIENDLYNAME,
+                     &friendly_name) ||
+        !GetCOMPort(friendly_name, &com_port))
+      // In Windows, the COM port is the path used to uniquely identify the
+      // serial device. If the COM can't be found, ignore the device.
+      continue;
+
     serial::DeviceInfoPtr info(serial::DeviceInfo::New());
-    info->path = base::UTF16ToASCII(iter_key.Value());
+    info->path = com_port;
+
+    std::string display_name;
+    if (GetDisplayName(friendly_name, &display_name))
+      info->display_name = display_name;
+
+    std::string hardware_id;
+    // SPDRP_HARDWAREID looks like "FTDIBUS\COMPORT&VID_0403&PID_6001".
+    if (GetProperty(dev_info, dev_info_data, SPDRP_HARDWAREID, &hardware_id)) {
+      uint32_t vendor_id, product_id;
+      if (GetVendorID(hardware_id, &vendor_id)) {
+        info->has_vendor_id = true;
+        info->vendor_id = vendor_id;
+      }
+      if (GetProductID(hardware_id, &product_id)) {
+        info->has_product_id = true;
+        info->product_id = product_id;
+      }
+    }
+
     devices.push_back(info.Pass());
   }
+
+  SetupDiDestroyDeviceInfoList(dev_info);
   return devices.Pass();
 }
 
diff --git a/device/usb/mock_usb_device_handle.h b/device/usb/mock_usb_device_handle.h
index c3742b3..30b23d9 100644
--- a/device/usb/mock_usb_device_handle.h
+++ b/device/usb/mock_usb_device_handle.h
@@ -15,7 +15,19 @@
  public:
   MockUsbDeviceHandle(UsbDevice* device);
 
+  scoped_refptr<UsbDevice> GetDevice() const override;
   MOCK_METHOD0(Close, void());
+  MOCK_METHOD2(SetConfiguration,
+               void(int configuration_value, const ResultCallback& callback));
+  MOCK_METHOD2(ClaimInterface,
+               void(int interface_number, const ResultCallback& callback));
+  MOCK_METHOD1(ReleaseInterface, bool(int interface_number));
+  MOCK_METHOD3(SetInterfaceAlternateSetting,
+               void(int interface_number,
+                    int alternate_setting,
+                    const ResultCallback& callback));
+  MOCK_METHOD1(ResetDevice, void(const ResultCallback& callback));
+  MOCK_METHOD2(ClearHalt, void(uint8 endpoint, const ResultCallback& callback));
   MOCK_METHOD10(ControlTransfer,
                 void(UsbEndpointDirection direction,
                      TransferRequestType request_type,
@@ -43,21 +55,8 @@
                     size_t length,
                     unsigned int timeout,
                     const TransferCallback& callback));
-  MOCK_METHOD1(ResetDevice, void(const ResultCallback& callback));
-  MOCK_METHOD2(GetStringDescriptor, bool(uint8_t, base::string16*));
-  MOCK_METHOD2(SetConfiguration,
-               void(int configuration_value, const ResultCallback& callback));
-  MOCK_METHOD2(ClaimInterface,
-               void(int interface_number, const ResultCallback& callback));
-  MOCK_METHOD1(ReleaseInterface, bool(int interface_number));
-  MOCK_METHOD3(SetInterfaceAlternateSetting,
-               void(int interface_number,
-                    int alternate_setting,
-                    const ResultCallback& callback));
-  MOCK_METHOD2(ClearHalt,
-               void(uint8_t endpoint, const ResultCallback& callback));
-
-  scoped_refptr<UsbDevice> GetDevice() const override;
+  MOCK_METHOD2(FindInterfaceByEndpoint,
+               bool(uint8_t endpoint_address, uint8_t* interface_number));
 
  private:
   ~MockUsbDeviceHandle() override;
diff --git a/device/usb/usb_device.h b/device/usb/usb_device.h
index 64fa6810..beb78036 100644
--- a/device/usb/usb_device.h
+++ b/device/usb/usb_device.h
@@ -44,6 +44,9 @@
     return webusb_allowed_origins_.get();
   }
   const GURL& webusb_landing_page() const { return webusb_landing_page_; }
+  const std::vector<UsbConfigDescriptor>& configurations() const {
+    return configurations_;
+  }
 
   // On ChromeOS the permission_broker service is used to change the ownership
   // of USB device nodes so that Chrome can open them. On other platforms these
@@ -61,11 +64,6 @@
   // if the device is unconfigured.
   virtual const UsbConfigDescriptor* GetActiveConfiguration() = 0;
 
-  // Gets all of the device's UsbConfigDescriptors.
-  const std::vector<UsbConfigDescriptor>& configurations() const {
-    return configurations_;
-  }
-
  protected:
   UsbDevice(uint16_t vendor_id,
             uint16_t product_id,
diff --git a/device/usb/usb_device_handle.h b/device/usb/usb_device_handle.h
index 0597378..23d2fd5c 100644
--- a/device/usb/usb_device_handle.h
+++ b/device/usb/usb_device_handle.h
@@ -90,6 +90,11 @@
                                unsigned int timeout,
                                const TransferCallback& callback) = 0;
 
+  // Gets the interface containing |endpoint_address|. Returns false if no
+  // claimed interface contains that endpoint.
+  virtual bool FindInterfaceByEndpoint(uint8_t endpoint_address,
+                                       uint8_t* interface_number) = 0;
+
  protected:
   friend class base::RefCountedThreadSafe<UsbDeviceHandle>;
 
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index c02895b..cdb0210 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -671,6 +671,17 @@
   }
 }
 
+bool UsbDeviceHandleImpl::FindInterfaceByEndpoint(uint8_t endpoint_address,
+                                                  uint8_t* interface_number) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  const auto endpoint_it = endpoint_map_.find(endpoint_address);
+  if (endpoint_it != endpoint_map_.end()) {
+    *interface_number = endpoint_it->second.interface_number;
+    return true;
+  }
+  return false;
+}
+
 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
     scoped_refptr<UsbContext> context,
     scoped_refptr<UsbDeviceImpl> device,
@@ -815,9 +826,10 @@
 
 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8_t endpoint) {
-  if (ContainsKey(endpoint_map_, endpoint))
-    return claimed_interfaces_[endpoint_map_[endpoint].interface_number];
-  return NULL;
+  const auto endpoint_it = endpoint_map_.find(endpoint);
+  if (endpoint_it != endpoint_map_.end())
+    return claimed_interfaces_[endpoint_it->second.interface_number];
+  return nullptr;
 }
 
 void UsbDeviceHandleImpl::ControlTransferInternal(
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h
index 1dff965..6d45e1e 100644
--- a/device/usb/usb_device_handle_impl.h
+++ b/device/usb/usb_device_handle_impl.h
@@ -82,6 +82,8 @@
                        size_t length,
                        unsigned int timeout,
                        const TransferCallback& callback) override;
+  bool FindInterfaceByEndpoint(uint8_t endpoint_address,
+                               uint8_t* interface_number) override;
 
  protected:
   friend class UsbDeviceImpl;
diff --git a/extensions/browser/api/app_runtime/app_runtime_api.cc b/extensions/browser/api/app_runtime/app_runtime_api.cc
index 39356c3..60c2c0d4 100644
--- a/extensions/browser/api/app_runtime/app_runtime_api.cc
+++ b/extensions/browser/api/app_runtime/app_runtime_api.cc
@@ -52,6 +52,11 @@
   launch_data->SetBoolean(
       "isKioskSession",
       ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode());
+
+  launch_data->SetBoolean(
+      "isPublicSession",
+      ExtensionsBrowserClient::Get()->IsLoggedInAsPublicAccount());
+
   scoped_ptr<base::ListValue> args(new base::ListValue());
   args->Append(launch_data.release());
   scoped_ptr<Event> event(new Event(events::APP_RUNTIME_ON_LAUNCHED,
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_api.cc b/extensions/browser/api/bluetooth/bluetooth_private_api.cc
index d716f897..aa63f2a 100644
--- a/extensions/browser/api/bluetooth/bluetooth_private_api.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_private_api.cc
@@ -452,7 +452,7 @@
     return true;
   }
 
-  device->Connect(
+  device->Pair(
       router->GetPairingDelegate(extension_id()),
       base::Bind(&BluetoothPrivatePairFunction::OnSuccessCallback, this),
       base::Bind(&BluetoothPrivatePairFunction::OnErrorCallback, this));
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc b/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc
index 2c4b61c..a6f20e1 100644
--- a/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc
@@ -263,7 +263,7 @@
                   _, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH));
   EXPECT_CALL(*mock_device_, ExpectingConfirmation())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_device_.get(), Connect(_, _, _))
+  EXPECT_CALL(*mock_device_.get(), Pair(_, _, _))
       .WillOnce(DoAll(
           WithoutArgs(Invoke(
               this,
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc
index 70296895..e4feaf5 100644
--- a/extensions/browser/api/management/management_api.cc
+++ b/extensions/browser/api/management/management_api.cc
@@ -166,7 +166,7 @@
   }
 
   const std::set<std::string> perms =
-      extension.permissions_data()->active_permissions()->GetAPIsAsStrings();
+      extension.permissions_data()->active_permissions().GetAPIsAsStrings();
   if (!perms.empty()) {
     std::set<std::string>::const_iterator perms_iter;
     for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
@@ -176,7 +176,7 @@
   if (!extension.is_hosted_app()) {
     // Skip host permissions for hosted apps.
     const URLPatternSet host_perms =
-        extension.permissions_data()->active_permissions()->explicit_hosts();
+        extension.permissions_data()->active_permissions().explicit_hosts();
     if (!host_perms.is_empty()) {
       for (URLPatternSet::const_iterator iter = host_perms.begin();
            iter != host_perms.end(); ++iter) {
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc
index 412bfc05..7bddcb8e 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -455,15 +455,16 @@
     const std::string& guid,
     const StringCallback& success_callback,
     const FailureCallback& failure_callback) {
-  if (!chromeos::NetworkPortalDetector::IsInitialized()) {
+  if (!chromeos::network_portal_detector::IsInitialized()) {
     failure_callback.Run(networking_private::kErrorNotReady);
     return;
   }
 
-  chromeos::NetworkPortalDetector::CaptivePortalState state =
-      chromeos::NetworkPortalDetector::Get()->GetCaptivePortalState(guid);
   success_callback.Run(
-      chromeos::NetworkPortalDetector::CaptivePortalStatusString(state.status));
+      chromeos::NetworkPortalDetector::CaptivePortalStatusString(
+          chromeos::network_portal_detector::GetInstance()
+              ->GetCaptivePortalState(guid)
+              .status));
 }
 
 void NetworkingPrivateChromeOS::UnlockCellularSim(
diff --git a/extensions/browser/api/networking_private/networking_private_event_router_chromeos.cc b/extensions/browser/api/networking_private/networking_private_event_router_chromeos.cc
index dbe80739..65f3d5c 100644
--- a/extensions/browser/api/networking_private/networking_private_event_router_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_event_router_chromeos.cc
@@ -137,13 +137,13 @@
   if (should_listen && !listening_) {
     NetworkHandler::Get()->network_state_handler()->AddObserver(this,
                                                                 FROM_HERE);
-    if (chromeos::NetworkPortalDetector::IsInitialized())
-      NetworkPortalDetector::Get()->AddObserver(this);
+    if (chromeos::network_portal_detector::IsInitialized())
+      chromeos::network_portal_detector::GetInstance()->AddObserver(this);
   } else if (!should_listen && listening_) {
     NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
                                                                    FROM_HERE);
-    if (chromeos::NetworkPortalDetector::IsInitialized())
-      NetworkPortalDetector::Get()->RemoveObserver(this);
+    if (chromeos::network_portal_detector::IsInitialized())
+      chromeos::network_portal_detector::GetInstance()->RemoveObserver(this);
   }
   listening_ = should_listen;
 }
diff --git a/extensions/browser/api/webcam_private/visca_webcam.cc b/extensions/browser/api/webcam_private/visca_webcam.cc
index b090731..d3cf70f 100644
--- a/extensions/browser/api/webcam_private/visca_webcam.cc
+++ b/extensions/browser/api/webcam_private/visca_webcam.cc
@@ -13,83 +13,114 @@
 namespace {
 
 // Message terminator:
-const char VISCA_TERMINATOR = 0xFF;
+const char kViscaTerminator = 0xFF;
 
 // Response types:
-const char VISCA_RESPONSE_NETWORK_CHANGE = 0x38;
-const char VISCA_RESPONSE_ACK = 0x40;
-const char VISCA_RESPONSE_ERROR = 0x60;
+const char kViscaResponseNetworkChange = 0x38;
+const char kViscaResponseAck = 0x40;
+const char kViscaResponseError = 0x60;
 
-// The default pan speed is MAX_PAN_SPEED /2 and the default tilt speed is
-// MAX_TILT_SPEED / 2.
-const int MAX_PAN_SPEED = 0x18;
-const int MAX_TILT_SPEED = 0x14;
+// The default pan speed is kMaxPanSpeed /2 and the default tilt speed is
+// kMaxTiltSpeed / 2.
+const int kMaxPanSpeed = 0x18;
+const int kMaxTiltSpeed = 0x14;
+const int kDefaultPanSpeed = 0x18 / 2;
+const int kDefaultTiltSpeed = 0x14 / 2;
 
 // Pan-Tilt-Zoom movement comands from http://www.manualslib.com/manual/...
 // 557364/Cisco-Precisionhd-1080p12x.html?page=31#manual
 
 // Reset the address of each device in the VISCA chain (broadcast). This is used
 // when resetting the VISCA network.
-const std::vector<char> kSetAddressCommand = {0x88, 0x30, 0x01, 0xFF};
+const char kSetAddressCommand[] = {0x88, 0x30, 0x01, 0xFF};
 
 // Clear all of the devices, halting any pending commands in the VISCA chain
 // (broadcast). This is used when resetting the VISCA network.
-const std::vector<char> kClearAllCommand = {0x88, 0x01, 0x00, 0x01, 0xFF};
-
-// Clear the command buffer in the target device and cancel the command
-// currently being executed. Command: {0x8X, 0x01, 0x00, 0x01, 0xFF}, X = 1 to
-// 7: target device address.
-const std::vector<char> kClearCommand = {0x81, 0x01, 0x00, 0x01, 0xFF};
+const char kClearAllCommand[] = {0x88, 0x01, 0x00, 0x01, 0xFF};
 
 // Command: {0x8X, 0x09, 0x06, 0x12, 0xFF}, X = 1 to 7: target device address.
 // Response: {0xY0, 0x50, 0x0p, 0x0q, 0x0r, 0x0s, 0x0t, 0x0u, 0x0v, 0x0w, 0xFF},
 // Y = socket number; pqrs: pan position; tuvw: tilt position.
-const std::vector<char> kGetPanTiltCommand = {0x81, 0x09, 0x06, 0x12, 0xFF};
+const char kGetPanTiltCommand[] = {0x81, 0x09, 0x06, 0x12, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x02, 0x0p, 0x0t, 0x0q, 0x0r, 0x0s, 0x0u, 0x0v,
 // 0x0w, 0x0y, 0x0z, 0xFF}, X = 1 to 7: target device address; p = pan speed;
 // t = tilt speed; qrsu = pan position; vwyz = tilt position.
-const std::vector<char> kSetPanTiltCommand = {0x81, 0x01, 0x06, 0x02, 0x00,
-                                              0x00, 0x00, 0x00, 0x00, 0x00,
-                                              0x00, 0x00, 0x00, 0x00, 0xFF};
+const char kSetPanTiltCommand[] = {0x81, 0x01, 0x06, 0x02, 0x00,
+                                   0x00, 0x00, 0x00, 0x00, 0x00,
+                                   0x00, 0x00, 0x00, 0x00, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x05, 0xFF}, X = 1 to 7: target device address.
-const std::vector<char> kResetPanTiltCommand = {0x81, 0x01, 0x06, 0x05, 0xFF};
+const char kResetPanTiltCommand[] = {0x81, 0x01, 0x06, 0x05, 0xFF};
 
 // Command: {0x8X, 0x09, 0x04, 0x47, 0xFF}, X = 1 to 7: target device address.
 // Response: {0xY0, 0x50, 0x0p, 0x0q, 0x0r, 0x0s, 0xFF}, Y = socket number;
 // pqrs: zoom position.
-const std::vector<char> kGetZoomCommand = {0x81, 0x09, 0x04, 0x47, 0xFF};
+const char kGetZoomCommand[] = {0x81, 0x09, 0x04, 0x47, 0xFF};
 
 // Command: {0x8X, 0x01, 0x04, 0x47, 0x0p, 0x0q, 0x0r, 0x0s, 0xFF}, X = 1 to 7:
 // target device address; pqrs: zoom position;
-const std::vector<char> kSetZoomCommand =
-    {0x81, 0x01, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0xFF};
+const char kSetZoomCommand[] = {0x81, 0x01, 0x04, 0x47, 0x00,
+                                0x00, 0x00, 0x00, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x01, 0x0p, 0x0t, 0x03, 0x01, 0xFF}, X = 1 to 7:
 // target device address; p: pan speed; t: tilt speed.
-const std::vector<char> kPTUpCommand = {0x81, 0x01, 0x06, 0x01, 0x00,
-                                        0x00, 0x03, 0x01, 0xFF};
+const char kPTUpCommand[] = {0x81, 0x01, 0x06, 0x01, 0x00,
+                             0x00, 0x03, 0x01, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x01, 0x0p, 0x0t, 0x03, 0x02, 0xFF}, X = 1 to 7:
 // target device address; p: pan speed; t: tilt speed.
-const std::vector<char> kPTDownCommand = {0x81, 0x01, 0x06, 0x01, 0x00,
-                                          0x00, 0x03, 0x02, 0xFF};
+const char kPTDownCommand[] = {0x81, 0x01, 0x06, 0x01, 0x00,
+                               0x00, 0x03, 0x02, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x01, 0x0p, 0x0t, 0x0, 0x03, 0xFF}, X = 1 to 7:
 // target device address; p: pan speed; t: tilt speed.
-const std::vector<char> kPTLeftCommand = {0x81, 0x01, 0x06, 0x01, 0x00,
-                                          0x00, 0x01, 0x03, 0xFF};
+const char kPTLeftCommand[] = {0x81, 0x01, 0x06, 0x01, 0x00,
+                               0x00, 0x01, 0x03, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x01, 0x0p, 0x0t, 0x02, 0x03, 0xFF}, X = 1 to 7:
 // target device address; p: pan speed; t: tilt speed.
-const std::vector<char> kPTRightCommand = {0x81, 0x01, 0x06, 0x01, 0x00,
-                                           0x00, 0x02, 0x03, 0xFF};
+const char kPTRightCommand[] = {0x81, 0x01, 0x06, 0x01, 0x00,
+                                0x00, 0x02, 0x03, 0xFF};
 
 // Command: {0x8X, 0x01, 0x06, 0x01, 0x03, 0x03, 0x03, 0x03, 0xFF}, X = 1 to 7:
 // target device address.
-const std::vector<char> kPTStopCommand =
-    {0x81, 0x01, 0x06, 0x01, 0x03, 0x03, 0x03, 0x03, 0xFF};
+const char kPTStopCommand[] = {0x81, 0x01, 0x06, 0x01, 0x03,
+                               0x03, 0x03, 0x03, 0xFF};
+
+#define CHAR_VECTOR_FROM_ARRAY(array) \
+  std::vector<char>(array, array + arraysize(array))
+
+int ShiftResponseLowerBits(char c, size_t shift) {
+  return static_cast<int>(c & 0x0F) << shift;
+}
+
+int BuildResponseInt(const std::vector<char>& response, size_t start_index) {
+  return ShiftResponseLowerBits(response[start_index], 12) +
+         ShiftResponseLowerBits(response[start_index + 1], 8) +
+         ShiftResponseLowerBits(response[start_index + 2], 4) +
+         ShiftResponseLowerBits(response[start_index + 3], 0);
+}
+
+void ResponseToCommand(std::vector<char>* command,
+                       size_t start_index,
+                       uint16_t response) {
+  DCHECK(command);
+  std::vector<char>& command_ref = *command;
+  command_ref[start_index] |= ((response >> 12) & 0x0F);
+  command_ref[start_index + 1] |= ((response >> 8) & 0x0F);
+  command_ref[start_index + 2] |= ((response >> 4 & 0x0F));
+  command_ref[start_index + 3] |= (response & 0x0F);
+}
+
+int CalculateSpeed(int desired_speed, int max_speed, int default_speed) {
+  int speed = std::min(desired_speed, max_speed);
+  return speed > 0 ? speed : default_speed;
+}
+
+int GetPositiveValue(int value) {
+  return value < 0x8000 ? value : value - 0xFFFF;
+}
 
 }  // namespace
 
@@ -139,13 +170,13 @@
 void ViscaWebcam::OnConnected(const OpenCompleteCallback& open_callback,
                               bool success) {
   if (!success) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(open_callback, false));
-  } else {
-    Send(kSetAddressCommand,
-         base::Bind(&ViscaWebcam::OnAddressSetCompleted,
-                    weak_ptr_factory_.GetWeakPtr(), open_callback));
+    PostOpenFailureTask(open_callback);
+    return;
   }
+
+  Send(CHAR_VECTOR_FROM_ARRAY(kSetAddressCommand),
+       base::Bind(&ViscaWebcam::OnAddressSetCompleted,
+                  weak_ptr_factory_.GetWeakPtr(), open_callback));
 }
 
 void ViscaWebcam::OnAddressSetCompleted(
@@ -154,13 +185,13 @@
     const std::vector<char>& response) {
   commands_.pop_front();
   if (!success) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(open_callback, false));
-  } else {
-    Send(kClearAllCommand,
-         base::Bind(&ViscaWebcam::OnClearAllCompleted,
-                    weak_ptr_factory_.GetWeakPtr(), open_callback));
+    PostOpenFailureTask(open_callback);
+    return;
   }
+
+  Send(CHAR_VECTOR_FROM_ARRAY(kClearAllCommand),
+       base::Bind(&ViscaWebcam::OnClearAllCompleted,
+                  weak_ptr_factory_.GetWeakPtr(), open_callback));
 }
 
 void ViscaWebcam::OnClearAllCompleted(const OpenCompleteCallback& open_callback,
@@ -168,12 +199,12 @@
                                       const std::vector<char>& response) {
   commands_.pop_front();
   if (!success) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(open_callback, false));
-  } else {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(open_callback, true));
+    PostOpenFailureTask(open_callback);
+    return;
   }
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(open_callback, true));
 }
 
 void ViscaWebcam::Send(const std::vector<char>& command,
@@ -193,8 +224,7 @@
   if (error == api::serial::SEND_ERROR_NONE) {
     ReceiveLoop(callback);
   } else {
-    const std::vector<char> response;
-    callback.Run(false, response);
+    callback.Run(false, std::vector<char>());
   }
 }
 
@@ -211,7 +241,7 @@
 
   if (error == api::serial::RECEIVE_ERROR_NONE) {
     // Loop until encounter the terminator.
-    if (int(data_buffer_.back()) != VISCA_TERMINATOR) {
+    if (static_cast<int>(data_buffer_.back()) != kViscaTerminator) {
       base::MessageLoop::current()->PostTask(
           FROM_HERE, base::Bind(&ViscaWebcam::ReceiveLoop,
                                 weak_ptr_factory_.GetWeakPtr(), callback));
@@ -220,10 +250,11 @@
       std::vector<char> response;
       response.swap(data_buffer_);
 
-      if ((int(response[1]) & 0xF0) == VISCA_RESPONSE_ERROR) {
+      if ((static_cast<int>(response[1]) & 0xF0) == kViscaResponseError) {
         callback.Run(false, response);
-      } else if ((int(response[1]) & 0xF0) != VISCA_RESPONSE_ACK &&
-                 (int(response[1]) & 0xFF) != VISCA_RESPONSE_NETWORK_CHANGE) {
+      } else if ((static_cast<int>(response[1]) & 0xF0) != kViscaResponseAck &&
+                 (static_cast<int>(response[1]) & 0xFF) !=
+                     kViscaResponseNetworkChange) {
         callback.Run(true, response);
       } else {
         base::MessageLoop::current()->PostTask(
@@ -270,23 +301,17 @@
     switch (type) {
       case INQUIRY_PAN:
         // See kGetPanTiltCommand for the format of response.
-        pan_ = ((int(response[2]) & 0x0F) << 12) +
-               ((int(response[3]) & 0x0F) << 8) +
-               ((int(response[4]) & 0x0F) << 4) + (int(response[5]) & 0x0F);
-        value = pan_ < 0x8000 ? pan_ : pan_ - 0xFFFF;
+        pan_ = BuildResponseInt(response, 2);
+        value = GetPositiveValue(pan_);
         break;
       case INQUIRY_TILT:
         // See kGetPanTiltCommand for the format of response.
-        tilt_ = ((int(response[6]) & 0x0F) << 12) +
-                ((int(response[7]) & 0x0F) << 8) +
-                ((int(response[8]) & 0x0F) << 4) + (int(response[9]) & 0x0F);
-        value = tilt_ < 0x8000 ? tilt_ : tilt_ - 0xFFFF;
+        tilt_ = BuildResponseInt(response, 6);
+        value = GetPositiveValue(tilt_);
         break;
       case INQUIRY_ZOOM:
         // See kGetZoomCommand for the format of response.
-        value = ((int(response[2]) & 0x0F) << 12) +
-                ((int(response[3]) & 0x0F) << 8) +
-                ((int(response[4]) & 0x0F) << 4) + (int(response[5]) & 0x0F);
+        value = BuildResponseInt(response, 2);
         break;
     }
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -305,20 +330,26 @@
   }
 }
 
+void ViscaWebcam::PostOpenFailureTask(
+    const OpenCompleteCallback& open_callback) {
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(open_callback, false /* success? */));
+}
+
 void ViscaWebcam::GetPan(const GetPTZCompleteCallback& callback) {
-  Send(kGetPanTiltCommand,
+  Send(CHAR_VECTOR_FROM_ARRAY(kGetPanTiltCommand),
        base::Bind(&ViscaWebcam::OnInquiryCompleted,
                   weak_ptr_factory_.GetWeakPtr(), INQUIRY_PAN, callback));
 }
 
 void ViscaWebcam::GetTilt(const GetPTZCompleteCallback& callback) {
-  Send(kGetPanTiltCommand,
+  Send(CHAR_VECTOR_FROM_ARRAY(kGetPanTiltCommand),
        base::Bind(&ViscaWebcam::OnInquiryCompleted,
                   weak_ptr_factory_.GetWeakPtr(), INQUIRY_TILT, callback));
 }
 
 void ViscaWebcam::GetZoom(const GetPTZCompleteCallback& callback) {
-  Send(kGetZoomCommand,
+  Send(CHAR_VECTOR_FROM_ARRAY(kGetZoomCommand),
        base::Bind(&ViscaWebcam::OnInquiryCompleted,
                   weak_ptr_factory_.GetWeakPtr(), INQUIRY_ZOOM, callback));
 }
@@ -326,23 +357,15 @@
 void ViscaWebcam::SetPan(int value,
                          int pan_speed,
                          const SetPTZCompleteCallback& callback) {
-  pan_speed = std::min(pan_speed, MAX_PAN_SPEED);
-  pan_speed = pan_speed > 0 ? pan_speed : MAX_PAN_SPEED / 2;
+  int actual_pan_speed =
+      CalculateSpeed(pan_speed, kMaxPanSpeed, kDefaultPanSpeed);
   pan_ = value;
-  uint16_t pan = (uint16_t)pan_;
-  uint16_t tilt = (uint16_t)tilt_;
 
-  std::vector<char> command = kSetPanTiltCommand;
-  command[4] |= pan_speed;
-  command[5] |= (MAX_TILT_SPEED / 2);
-  command[6] |= ((pan & 0xF000) >> 12);
-  command[7] |= ((pan & 0x0F00) >> 8);
-  command[8] |= ((pan & 0x00F0) >> 4);
-  command[9] |= (pan & 0x000F);
-  command[10] |= ((tilt & 0xF000) >> 12);
-  command[11] |= ((tilt & 0x0F00) >> 8);
-  command[12] |= ((tilt & 0x00F0) >> 4);
-  command[13] |= (tilt & 0x000F);
+  std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kSetPanTiltCommand);
+  command[4] |= actual_pan_speed;
+  command[5] |= kDefaultTiltSpeed;
+  ResponseToCommand(&command, 6, static_cast<uint16_t>(pan_));
+  ResponseToCommand(&command, 10, static_cast<uint16_t>(tilt_));
   Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
                            weak_ptr_factory_.GetWeakPtr(), callback));
 }
@@ -350,34 +373,23 @@
 void ViscaWebcam::SetTilt(int value,
                           int tilt_speed,
                           const SetPTZCompleteCallback& callback) {
-  tilt_speed = std::min(tilt_speed, MAX_TILT_SPEED);
-  tilt_speed = tilt_speed > 0 ? tilt_speed : MAX_TILT_SPEED / 2;
+  int actual_tilt_speed =
+      CalculateSpeed(tilt_speed, kMaxTiltSpeed, kDefaultTiltSpeed);
   tilt_ = value;
-  uint16_t pan = (uint16_t)pan_;
-  uint16_t tilt = (uint16_t)tilt_;
 
-  std::vector<char> command = kSetPanTiltCommand;
-  command[4] |= (MAX_PAN_SPEED / 2);
-  command[5] |= tilt_speed;
-  command[6] |= ((pan & 0xF000) >> 12);
-  command[7] |= ((pan & 0x0F00) >> 8);
-  command[8] |= ((pan & 0x00F0) >> 4);
-  command[9] |= (pan & 0x000F);
-  command[10] |= ((tilt & 0xF000) >> 12);
-  command[11] |= ((tilt & 0x0F00) >> 8);
-  command[12] |= ((tilt & 0x00F0) >> 4);
-  command[13] |= (tilt & 0x000F);
+  std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kSetPanTiltCommand);
+  command[4] |= kDefaultPanSpeed;
+  command[5] |= actual_tilt_speed;
+  ResponseToCommand(&command, 6, static_cast<uint16_t>(pan_));
+  ResponseToCommand(&command, 10, static_cast<uint16_t>(tilt_));
   Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
                            weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
 void ViscaWebcam::SetZoom(int value, const SetPTZCompleteCallback& callback) {
-  value = value > 0 ? value : 0;
-  std::vector<char> command = kSetZoomCommand;
-  command[4] |= ((value & 0xF000) >> 12);
-  command[5] |= ((value & 0x0F00) >> 8);
-  command[6] |= ((value & 0x00F0) >> 4);
-  command[7] |= (value & 0x000F);
+  int actual_value = std::min(value, 0);
+  std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kSetZoomCommand);
+  ResponseToCommand(&command, 4, actual_value);
   Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
                            weak_ptr_factory_.GetWeakPtr(), callback));
 }
@@ -385,21 +397,21 @@
 void ViscaWebcam::SetPanDirection(PanDirection direction,
                                   int pan_speed,
                                   const SetPTZCompleteCallback& callback) {
-  pan_speed = std::min(pan_speed, MAX_PAN_SPEED);
-  pan_speed = pan_speed > 0 ? pan_speed : MAX_PAN_SPEED / 2;
-  std::vector<char> command = kPTStopCommand;
+  int actual_pan_speed =
+      CalculateSpeed(pan_speed, kMaxPanSpeed, kDefaultPanSpeed);
+  std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kPTStopCommand);
   switch (direction) {
     case PAN_STOP:
       break;
     case PAN_RIGHT:
-      command = kPTRightCommand;
-      command[4] |= pan_speed;
-      command[5] |= (MAX_TILT_SPEED / 2);
+      command = CHAR_VECTOR_FROM_ARRAY(kPTRightCommand);
+      command[4] |= actual_pan_speed;
+      command[5] |= kDefaultTiltSpeed;
       break;
     case PAN_LEFT:
-      command = kPTLeftCommand;
-      command[4] |= pan_speed;
-      command[5] |= (MAX_TILT_SPEED / 2);
+      command = CHAR_VECTOR_FROM_ARRAY(kPTLeftCommand);
+      command[4] |= actual_pan_speed;
+      command[5] |= kDefaultTiltSpeed;
       break;
   }
   Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
@@ -409,21 +421,21 @@
 void ViscaWebcam::SetTiltDirection(TiltDirection direction,
                                    int tilt_speed,
                                    const SetPTZCompleteCallback& callback) {
-  tilt_speed = std::min(tilt_speed, MAX_TILT_SPEED);
-  tilt_speed = tilt_speed > 0 ? tilt_speed : MAX_TILT_SPEED / 2;
-  std::vector<char> command = kPTStopCommand;
+  int actual_tilt_speed =
+      CalculateSpeed(tilt_speed, kMaxTiltSpeed, kDefaultTiltSpeed);
+  std::vector<char> command = CHAR_VECTOR_FROM_ARRAY(kPTStopCommand);
   switch (direction) {
     case TILT_STOP:
       break;
     case TILT_UP:
-      command = kPTUpCommand;
-      command[4] |= (MAX_PAN_SPEED / 2);
-      command[5] |= tilt_speed;
+      command = CHAR_VECTOR_FROM_ARRAY(kPTUpCommand);
+      command[4] |= kDefaultPanSpeed;
+      command[5] |= actual_tilt_speed;
       break;
     case TILT_DOWN:
-      command = kPTDownCommand;
-      command[4] |= (MAX_PAN_SPEED / 2);
-      command[5] |= tilt_speed;
+      command = CHAR_VECTOR_FROM_ARRAY(kPTDownCommand);
+      command[4] |= kDefaultPanSpeed;
+      command[5] |= actual_tilt_speed;
       break;
   }
   Send(command, base::Bind(&ViscaWebcam::OnCommandCompleted,
@@ -436,14 +448,14 @@
                         const SetPTZCompleteCallback& callback) {
   // pan and tilt are always reset together in Visca Webcams.
   if (pan || tilt) {
-    Send(kResetPanTiltCommand,
+    Send(CHAR_VECTOR_FROM_ARRAY(kResetPanTiltCommand),
          base::Bind(&ViscaWebcam::OnCommandCompleted,
                     weak_ptr_factory_.GetWeakPtr(), callback));
   }
   if (zoom) {
     // Set the default zoom value to 100 to be consistent with V4l2 webcam.
-    const int default_zoom = 100;
-    SetZoom(default_zoom, callback);
+    const int kDefaultZoom = 100;
+    SetZoom(kDefaultZoom, callback);
   }
 }
 
diff --git a/extensions/browser/api/webcam_private/visca_webcam.h b/extensions/browser/api/webcam_private/visca_webcam.h
index 67ba759..7b56196fa 100644
--- a/extensions/browser/api/webcam_private/visca_webcam.h
+++ b/extensions/browser/api/webcam_private/visca_webcam.h
@@ -77,6 +77,8 @@
                           bool success,
                           const std::vector<char>& response);
 
+  void PostOpenFailureTask(const OpenCompleteCallback& open_callback);
+
   // Webcam Overrides:
   void GetPan(const GetPTZCompleteCallback& callback) override;
   void GetTilt(const GetPTZCompleteCallback& callback) override;
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index d660b8d..0aeec38 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -596,7 +596,7 @@
         event->event_url.host() != extension->id() &&  // event for self is ok
         !extension->permissions_data()
              ->active_permissions()
-             ->HasEffectiveAccessToURL(event->event_url)) {
+             .HasEffectiveAccessToURL(event->event_url)) {
       return;
     }
     // Secondly, if the event is for incognito mode, the Extension must be
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 1e8bd72..3c918e2 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1150,6 +1150,7 @@
   EASYUNLOCKPRIVATE_SETUPCONNECTIONDISCONNECT,
   EASYUNLOCKPRIVATE_SETUPCONNECTIONSEND,
   DATAREDUCTIONPROXY_GETDATAUSAGE,
+  EASYUNLOCKPRIVATE_SETUPCONNECTIONGETDEVICEADDRESS,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index 51074f9..28d8db8c 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -629,31 +629,31 @@
 void ExtensionPrefs::SetExtensionPrefPermissionSet(
     const std::string& extension_id,
     const std::string& pref_key,
-    const PermissionSet* new_value) {
+    const PermissionSet& new_value) {
   std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
-  base::ListValue* api_values = CreatePermissionList(new_value->apis());
+  base::ListValue* api_values = CreatePermissionList(new_value.apis());
   UpdateExtensionPref(extension_id, api_pref, api_values);
 
   std::string manifest_permissions_pref =
       JoinPrefs(pref_key, kPrefManifestPermissions);
-  base::ListValue* manifest_permissions_values = CreatePermissionList(
-      new_value->manifest_permissions());
+  base::ListValue* manifest_permissions_values =
+      CreatePermissionList(new_value.manifest_permissions());
   UpdateExtensionPref(extension_id,
                       manifest_permissions_pref,
                       manifest_permissions_values);
 
   // Set the explicit host permissions.
-  if (!new_value->explicit_hosts().is_empty()) {
+  if (!new_value.explicit_hosts().is_empty()) {
     SetExtensionPrefURLPatternSet(extension_id,
                                   JoinPrefs(pref_key, kPrefExplicitHosts),
-                                  new_value->explicit_hosts());
+                                  new_value.explicit_hosts());
   }
 
   // Set the scriptable host permissions.
-  if (!new_value->scriptable_hosts().is_empty()) {
+  if (!new_value.scriptable_hosts().is_empty()) {
     SetExtensionPrefURLPatternSet(extension_id,
                                   JoinPrefs(pref_key, kPrefScriptableHosts),
-                                  new_value->scriptable_hosts());
+                                  new_value.scriptable_hosts());
   }
 }
 
@@ -1020,34 +1020,30 @@
   return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
 }
 
-void ExtensionPrefs::AddGrantedPermissions(
-    const std::string& extension_id,
-    const PermissionSet* permissions) {
+void ExtensionPrefs::AddGrantedPermissions(const std::string& extension_id,
+                                           const PermissionSet& permissions) {
   CHECK(crx_file::id_util::IdIsValid(extension_id));
-  DCHECK(permissions);
-
   scoped_ptr<const PermissionSet> granted = GetGrantedPermissions(extension_id);
   scoped_ptr<const PermissionSet> union_set;
   if (granted)
-    union_set = PermissionSet::CreateUnion(*permissions, *granted);
+    union_set = PermissionSet::CreateUnion(permissions, *granted);
   // The new granted permissions are the union of the already granted
   // permissions and the newly granted permissions.
   SetExtensionPrefPermissionSet(extension_id, kPrefGrantedPermissions,
-                                union_set ? union_set.get() : permissions);
+                                union_set ? *union_set : permissions);
 }
 
 void ExtensionPrefs::RemoveGrantedPermissions(
     const std::string& extension_id,
-    const PermissionSet* permissions) {
+    const PermissionSet& permissions) {
   CHECK(crx_file::id_util::IdIsValid(extension_id));
 
   // The new granted permissions are the difference of the already granted
   // permissions and the newly ungranted permissions.
   SetExtensionPrefPermissionSet(
       extension_id, kPrefGrantedPermissions,
-      PermissionSet::CreateDifference(*GetGrantedPermissions(extension_id),
-                                      *permissions)
-          .get());
+      *PermissionSet::CreateDifference(*GetGrantedPermissions(extension_id),
+                                       permissions));
 }
 
 scoped_ptr<const PermissionSet> ExtensionPrefs::GetActivePermissions(
@@ -1056,9 +1052,8 @@
   return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
 }
 
-void ExtensionPrefs::SetActivePermissions(
-    const std::string& extension_id,
-    const PermissionSet* permissions) {
+void ExtensionPrefs::SetActivePermissions(const std::string& extension_id,
+                                          const PermissionSet& permissions) {
   SetExtensionPrefPermissionSet(
       extension_id, kPrefActivePermissions, permissions);
 }
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
index 0ef1d40..2e9e840 100644
--- a/extensions/browser/extension_prefs.h
+++ b/extensions/browser/extension_prefs.h
@@ -360,11 +360,11 @@
   // |extension_id|. The new granted permissions set will be the union of
   // |permissions| and the already granted permissions.
   void AddGrantedPermissions(const std::string& extension_id,
-                             const PermissionSet* permissions);
+                             const PermissionSet& permissions);
 
   // As above, but subtracts the given |permissions| from the granted set.
   void RemoveGrantedPermissions(const std::string& extension_id,
-                                const PermissionSet* permissions);
+                                const PermissionSet& permissions);
 
   // Gets the active permission set for the specified extension. This may
   // differ from the permissions in the manifest due to the optional
@@ -374,7 +374,7 @@
 
   // Sets the active |permissions| for the extension with |extension_id|.
   void SetActivePermissions(const std::string& extension_id,
-                            const PermissionSet* permissions);
+                            const PermissionSet& permissions);
 
   // Records whether or not this extension is currently running.
   void SetExtensionRunning(const std::string& extension_id, bool is_running);
@@ -613,7 +613,7 @@
   // belonging to |extension_id|.
   void SetExtensionPrefPermissionSet(const std::string& extension_id,
                                      const std::string& pref_key,
-                                     const PermissionSet* new_value);
+                                     const PermissionSet& new_value);
 
   // Returns an immutable dictionary for extension |id|'s prefs, or NULL if it
   // doesn't exist.
diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h
index 8b66051..89763d9d 100644
--- a/extensions/browser/extensions_browser_client.h
+++ b/extensions/browser/extensions_browser_client.h
@@ -164,6 +164,9 @@
   // Return true if the system is run in forced app mode.
   virtual bool IsRunningInForcedAppMode() = 0;
 
+  // Return true if the user is logged in as a public session.
+  virtual bool IsLoggedInAsPublicAccount() = 0;
+
   // Returns the embedder's ApiActivityMonitor for |context|. Returns NULL if
   // the embedder does not monitor extension API activity.
   virtual ApiActivityMonitor* GetApiActivityMonitor(
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index e96b30e5..f4d1cc4 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1235,17 +1235,20 @@
 WebContents* WebViewGuest::OpenURLFromTab(
     WebContents* source,
     const content::OpenURLParams& params) {
-  // There are two use cases to consider from a security perspective:
-  // 1.) Renderer-initiated navigation to chrome:// must always be blocked even
-  //     if the <webview> is in WebUI. This is handled by
-  //     WebViewGuest::LoadURLWithParams. WebViewGuest::NavigateGuest will also
-  //     call LoadURLWithParams. CreateNewGuestWebViewWindow creates a new
-  //     WebViewGuest which will call NavigateGuest in DidInitialize.
-  // 2.) The Language Settings context menu item should always work, both in
-  //     Chrome Apps and WebUI. This is a browser initiated request and so
-  //     we pass it along to the embedder's WebContentsDelegate to get the
-  //     browser to perform the action for the <webview>.
-  if (!params.is_renderer_initiated) {
+  // Most navigations should be handled by WebViewGuest::LoadURLWithParams,
+  // which takes care of blocking chrome:// URLs and other web-unsafe schemes.
+  // (NavigateGuest and CreateNewGuestWebViewWindow also go through
+  // LoadURLWithParams.)
+  //
+  // We make an exception here for context menu items, since the Language
+  // Settings item uses a browser-initiated navigation to a chrome:// URL.
+  // These can be passed to the embedder's WebContentsDelegate so that the
+  // browser performs the action for the <webview>. Navigations to a new
+  // tab, etc., are also handled by the WebContentsDelegate.
+  if (!params.is_renderer_initiated &&
+      (!content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
+           params.url.scheme()) ||
+       params.disposition != CURRENT_TAB)) {
     if (!owner_web_contents()->GetDelegate())
       return nullptr;
     return owner_web_contents()->GetDelegate()->OpenURLFromTab(
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index a4a46cd..8b2b4b534 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -553,6 +553,8 @@
     uint64 request_id) {
   ExtensionHost* host = GetBackgroundHostForExtension(
       GetExtensionID(render_frame_host));
+  auto result = pending_network_requests_.insert(request_id);
+  DCHECK(result.second) << "Duplicate network request IDs.";
   if (host && IsFrameInExtensionHost(host, render_frame_host)) {
     IncrementLazyKeepaliveCount(host->extension());
     host->OnNetworkRequestStarted(request_id);
@@ -566,7 +568,8 @@
       GetExtensionID(render_frame_host));
   if (host && IsFrameInExtensionHost(host, render_frame_host)) {
     host->OnNetworkRequestDone(request_id);
-    DecrementLazyKeepaliveCount(host->extension());
+    if (pending_network_requests_.erase(request_id))
+      DecrementLazyKeepaliveCount(host->extension());
   }
 }
 
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h
index 85f2def..9d44453 100644
--- a/extensions/browser/process_manager.h
+++ b/extensions/browser/process_manager.h
@@ -314,6 +314,13 @@
   // reset.
   uint64 last_background_close_sequence_id_;
 
+  // Tracks pending network requests by opaque ID. This is used to ensure proper
+  // keepalive counting in response to request status updates; e.g., if an
+  // extension URLRequest is constructed and then destroyed without ever
+  // starting, we can receive a completion notification without a corresponding
+  // start notification. In that case we want to avoid decrementing keepalive.
+  std::set<int> pending_network_requests_;
+
   // Must be last member, see doc on WeakPtrFactory.
   base::WeakPtrFactory<ProcessManager> weak_ptr_factory_;
 
diff --git a/extensions/browser/test_extensions_browser_client.cc b/extensions/browser/test_extensions_browser_client.cc
index be9e4b5..d98f7af 100644
--- a/extensions/browser/test_extensions_browser_client.cc
+++ b/extensions/browser/test_extensions_browser_client.cc
@@ -142,6 +142,10 @@
 
 bool TestExtensionsBrowserClient::IsRunningInForcedAppMode() { return false; }
 
+bool TestExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
+  return false;
+}
+
 ApiActivityMonitor* TestExtensionsBrowserClient::GetApiActivityMonitor(
     BrowserContext* context) {
   return NULL;
diff --git a/extensions/browser/test_extensions_browser_client.h b/extensions/browser/test_extensions_browser_client.h
index 86f05765..274a8a9 100644
--- a/extensions/browser/test_extensions_browser_client.h
+++ b/extensions/browser/test_extensions_browser_client.h
@@ -76,6 +76,7 @@
   bool DidVersionUpdate(content::BrowserContext* context) override;
   void PermitExternalProtocolHandler() override;
   bool IsRunningInForcedAppMode() override;
+  bool IsLoggedInAsPublicAccount() override;
   ApiActivityMonitor* GetApiActivityMonitor(
       content::BrowserContext* context) override;
   ExtensionSystemProvider* GetExtensionSystemFactory() override;
diff --git a/extensions/common/api/app_runtime.idl b/extensions/common/api/app_runtime.idl
index 0f8cb9c..e3339bd 100644
--- a/extensions/common/api/app_runtime.idl
+++ b/extensions/common/api/app_runtime.idl
@@ -63,6 +63,11 @@
     // kiosk session</a>.
     boolean? isKioskSession;
 
+    // Whether the app is being launched in a <a
+    // href="https://support.google.com/chrome/a/answer/3017014">Chrome OS
+    // public session</a>.
+    boolean? isPublicSession;
+
     // Where the app is launched from.
     LaunchSource? source;
   };
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl
index b813e34..64ef51e 100644
--- a/extensions/common/api/networking_private.idl
+++ b/extensions/common/api/networking_private.idl
@@ -72,14 +72,10 @@
     DOMString? Username;
   };
 
-  dictionary CellularConfigProperties {
-    boolean? AutoConnect;
-    APNProperties? APN;
-
-    // Specifies which carrier to use for Cellular configurations that support
-    // multiple carriers. May be set with $(ref:setProperties), but will be
-    // ignored by $(ref:createConfiguration).
-    DOMString? Carrier;
+  dictionary CellularProviderProperties {
+    DOMString Name;
+    DOMString Code;
+    DOMString? Country;
   };
 
   dictionary CellularSimState {
@@ -93,12 +89,18 @@
     DOMString? newPin;
   };
 
-  dictionary CellularStateProperties {
-    ActivationStateType? ActivationState;
-    DOMString? NetworkTechnology;
-    DOMString? RoamingState;
-    boolean? SIMPresent;
-    long? SignalStrength;
+  dictionary IssuerSubjectPattern {
+    DOMString? CommonName;
+    DOMString? Locality;
+    DOMString? Organization;
+    DOMString? OrganizationalUnit;    
+  };
+
+  dictionary CertificatePattern {
+    DOMString[]? EnrollmentURI;
+    IssuerSubjectPattern? Issuer;
+    DOMString[]? IssuerCARef;
+    IssuerSubjectPattern? Subject;
   };
 
   dictionary DeviceStateProperties {
@@ -120,8 +122,27 @@
     NetworkType Type;
   };
 
-  dictionary EthernetStateProperties {
-    DOMString Authentication;
+  dictionary EAPProperties {
+    DOMString? AnonymousIdentity;
+    CertificatePattern? ClientCertPattern;
+    DOMString? ClientCertRef;
+    DOMString? ClientCertType;
+    DOMString? Identity;
+    DOMString? Inner;
+    DOMString Outer;
+    DOMString? Password;
+    boolean? SaveCredentials;
+    DOMString[]? ServerCARefs;
+    boolean? UseProactiveKeyCaching;
+    boolean? UseSystemCAs;
+  };
+
+  dictionary FoundNetworkProperties {
+    DOMString Status;
+    DOMString NetworkId;
+    DOMString Technology;
+    DOMString? ShortName;
+    DOMString? LongName;
   };
 
   dictionary IPConfigProperties {
@@ -133,8 +154,37 @@
     DOMString? WebProxyAutoDiscoveryUrl;
   };
 
+  dictionary XAUTHProperties {
+    DOMString? Password;
+    boolean? SaveCredentials;
+    DOMString? Username;
+  };
+
   dictionary IPSecProperties {
     DOMString AuthenticationType;
+    CertificatePattern? ClientCertPattern;
+    DOMString? ClientCertRef;
+    DOMString? ClientCertType;
+    EAPProperties? EAP;
+    DOMString? Group;
+    long? IKEVersion;
+    DOMString? PSK;
+    boolean? SaveCredentials;
+    DOMString[]? ServerCARefs;
+    XAUTHProperties? XAUTH;
+  };
+
+  dictionary L2TPProperties {
+    boolean? LcpEchoDisabled;
+    DOMString? Password;
+    boolean? SaveCredentials;
+    DOMString? Username;
+  };
+
+  dictionary PaymentPortal {
+    DOMString Method;
+    DOMString? PostData;
+    DOMString? Url;
   };
 
   dictionary ProxyLocation {
@@ -156,11 +206,52 @@
     DOMString? PAC;
   };
 
+  dictionary VerifyX509 {
+    DOMString? Name;
+    DOMString? Type;
+  };
+
   dictionary OpenVPNProperties {
+    DOMString? Auth;
+    DOMString? AuthRetry;
+    boolean? AuthNoCache;
+    DOMString? Cipher;
+    DOMString? ClientCertRef;
+    CertificatePattern? ClientCertPattern;
+    DOMString? ClientCertType;
+    DOMString? CompLZO;
+    boolean? CompNoAdapt;
+    boolean? IgnoreDefaultRoute;
+    DOMString? KeyDirection;
+    DOMString? NsCertType;
     DOMString? OTP;
     DOMString? Password;
+    long? Port;
+    DOMString? Proto;
+    DOMString? PushPeerInfo;
+    DOMString? RemoteCertEKU;
+    DOMString[]? RemoteCertKU;
+    DOMString? RemoteCertTLS;
+    long? RenegSec;
+    boolean? SaveCredentials;
+    DOMString[]? ServerCARefs;
+    DOMString? ServerCertRef;
+    long? ServerPollTimeout;
+    long? Shaper;
+    DOMString? StaticChallenge;
+    DOMString? TLSAuthContents;
+    DOMString? TLSRemote;
     DOMString? UserAuthenticationType;
     DOMString? Username;
+    DOMString? Verb;
+    DOMString? VerifyHash;
+    VerifyX509? VerifyX509;
+  };
+
+  dictionary SIMLockStatus {
+    DOMString LockType;  // sim-pin, sim-puk, or ''
+    boolean LockEnabled;
+    long? RetriesLeft;
   };
 
   dictionary ThirdPartyVPNProperties {
@@ -168,9 +259,61 @@
     DOMString? ProviderName;
   };
 
-  dictionary VPNConfigProperties {
+  dictionary CellularProperties {
+    boolean? AutoConnect;
+    APNProperties? APN;
+    APNProperties[]? APNList;
+    DOMString? ActivationType;
+    ActivationStateType? ActivationState;
+    boolean? AllowRoaming;
+    DOMString? Carrier;
+    DOMString? ESN;
+    DOMString? Family;
+    DOMString? FirmwareRevision;
+    FoundNetworkProperties[]? FoundNetworks;
+    DOMString? HardwareRevision;
+    CellularProviderProperties? HomeProvider;
+    DOMString? ICCID;
+    DOMString? IMEI;
+    APNProperties? LastGoodAPN;
+    DOMString? Manufacturer;
+    DOMString? MDN;
+    DOMString? MEID;
+    DOMString? MIN;
+    DOMString? ModelID;
+    DOMString? NetworkTechnology;
+    PaymentPortal? PaymentPortal;
+    long? PRLVersion;
+    DOMString? RoamingState;
+    CellularProviderProperties? ServingOperator;
+    SIMLockStatus? SIMLockStatus;
+    boolean? SIMPresent;
+    boolean? SupportNetworkScan;
+    DOMString[]? SupportedCarriers;
+  };
+
+  dictionary CellularStateProperties {
+    ActivationStateType? ActivationState;
+    DOMString? NetworkTechnology;
+    DOMString? RoamingState;
+    boolean? SIMPresent;
+    long? SignalStrength;
+  };
+
+  dictionary EthernetProperties {
+    DOMString? Authentication;
+    EAPProperties? EAP;
+  };
+
+  dictionary EthernetStateProperties {
+    DOMString Authentication;
+  };
+
+  dictionary VPNProperties {
     boolean? AutoConnect;
     DOMString? Host;
+    IPSecProperties? IPsec;
+    L2TPProperties? L2TP;
     OpenVPNProperties? OpenVPN;
     ThirdPartyVPNProperties? ThirdPartyVPN;
     DOMString? Type;
@@ -182,13 +325,20 @@
     ThirdPartyVPNProperties? ThirdPartyVPN;
   };
 
-  dictionary WiFiConfigProperties {
+  dictionary WiFiProperties {
+    boolean? AllowGatewayARPPolling;
     boolean? AutoConnect;
+    DOMString? BSSID;
+    EAPProperties? EAP;
+    long? Frequency;
+    long[]? FrequencyList;
     DOMString? HexSSID;
     boolean? HiddenSSID;
     DOMString? Passphrase;
+    long? RoamThreshold;
     DOMString? SSID;
     DOMString? Security;
+    long? SignalStrength;
   };
 
   dictionary WiFiStateProperties {
@@ -196,8 +346,10 @@
     long? SignalStrength;
   };
 
-  dictionary WiMaxConfigProperties {
+  dictionary WiMAXProperties {
     boolean? AutoConnect;
+    EAPProperties? EAP;
+    long? SignalStrength;
   };
 
   dictionary WiMAXStateProperties {
@@ -205,7 +357,8 @@
   };
 
   dictionary NetworkConfigProperties {
-    CellularConfigProperties? Cellular;
+    CellularProperties? Cellular;
+    EthernetProperties? Ethernet;
     DOMString? GUID;
     IPConfigType? IPAddressConfigType;
     DOMString? Name;
@@ -214,9 +367,9 @@
     ProxySettings? ProxySettings;
     IPConfigProperties? StaticIPConfig;
     NetworkType? Type;
-    VPNConfigProperties? VPN;
-    WiFiConfigProperties? WiFi;
-    WiMaxConfigProperties? WiMAX;
+    VPNProperties? VPN;
+    WiFiProperties? WiFi;
+    WiMAXProperties? WiMAX;
   };
 
   dictionary NetworkStateProperties {
@@ -235,6 +388,30 @@
     WiMAXStateProperties? WiMAX;
   };
 
+  dictionary NetworkProperties {
+    CellularProperties? Cellular;
+    boolean? Connectable;
+    ConnectionStateType? ConnectionState;
+    DOMString? ErrorState;
+    EthernetProperties? Ethernet;
+    DOMString GUID;
+    IPConfigType? IPAddressConfigType;
+    IPConfigProperties[]? IPConfigs;
+    DOMString? MacAddress;
+    DOMString? Name;
+    IPConfigType? NameServersConfigType;
+    long? Priority;
+    ProxySettings? ProxySettings;
+    boolean? RestrictedConnectivity;
+    IPConfigProperties? StaticIPConfig;
+    IPConfigProperties? SavedIPConfig;
+    DOMString? Source;
+    NetworkType Type;
+    VPNProperties? VPN;
+    WiFiProperties? WiFi;
+    WiMAXProperties? WiMAX;
+  };
+
   dictionary VerificationProperties {
     // A string containing a PEM-encoded (including the 'BEGIN CERTIFICATE'
     // header and 'END CERTIFICATE' footer) X.509 certificate for use in
@@ -291,7 +468,7 @@
   callback BooleanCallback = void(boolean result);
   callback StringCallback = void(DOMString result);
   // TODO(stevenjb): Use NetworkProperties for |result| once defined.
-  callback GetPropertiesCallback = void(object result);
+  callback GetPropertiesCallback = void(NetworkProperties result);
   // TODO(stevenjb): Use ManagedNetworkProperties for |result| once defined.
   callback GetManagedPropertiesCallback = void(object result);
   callback GetStatePropertiesCallback = void(NetworkStateProperties result);
diff --git a/extensions/common/extension_messages.cc b/extensions/common/extension_messages.cc
index 76c36dce..1fee836 100644
--- a/extensions/common/extension_messages.cc
+++ b/extensions/common/extension_messages.cc
@@ -54,9 +54,9 @@
     : manifest(extension->manifest()->value()->DeepCopy()),
       location(extension->location()),
       path(extension->path()),
-      active_permissions(*extension->permissions_data()->active_permissions()),
-      withheld_permissions(
-          *extension->permissions_data()->withheld_permissions()),
+      active_permissions(extension->permissions_data()->active_permissions()),
+      withheld_permissions(extension->permissions_data()
+                               ->withheld_permissions()),
       id(extension->id()),
       creation_flags(extension->creation_flags()) {
   if (include_tab_permissions) {
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc
index 1aa2e606..a7c6db9 100644
--- a/extensions/common/manifest_handlers/permissions_parser.cc
+++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -318,21 +318,21 @@
 }
 
 // static
-const PermissionSet* PermissionsParser::GetRequiredPermissions(
+const PermissionSet& PermissionsParser::GetRequiredPermissions(
     const Extension* extension) {
   DCHECK(extension->GetManifestData(keys::kPermissions));
-  return static_cast<const ManifestPermissions*>(
-             extension->GetManifestData(keys::kPermissions))
-      ->permissions.get();
+  return *static_cast<const ManifestPermissions*>(
+              extension->GetManifestData(keys::kPermissions))
+              ->permissions;
 }
 
 // static
-const PermissionSet* PermissionsParser::GetOptionalPermissions(
+const PermissionSet& PermissionsParser::GetOptionalPermissions(
     const Extension* extension) {
   DCHECK(extension->GetManifestData(keys::kOptionalPermissions));
-  return static_cast<const ManifestPermissions*>(
-             extension->GetManifestData(keys::kOptionalPermissions))
-      ->permissions.get();
+  return *static_cast<const ManifestPermissions*>(
+              extension->GetManifestData(keys::kOptionalPermissions))
+              ->permissions;
 }
 
 }  // namespace extensions
diff --git a/extensions/common/manifest_handlers/permissions_parser.h b/extensions/common/manifest_handlers/permissions_parser.h
index 645017d1b..2844d2ae 100644
--- a/extensions/common/manifest_handlers/permissions_parser.h
+++ b/extensions/common/manifest_handlers/permissions_parser.h
@@ -45,9 +45,9 @@
   // Return the extension's manifest-specified permissions. In no cases should
   // these permissions be used to determine if an action is allowed. Instead,
   // use PermissionsData.
-  static const PermissionSet* GetRequiredPermissions(
+  static const PermissionSet& GetRequiredPermissions(
       const Extension* extension);
-  static const PermissionSet* GetOptionalPermissions(
+  static const PermissionSet& GetOptionalPermissions(
       const Extension* extension);
 
  private:
diff --git a/extensions/common/manifest_handlers/shared_module_info.cc b/extensions/common/manifest_handlers/shared_module_info.cc
index 8fd1ab9a..ecd68da 100644
--- a/extensions/common/manifest_handlers/shared_module_info.cc
+++ b/extensions/common/manifest_handlers/shared_module_info.cc
@@ -218,7 +218,7 @@
   // own, instead they rely on the permissions of the extensions which import
   // them.
   if (SharedModuleInfo::IsSharedModule(extension) &&
-      !extension->permissions_data()->active_permissions()->IsEmpty()) {
+      !extension->permissions_data()->active_permissions().IsEmpty()) {
     *error = errors::kInvalidExportPermissions;
     return false;
   }
diff --git a/extensions/common/permissions/permission_message_provider.h b/extensions/common/permissions/permission_message_provider.h
index 8981f80..a75b46e 100644
--- a/extensions/common/permissions/permission_message_provider.h
+++ b/extensions/common/permissions/permission_message_provider.h
@@ -38,10 +38,9 @@
   // Whether certain permissions are considered varies by extension type.
   // TODO(sashab): Add an implementation of this method that uses
   // PermissionIDSet instead, then deprecate this one.
-  virtual bool IsPrivilegeIncrease(
-      const PermissionSet* old_permissions,
-      const PermissionSet* new_permissions,
-      Manifest::Type extension_type) const = 0;
+  virtual bool IsPrivilegeIncrease(const PermissionSet& old_permissions,
+                                   const PermissionSet& new_permissions,
+                                   Manifest::Type extension_type) const = 0;
 
   // Given the permissions for an extension, finds the IDs of all the
   // permissions for that extension (including API, manifest and host
@@ -50,7 +49,7 @@
   // this type, and make this take as little as is needed to work out the
   // PermissionIDSet.
   virtual PermissionIDSet GetAllPermissionIDs(
-      const PermissionSet* permissions,
+      const PermissionSet& permissions,
       Manifest::Type extension_type) const = 0;
 };
 
diff --git a/extensions/common/permissions/permission_message_test_util.cc b/extensions/common/permissions/permission_message_test_util.cc
index 2cf3a5d9..9b1981e 100644
--- a/extensions/common/permissions/permission_message_test_util.cc
+++ b/extensions/common/permissions/permission_message_test_util.cc
@@ -17,7 +17,7 @@
 
 namespace {
 
-PermissionMessages GetMessages(const PermissionSet* permissions,
+PermissionMessages GetMessages(const PermissionSet& permissions,
                                Manifest::Type extension_type) {
   const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
   return provider->GetPermissionMessages(
@@ -194,7 +194,7 @@
 }
 
 testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const std::string& expected_message) {
   return VerifyHasPermissionMessage(permissions, extension_type,
@@ -202,7 +202,7 @@
 }
 
 testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const base::string16& expected_message) {
   return VerifyHasPermissionMessageImpl(
@@ -231,7 +231,7 @@
 }
 
 testing::AssertionResult VerifyOnePermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const base::string16& expected_message) {
   return VerifyPermissionMessagesWithSubmessagesImpl(
diff --git a/extensions/common/permissions/permission_message_test_util.h b/extensions/common/permissions/permission_message_test_util.h
index 8cfc3e0..34e36f3 100644
--- a/extensions/common/permissions/permission_message_test_util.h
+++ b/extensions/common/permissions/permission_message_test_util.h
@@ -24,11 +24,11 @@
     const PermissionsData* permissions_data,
     const base::string16& expected_message);
 testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const std::string& expected_message);
 testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const base::string16& expected_message);
 
@@ -42,7 +42,7 @@
     const PermissionsData* permissions_data,
     const base::string16& expected_message);
 testing::AssertionResult VerifyOnePermissionMessage(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type,
     const base::string16& expected_message);
 
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc
index 6757298..7c001a5 100644
--- a/extensions/common/permissions/permissions_data.cc
+++ b/extensions/common/permissions/permissions_data.cc
@@ -42,13 +42,12 @@
 
 PermissionsData::PermissionsData(const Extension* extension)
     : extension_id_(extension->id()), manifest_type_(extension->GetType()) {
-  const PermissionSet* required_permissions =
+  const PermissionSet& required_permissions =
       PermissionsParser::GetRequiredPermissions(extension);
-  active_permissions_unsafe_.reset(
-      new PermissionSet(required_permissions->apis(),
-                        required_permissions->manifest_permissions(),
-                        required_permissions->explicit_hosts(),
-                        required_permissions->scriptable_hosts()));
+  active_permissions_unsafe_.reset(new PermissionSet(
+      required_permissions.apis(), required_permissions.manifest_permissions(),
+      required_permissions.explicit_hosts(),
+      required_permissions.scriptable_hosts()));
   withheld_permissions_unsafe_.reset(new PermissionSet());
 }
 
@@ -75,16 +74,16 @@
 // static
 bool PermissionsData::ScriptsMayRequireActionForExtension(
     const Extension* extension,
-    const PermissionSet* permissions) {
+    const PermissionSet& permissions) {
   // An extension may require user action to execute scripts iff the extension
   // shows up in chrome:extensions (so the user can grant withheld permissions),
   // is not part of chrome or corporate policy, not on the scripting whitelist,
   // and requires enough permissions that we should withhold them.
   return extension->ShouldDisplayInExtensionSettings() &&
-      !Manifest::IsPolicyLocation(extension->location()) &&
-      !Manifest::IsComponentLocation(extension->location()) &&
-      !CanExecuteScriptEverywhere(extension) &&
-      permissions->ShouldWarnAllHosts();
+         !Manifest::IsPolicyLocation(extension->location()) &&
+         !Manifest::IsComponentLocation(extension->location()) &&
+         !CanExecuteScriptEverywhere(extension) &&
+         permissions.ShouldWarnAllHosts();
 }
 
 // static
@@ -226,7 +225,7 @@
   base::AutoLock auto_lock(runtime_lock_);
   return PermissionMessageProvider::Get()->GetPermissionMessages(
       PermissionMessageProvider::Get()->GetAllPermissionIDs(
-          active_permissions_unsafe_.get(), manifest_type_));
+          *active_permissions_unsafe_, manifest_type_));
 }
 
 bool PermissionsData::HasWithheldImpliedAllHosts() const {
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h
index d7d5f27..19fbe02 100644
--- a/extensions/common/permissions/permissions_data.h
+++ b/extensions/common/permissions/permissions_data.h
@@ -78,7 +78,7 @@
   // that are currently on the extension's PermissionsData.
   static bool ScriptsMayRequireActionForExtension(
       const Extension* extension,
-      const PermissionSet* permissions);
+      const PermissionSet& permissions);
 
   // Returns true if we should skip the permissions warning for the extension
   // with the given |extension_id|.
@@ -204,14 +204,14 @@
     return tab_specific_permissions_;
   }
 
-  const PermissionSet* active_permissions() const {
+  const PermissionSet& active_permissions() const {
     DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
-    return active_permissions_unsafe_.get();
+    return *active_permissions_unsafe_;
   }
 
-  const PermissionSet* withheld_permissions() const {
+  const PermissionSet& withheld_permissions() const {
     DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread());
-    return withheld_permissions_unsafe_.get();
+    return *withheld_permissions_unsafe_;
   }
 
 #if defined(UNIT_TEST)
diff --git a/extensions/renderer/extension_injection_host.cc b/extensions/renderer/extension_injection_host.cc
index 43782be..e0a51a0 100644
--- a/extensions/renderer/extension_injection_host.cc
+++ b/extensions/renderer/extension_injection_host.cc
@@ -91,7 +91,7 @@
   // We notify the browser of any injection if the extension has no withheld
   // permissions (i.e., the permissions weren't restricted), but would have
   // otherwise been affected by the scripts-require-action feature.
-  return extension_->permissions_data()->withheld_permissions()->IsEmpty() &&
+  return extension_->permissions_data()->withheld_permissions().IsEmpty() &&
          PermissionsData::ScriptsMayRequireActionForExtension(
              extension_, extension_->permissions_data()->active_permissions());
 }
diff --git a/extensions/renderer/resources/app_runtime_custom_bindings.js b/extensions/renderer/resources/app_runtime_custom_bindings.js
index 309d4af..2b492c59 100644
--- a/extensions/renderer/resources/app_runtime_custom_bindings.js
+++ b/extensions/renderer/resources/app_runtime_custom_bindings.js
@@ -45,6 +45,7 @@
       if (--numItems === 0) {
         var data = {
           isKioskSession: launchData.isKioskSession,
+          isPublicSession: launchData.isPublicSession,
           source: launchData.source
         };
         if (items.length !== 0) {
diff --git a/extensions/renderer/resources/runtime_custom_bindings.js b/extensions/renderer/resources/runtime_custom_bindings.js
index 4e4a71d..2b0e44a 100644
--- a/extensions/renderer/resources/runtime_custom_bindings.js
+++ b/extensions/renderer/resources/runtime_custom_bindings.js
@@ -8,7 +8,6 @@
 
 var messaging = require('messaging');
 var runtimeNatives = requireNative('runtime');
-var unloadEvent = require('unload_event');
 var process = requireNative('process');
 var forEach = require('utils').forEach;
 
@@ -153,11 +152,6 @@
   });
 
   apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) {
-    // Don't let orphaned content scripts communicate with their extension.
-    // http://crbug.com/168263
-    if (unloadEvent.wasDispatched)
-      throw new Error('Error connecting to extension ' + targetId);
-
     if (!targetId) {
       // runtime.id is only defined inside extensions. If we're in a webpage,
       // the best we can do at this point is to fail.
@@ -190,12 +184,10 @@
 
   apiFunctions.setHandleRequest('connectNative',
                                 function(nativeAppName) {
-    if (!unloadEvent.wasDispatched) {
-      var portId = runtimeNatives.OpenChannelToNativeApp(runtime.id,
-                                                         nativeAppName);
-      if (portId >= 0)
-        return messaging.createPort(portId, '');
-    }
+    var portId = runtimeNatives.OpenChannelToNativeApp(runtime.id,
+                                                       nativeAppName);
+    if (portId >= 0)
+      return messaging.createPort(portId, '');
     throw new Error('Error connecting to native app: ' + nativeAppName);
   });
 
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc
index 62b2a5f..a3ec44a 100644
--- a/extensions/shell/browser/shell_extensions_browser_client.cc
+++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -159,6 +159,10 @@
   return false;
 }
 
+bool ShellExtensionsBrowserClient::IsLoggedInAsPublicAccount() {
+  return false;
+}
+
 ApiActivityMonitor* ShellExtensionsBrowserClient::GetApiActivityMonitor(
     BrowserContext* context) {
   // app_shell doesn't monitor API function calls or events.
diff --git a/extensions/shell/browser/shell_extensions_browser_client.h b/extensions/shell/browser/shell_extensions_browser_client.h
index 8b65ccf..8c449ee 100644
--- a/extensions/shell/browser/shell_extensions_browser_client.h
+++ b/extensions/shell/browser/shell_extensions_browser_client.h
@@ -67,6 +67,7 @@
   bool DidVersionUpdate(content::BrowserContext* context) override;
   void PermitExternalProtocolHandler() override;
   bool IsRunningInForcedAppMode() override;
+  bool IsLoggedInAsPublicAccount() override;
   ApiActivityMonitor* GetApiActivityMonitor(
       content::BrowserContext* context) override;
   ExtensionSystemProvider* GetExtensionSystemFactory() override;
diff --git a/extensions/shell/common/shell_extensions_client.cc b/extensions/shell/common/shell_extensions_client.cc
index cd0b9faa..4a37b0906d 100644
--- a/extensions/shell/common/shell_extensions_client.cc
+++ b/extensions/shell/common/shell_extensions_client.cc
@@ -47,8 +47,8 @@
     return PermissionMessages();
   }
 
-  bool IsPrivilegeIncrease(const PermissionSet* old_permissions,
-                           const PermissionSet* new_permissions,
+  bool IsPrivilegeIncrease(const PermissionSet& old_permissions,
+                           const PermissionSet& new_permissions,
                            Manifest::Type extension_type) const override {
     // Ensure we implement this before shipping.
     CHECK(false);
@@ -56,7 +56,7 @@
   }
 
   PermissionIDSet GetAllPermissionIDs(
-      const PermissionSet* permissions,
+      const PermissionSet& permissions,
       Manifest::Type extension_type) const override {
     return PermissionIDSet();
   }
diff --git a/extensions/test/test_permission_message_provider.cc b/extensions/test/test_permission_message_provider.cc
index 62dbf87ca..c34081e 100644
--- a/extensions/test/test_permission_message_provider.cc
+++ b/extensions/test/test_permission_message_provider.cc
@@ -18,14 +18,14 @@
 }
 
 bool TestPermissionMessageProvider::IsPrivilegeIncrease(
-    const PermissionSet* old_permissions,
-    const PermissionSet* new_permissions,
+    const PermissionSet& old_permissions,
+    const PermissionSet& new_permissions,
     Manifest::Type extension_type) const {
   return false;
 }
 
 PermissionIDSet TestPermissionMessageProvider::GetAllPermissionIDs(
-    const PermissionSet* permissions,
+    const PermissionSet& permissions,
     Manifest::Type extension_type) const {
   return PermissionIDSet();
 }
diff --git a/extensions/test/test_permission_message_provider.h b/extensions/test/test_permission_message_provider.h
index 18c0aa2..3866e90d 100644
--- a/extensions/test/test_permission_message_provider.h
+++ b/extensions/test/test_permission_message_provider.h
@@ -18,11 +18,11 @@
  private:
   PermissionMessages GetPermissionMessages(
       const PermissionIDSet& permissions) const override;
-  bool IsPrivilegeIncrease(const PermissionSet* old_permissions,
-                           const PermissionSet* new_permissions,
+  bool IsPrivilegeIncrease(const PermissionSet& old_permissions,
+                           const PermissionSet& new_permissions,
                            Manifest::Type extension_type) const override;
   PermissionIDSet GetAllPermissionIDs(
-      const PermissionSet* permissions,
+      const PermissionSet& permissions,
       Manifest::Type extension_type) const override;
 
   DISALLOW_COPY_AND_ASSIGN(TestPermissionMessageProvider);
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index eee0f810..68b12def 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -1404,7 +1404,12 @@
 }
 
 void BatchUploadRequest::ProcessURLFetchResults(const net::URLFetcher* source) {
-  UMA_HISTOGRAM_SPARSE_SLOWLY(kUMADriveBatchUploadResponseCode, GetErrorCode());
+  // Return the detailed raw HTTP code if the error code is abstracted
+  // DRIVE_OTHER_ERROR.
+  UMA_HISTOGRAM_SPARSE_SLOWLY(kUMADriveBatchUploadResponseCode,
+                              GetErrorCode() != DRIVE_OTHER_ERROR
+                                  ? GetErrorCode()
+                                  : source->GetResponseCode());
 
   if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) {
     RunCallbackOnPrematureFailure(GetErrorCode());
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index d6d81ea..597f5259 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -6016,7 +6016,8 @@
     f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
     f.write("      next_cmd, sizeof(cmd) +\n")
     f.write("      RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));\n")
-    f.write("  // TODO(gman): Check that ids were inserted;\n")
+    f.write("  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd),\n")
+    f.write("                      sizeof(ids)));\n")
     f.write("}\n")
     f.write("\n")
 
@@ -6480,7 +6481,8 @@
     f.write("  CheckBytesWrittenMatchesExpectedSize(\n")
     f.write("      next_cmd, sizeof(cmd) +\n")
     f.write("      RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));\n")
-    f.write("  // TODO(gman): Check that ids were inserted;\n")
+    f.write("  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd),\n")
+    f.write("                      sizeof(ids)));\n")
     f.write("}\n")
     f.write("\n")
 
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 1856e65..62bff78 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -744,7 +744,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteFramebuffersImmediate) {
@@ -762,7 +762,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteProgram) {
@@ -790,7 +790,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteSamplersImmediate) {
@@ -808,7 +808,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteSync) {
@@ -846,7 +846,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteTransformFeedbacksImmediate) {
@@ -865,7 +865,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DepthFunc) {
@@ -1074,7 +1074,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GenerateMipmap) {
@@ -1102,7 +1102,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GenRenderbuffersImmediate) {
@@ -1120,7 +1120,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GenSamplersImmediate) {
@@ -1137,7 +1137,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GenTexturesImmediate) {
@@ -1154,7 +1154,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GenTransformFeedbacksImmediate) {
@@ -1172,7 +1172,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, GetActiveAttrib) {
@@ -3778,7 +3778,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteQueriesEXTImmediate) {
@@ -3796,7 +3796,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, QueryCounterEXT) {
@@ -3919,7 +3919,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteVertexArraysOESImmediate) {
@@ -3937,7 +3937,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, IsVertexArrayOES) {
@@ -4585,7 +4585,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, DeleteValuebuffersCHROMIUMImmediate) {
@@ -4604,7 +4604,7 @@
   CheckBytesWrittenMatchesExpectedSize(
       next_cmd,
       sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u));
-  // TODO(gman): Check that ids were inserted;
+  EXPECT_EQ(0, memcmp(ids, ImmediateDataAddress(&cmd), sizeof(ids)));
 }
 
 TEST_F(GLES2FormatTest, IsValuebufferCHROMIUM) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index fcde538..8574d5fc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -7630,7 +7630,7 @@
 
   glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
 
-  if (attrib->divisor())
+  if (feature_info_->feature_flags().angle_instanced_arrays)
     glVertexAttribDivisorANGLE(0, 0);
 
   *simulated = true;
@@ -7649,7 +7649,13 @@
         attrib_index, attrib->size(), attrib->type(), attrib->normalized(),
         attrib->gl_stride(), ptr);
   }
-  if (attrib->divisor())
+
+  // Attrib divisors should only be non-zero when the ANGLE_instanced_arrays
+  // extension is available
+  DCHECK(attrib->divisor() == 0 ||
+      feature_info_->feature_flags().angle_instanced_arrays);
+
+  if (feature_info_->feature_flags().angle_instanced_arrays)
     glVertexAttribDivisorANGLE(attrib_index, attrib->divisor());
   glBindBuffer(
       GL_ARRAY_BUFFER, state_.bound_array_buffer.get() ?
@@ -10090,6 +10096,14 @@
         "glCompressedTexImage2D", target, "target");
     return error::kNoError;
   }
+  // TODO(ccameron): Add a separate texture from |texture_target| for
+  // [Compressed]Tex[Sub]Image2D and related functions.
+  // http://crbug.com/536854
+  if (target == GL_TEXTURE_RECTANGLE_ARB) {
+    LOCAL_SET_GL_ERROR_INVALID_ENUM(
+        "glCompressedTexImage2D", target, "target");
+    return error::kNoError;
+  }
   if (!validators_->compressed_texture_format.IsValid(
       internal_format)) {
     LOCAL_SET_GL_ERROR_INVALID_ENUM(
@@ -10236,6 +10250,14 @@
         GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
     return error::kNoError;
   }
+  // TODO(ccameron): Add a separate texture from |texture_target| for
+  // [Compressed]Tex[Sub]Image2D and related functions.
+  // http://crbug.com/536854
+  if (target == GL_TEXTURE_RECTANGLE_ARB) {
+    LOCAL_SET_GL_ERROR(
+        GL_INVALID_ENUM, "glCompressedTexSubImage2D", "target");
+    return error::kNoError;
+  }
   if (!validators_->compressed_texture_format.IsValid(format)) {
     LOCAL_SET_GL_ERROR_INVALID_ENUM(
         "glCompressedTexSubImage2D", format, "format");
@@ -10989,6 +11011,13 @@
     LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
     return false;
   }
+  // TODO(ccameron): Add a separate texture from |texture_target| for
+  // [Compressed]Tex[Sub]Image2D and related functions.
+  // http://crbug.com/536854
+  if (target == GL_TEXTURE_RECTANGLE_ARB) {
+    LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
+    return false;
+  }
   if (width < 0) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0");
     return false;
@@ -14298,12 +14327,6 @@
                                              const GLfloat* matrix) {
   DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
          matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
-  if (!features().chromium_path_rendering) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
-                       "glMatrixLoadfCHROMIUM",
-                       "function not available");
-    return;
-  }
 
   GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
                                ? state_.projection_matrix
@@ -14318,13 +14341,6 @@
   DCHECK(matrix_mode == GL_PATH_PROJECTION_CHROMIUM ||
          matrix_mode == GL_PATH_MODELVIEW_CHROMIUM);
 
-  if (!features().chromium_path_rendering) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
-                       "glMatrixLoadIdentityCHROMIUM",
-                       "function not available");
-    return;
-  }
-
   GLfloat* target_matrix = matrix_mode == GL_PATH_PROJECTION_CHROMIUM
                                ? state_.projection_matrix
                                : state_.modelview_matrix;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 5107b09..d4ca3bc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -1824,6 +1824,9 @@
     EXPECT_CALL(*gl_, VertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL))
         .Times(1)
         .RetiresOnSaturation();
+    EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0))
+        .Times(testing::AtMost(1))
+        .RetiresOnSaturation();
     EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, buffer_id))
         .Times(1)
         .RetiresOnSaturation();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
index 932e8511..b2147cc 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
@@ -1027,6 +1027,10 @@
   AddExpectationsForSimulatedAttrib0(kNumVertices, kServiceBufferId);
   SetupExpectationsForApplyingDefaultDirtyState();
 
+  EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0))
+        .Times(1)
+        .RetiresOnSaturation();
+
   EXPECT_CALL(*gl_, DrawArraysInstancedANGLE(GL_TRIANGLES, 0, kNumVertices, 1))
       .Times(1)
       .RetiresOnSaturation();
@@ -1520,6 +1524,10 @@
   AddExpectationsForSimulatedAttrib0(kMaxValidIndex + 1, kServiceBufferId);
   SetupExpectationsForApplyingDefaultDirtyState();
 
+  EXPECT_CALL(*gl_, VertexAttribDivisorANGLE(0, 0))
+        .Times(1)
+        .RetiresOnSaturation();
+
   EXPECT_CALL(
       *gl_,
       DrawElementsInstancedANGLE(GL_TRIANGLES,
@@ -1529,6 +1537,7 @@
                                  1))
       .Times(1)
       .RetiresOnSaturation();
+
   DrawElementsInstancedANGLE cmd;
   cmd.Init(GL_TRIANGLES,
            kValidIndexRangeCount,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
index 1b30d0ba..89dec15a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_textures.cc
@@ -1807,22 +1807,6 @@
       GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId);
   ASSERT_TRUE(GetTexture(client_texture_id_) != NULL);
 
-  EXPECT_CALL(*gl_, GetError())
-      .WillOnce(Return(GL_NO_ERROR))
-      .WillOnce(Return(GL_NO_ERROR))
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_,
-              TexImage2D(target,
-                         level,
-                         internal_format,
-                         width,
-                         height,
-                         0,
-                         format,
-                         type,
-                         _))
-      .Times(1)
-      .RetiresOnSaturation();
   TexImage2D cmd;
   cmd.Init(target,
            level,
@@ -1835,7 +1819,7 @@
            kSharedMemoryOffset);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 
-  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+  EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
 }
 
 TEST_P(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DInvalid) {
@@ -1868,9 +1852,7 @@
            kSharedMemoryOffset);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 
-  // TexImage2D may only be used with level 0 on GL_TEXTURE_RECTANGLE_ARB
-  // targets.
-  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+  EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
 }
 
 TEST_P(GLES2DecoderManualInitTest, TexSubImage2DClearsAfterTexImage2DNULL) {
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 1dab2b8..5ff4d2d 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -1934,6 +1934,14 @@
         error_state, function_name, args.target, "target");
     return false;
   }
+  // TODO(ccameron): Add a separate texture from |texture_target| for
+  // [Compressed]Tex[Sub]Image2D and related functions.
+  // http://crbug.com/536854
+  if (args.target == GL_TEXTURE_RECTANGLE_ARB) {
+    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+        error_state, function_name, args.target, "target");
+    return false;
+  }
   if (!ValidateTextureParameters(
       error_state, function_name, args.format, args.type,
       args.internal_format, args.level)) {
diff --git a/gpu/gl_tests_apk.isolate b/gpu/gl_tests_apk.isolate
new file mode 100644
index 0000000..8abb497
--- /dev/null
+++ b/gpu/gl_tests_apk.isolate
@@ -0,0 +1,17 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'includes': [
+    '../build/android/android.isolate',
+  ],
+  'variables': {
+    'command': [
+      '<(PRODUCT_DIR)/bin/run_gl_tests',
+    ],
+    'files': [
+      '<(PRODUCT_DIR)/bin/run_gl_tests',
+      '<(PRODUCT_DIR)/gl_tests_apk/',
+    ]
+  },
+}
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 15b62cd..930153a 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -847,6 +847,38 @@
           ],
         },
       ],
-    }]
+    }],
+    ['OS == "android" and test_isolation_mode != "noop"',
+      {
+        'targets': [
+          {
+            'target_name': 'gl_tests_apk_run',
+            'type': 'none',
+            'dependencies': [
+              'gl_tests_apk',
+            ],
+            'includes': [
+              '../build/isolate.gypi',
+            ],
+            'sources': [
+              'gl_tests_apk.isolate',
+            ],
+          },
+          {
+            'target_name': 'gpu_unittests_apk_run',
+            'type': 'none',
+            'dependencies': [
+              'gpu_unittests_apk',
+            ],
+            'includes': [
+              '../build/isolate.gypi',
+            ],
+            'sources': [
+              'gpu_unittests_apk.isolate',
+            ],
+          },
+        ],
+      },
+    ],
   ],
 }
diff --git a/gpu/gpu_unittests_apk.isolate b/gpu/gpu_unittests_apk.isolate
new file mode 100644
index 0000000..94411b1
--- /dev/null
+++ b/gpu/gpu_unittests_apk.isolate
@@ -0,0 +1,17 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'includes': [
+    '../build/android/android.isolate',
+  ],
+  'variables': {
+    'command': [
+      '<(PRODUCT_DIR)/bin/run_gpu_unittests',
+    ],
+    'files': [
+      '<(PRODUCT_DIR)/bin/run_gpu_unittests',
+      '<(PRODUCT_DIR)/gpu_unittests_apk/',
+    ]
+  },
+}
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index d574a9d6..c20f7960 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -28,10 +28,6 @@
   try_job {
     buckets {
       name: "tryserver.chromium.linux"
-      builders {
-        name: "android_amp_rel_tests_recipe"
-        experiment_percentage: 10
-      }
       builders { name: "android_arm64_dbg_recipe" }
       builders { name: "android_chromium_gn_compile_dbg" }
       builders { name: "android_chromium_gn_compile_rel" }
diff --git a/ios/build/bots/chromium.fyi/Chromium_iOS_Device.json b/ios/build/bots/chromium.fyi/Chromium_iOS_Device.json
index 9994e52..283a859 100644
--- a/ios/build/bots/chromium.fyi/Chromium_iOS_Device.json
+++ b/ios/build/bots/chromium.fyi/Chromium_iOS_Device.json
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for 32-bit devices."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "arm32"
   },
   "compiler": "xcodebuild",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git "a/ios/build/bots/chromium.fyi/Chromium_iOS_Device_\050ninja\051.json" "b/ios/build/bots/chromium.fyi/Chromium_iOS_Device_\050ninja\051.json"
index 79e7f1c..5440881 100644
--- "a/ios/build/bots/chromium.fyi/Chromium_iOS_Device_\050ninja\051.json"
+++ "b/ios/build/bots/chromium.fyi/Chromium_iOS_Device_\050ninja\051.json"
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for fat binaries using ninja."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "ninja",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git "a/ios/build/bots/chromium.fyi/Chromium_iOS_Simulator_\050dbg\051.json" "b/ios/build/bots/chromium.fyi/Chromium_iOS_Simulator_\050dbg\051.json"
index c11cbed..91d5028 100644
--- "a/ios/build/bots/chromium.fyi/Chromium_iOS_Simulator_\050dbg\051.json"
+++ "b/ios/build/bots/chromium.fyi/Chromium_iOS_Simulator_\050dbg\051.json"
@@ -3,20 +3,30 @@
     "smut"
   ],
   "comments": [
-    "Tests for 32- and 64-bit iOS 8.3 simulators."
+    "Tests for 32- and 64-bit iOS 9.0 simulators."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "xcodebuild",
   "configuration": "Debug",
-  "sdk": "iphonesimulator8.3",
+  "sdk": "iphonesimulator9.0",
   "tests": [
     {
       "include": "common_tests.json",
       "device type": "iPhone 5s",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 5s",
       "os": "8.3"
     },
     {
diff --git a/ios/build/bots/chromium.mac/iOS_Device.json b/ios/build/bots/chromium.mac/iOS_Device.json
index 9994e52..283a859 100644
--- a/ios/build/bots/chromium.mac/iOS_Device.json
+++ b/ios/build/bots/chromium.mac/iOS_Device.json
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for 32-bit devices."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "arm32"
   },
   "compiler": "xcodebuild",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git "a/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json" "b/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
index 79e7f1c..5440881 100644
--- "a/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
+++ "b/ios/build/bots/chromium.mac/iOS_Device_\050ninja\051.json"
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for fat binaries using ninja."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "ninja",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git "a/ios/build/bots/chromium.mac/iOS_Simulator_\050dbg\051.json" "b/ios/build/bots/chromium.mac/iOS_Simulator_\050dbg\051.json"
index c11cbed..91d5028 100644
--- "a/ios/build/bots/chromium.mac/iOS_Simulator_\050dbg\051.json"
+++ "b/ios/build/bots/chromium.mac/iOS_Simulator_\050dbg\051.json"
@@ -3,20 +3,30 @@
     "smut"
   ],
   "comments": [
-    "Tests for 32- and 64-bit iOS 8.3 simulators."
+    "Tests for 32- and 64-bit iOS 9.0 simulators."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "xcodebuild",
   "configuration": "Debug",
-  "sdk": "iphonesimulator8.3",
+  "sdk": "iphonesimulator9.0",
   "tests": [
     {
       "include": "common_tests.json",
       "device type": "iPhone 5s",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 5s",
       "os": "8.3"
     },
     {
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator.json b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator.json
index c11cbed..91d5028 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator.json
@@ -3,20 +3,30 @@
     "smut"
   ],
   "comments": [
-    "Tests for 32- and 64-bit iOS 8.3 simulators."
+    "Tests for 32- and 64-bit iOS 9.0 simulators."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "xcodebuild",
   "configuration": "Debug",
-  "sdk": "iphonesimulator8.3",
+  "sdk": "iphonesimulator9.0",
   "tests": [
     {
       "include": "common_tests.json",
       "device type": "iPhone 5s",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 5s",
       "os": "8.3"
     },
     {
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
index 3db6c22..8f3e195 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_dbg_simulator_ninja.json
@@ -3,20 +3,30 @@
     "smut"
   ],
   "comments": [
-    "Tests for 32- and 64-bit iOS 8.3 simulators."
+    "Tests for 32- and 64-bit iOS 9.0 simulators."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "ninja",
   "configuration": "Debug",
-  "sdk": "iphonesimulator8.3",
+  "sdk": "iphonesimulator9.0",
   "tests": [
     {
       "include": "common_tests.json",
       "device type": "iPhone 5s",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPad Retina",
+      "os": "9.0"
+    },
+    {
+      "include": "common_tests.json",
+      "device type": "iPhone 5s",
       "os": "8.3"
     },
     {
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_rel_device.json b/ios/build/bots/tryserver.chromium.mac/ios_rel_device.json
index 9994e52..283a859 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_rel_device.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_rel_device.json
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for 32-bit devices."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "arm32"
   },
   "compiler": "xcodebuild",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git a/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json b/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
index 79e7f1c..5440881 100644
--- a/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
+++ b/ios/build/bots/tryserver.chromium.mac/ios_rel_device_ninja.json
@@ -5,14 +5,14 @@
   "comments": [
     "Builder for fat binaries using ninja."
   ],
-  "xcode version": "6.3",
+  "xcode version": "7.0",
   "GYP_DEFINES": {
     "chromium_ios_signing": "0",
     "target_subarch": "both"
   },
   "compiler": "ninja",
   "configuration": "Release",
-  "sdk": "iphoneos8.3",
+  "sdk": "iphoneos9.0",
   "tests": [
   ]
 }
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc
index a8401345..557064d 100644
--- a/ios/chrome/browser/chrome_url_constants.cc
+++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -4,6 +4,8 @@
 
 #include "ios/chrome/browser/chrome_url_constants.h"
 
+const char kChromeUINewTabURL[] = "chrome://newtab/";
+
 const char kChromeUIExternalFileHost[] = "external-file";
 const char kChromeUIOmahaHost[] = "omaha";
 const char kChromeUISyncInternalsHost[] = "sync-internals";
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h
index f6663fd6..6ed08b0 100644
--- a/ios/chrome/browser/chrome_url_constants.h
+++ b/ios/chrome/browser/chrome_url_constants.h
@@ -7,6 +7,14 @@
 #ifndef IOS_CHROME_BROWSER_CHROME_URL_CONSTANTS_H_
 #define IOS_CHROME_BROWSER_CHROME_URL_CONSTANTS_H_
 
+// TODO(blundell): This file should be ios_chrome_url_constants.*, and all of
+// these constants should have a kIOSChrome prefix instead of a kChrome
+// prefix. crbug.com/537174
+
+// chrome: URLs (including schemes). Should be kept in sync with the
+// components below.
+extern const char kChromeUINewTabURL[];
+
 // URL components for Chrome on iOS.
 extern const char kChromeUIExternalFileHost[];
 extern const char kChromeUIOmahaHost[];
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc
index 3cb1845..b6d5d1a 100644
--- a/ios/chrome/browser/pref_names.cc
+++ b/ios/chrome/browser/pref_names.cc
@@ -110,4 +110,9 @@
 const char kOmniboxGeolocationLastAuthorizationAlertVersion[] =
     "ios.omnibox.geolocation_last_authorization_alert_version";
 
+// Integer which contains the timestamp at which the "Rate This App" dialog was
+// last shown.
+const char kRateThisAppDialogLastShownTime[] =
+    "ios.ratethisapp.dialog_last_shown_time";
+
 }  // namespace prefs
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h
index 2fa445e..fdb52887 100644
--- a/ios/chrome/browser/pref_names.h
+++ b/ios/chrome/browser/pref_names.h
@@ -47,6 +47,8 @@
 extern const char kOmniboxGeolocationAuthorizationState[];
 extern const char kOmniboxGeolocationLastAuthorizationAlertVersion[];
 
+extern const char kRateThisAppDialogLastShownTime[];
+
 }  // namespace prefs
 
 #endif  // IOS_CHROME_BROWSER_PREF_NAMES_H_
diff --git a/ios/chrome/browser/prefs/browser_prefs.cc b/ios/chrome/browser/prefs/browser_prefs.cc
index e3aec57..d11003c 100644
--- a/ios/chrome/browser/prefs/browser_prefs.cc
+++ b/ios/chrome/browser/prefs/browser_prefs.cc
@@ -103,6 +103,8 @@
       ios::prefs::kDefaultCharset,
       l10n_util::GetStringUTF8(IDS_IOS_DEFAULT_ENCODING),
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+  registry->RegisterInt64Pref(prefs::kRateThisAppDialogLastShownTime, 0,
+                              user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 
   // TODO(sdefresne): those preferences are not used on iOS but are required to
   // be able to run unit_tests until componentization of chrome/browser/prefs
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.cc b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.cc
new file mode 100644
index 0000000..f3f42b05
--- /dev/null
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.cc
@@ -0,0 +1,83 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h"
+
+#include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#include "ios/public/provider/chrome/browser/sessions/live_tab_context_provider.h"
+#include "ios/web/public/web_thread.h"
+#include "url/gurl.h"
+
+IOSChromeTabRestoreServiceClient::IOSChromeTabRestoreServiceClient(
+    ios::ChromeBrowserState* browser_state)
+    : browser_state_(browser_state) {}
+
+IOSChromeTabRestoreServiceClient::~IOSChromeTabRestoreServiceClient() {}
+
+sessions::LiveTabContext*
+IOSChromeTabRestoreServiceClient::CreateLiveTabContext(
+    int host_desktop_type,
+    const std::string& app_name) {
+  return ios::GetChromeBrowserProvider()->GetLiveTabContextProvider()->Create(
+      browser_state_);
+}
+
+sessions::LiveTabContext*
+IOSChromeTabRestoreServiceClient::FindLiveTabContextForTab(
+    const sessions::LiveTab* tab) {
+  return ios::GetChromeBrowserProvider()
+      ->GetLiveTabContextProvider()
+      ->FindContextForTab(tab);
+}
+
+sessions::LiveTabContext*
+IOSChromeTabRestoreServiceClient::FindLiveTabContextWithID(
+    SessionID::id_type desired_id,
+    int host_desktop_type) {
+  return ios::GetChromeBrowserProvider()
+      ->GetLiveTabContextProvider()
+      ->FindContextWithID(desired_id);
+}
+
+bool IOSChromeTabRestoreServiceClient::ShouldTrackURLForRestore(
+    const GURL& url) {
+  // NOTE: In the //chrome client, chrome://quit and chrome://restart are
+  // blacklisted from being tracked to avoid entering infinite loops. However,
+  // iOS intentionally does not support those URLs, so there is no need to
+  // blacklist them here.
+  return url.is_valid();
+}
+
+std::string IOSChromeTabRestoreServiceClient::GetExtensionAppIDForTab(
+    sessions::LiveTab* tab) {
+  return std::string();
+}
+
+base::SequencedWorkerPool* IOSChromeTabRestoreServiceClient::GetBlockingPool() {
+  DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
+  return web::WebThread::GetBlockingPool();
+}
+
+base::FilePath IOSChromeTabRestoreServiceClient::GetPathToSaveTo() {
+  // Note that this will return a different path in incognito from normal mode.
+  // In this case, that shouldn't be an issue because the tab restore service
+  // is not used in incognito mode.
+  return browser_state_->GetStatePath();
+}
+
+GURL IOSChromeTabRestoreServiceClient::GetNewTabURL() {
+  return GURL(kChromeUINewTabURL);
+}
+
+bool IOSChromeTabRestoreServiceClient::HasLastSession() {
+  return false;
+}
+
+void IOSChromeTabRestoreServiceClient::GetLastSession(
+    const sessions::GetLastSessionCallback& callback,
+    base::CancelableTaskTracker* tracker) {
+  NOTREACHED();
+}
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
new file mode 100644
index 0000000..b2429b2
--- /dev/null
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
@@ -0,0 +1,48 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_CLIENT_H_
+#define IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_CLIENT_H_
+
+#include "base/macros.h"
+#include "components/sessions/core/tab_restore_service_client.h"
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// IOSChromeTabRestoreServiceClient provides an implementation of
+// TabRestoreServiceClient that depends on ios/chrome/.
+class IOSChromeTabRestoreServiceClient
+    : public sessions::TabRestoreServiceClient {
+ public:
+  explicit IOSChromeTabRestoreServiceClient(
+      ios::ChromeBrowserState* browser_state);
+  ~IOSChromeTabRestoreServiceClient() override;
+
+ private:
+  // TabRestoreServiceClient:
+  sessions::LiveTabContext* CreateLiveTabContext(
+      int host_desktop_type,
+      const std::string& app_name) override;
+  sessions::LiveTabContext* FindLiveTabContextForTab(
+      const sessions::LiveTab* tab) override;
+  sessions::LiveTabContext* FindLiveTabContextWithID(
+      SessionID::id_type desired_id,
+      int host_desktop_type) override;
+  bool ShouldTrackURLForRestore(const GURL& url) override;
+  std::string GetExtensionAppIDForTab(sessions::LiveTab* tab) override;
+  base::SequencedWorkerPool* GetBlockingPool() override;
+  base::FilePath GetPathToSaveTo() override;
+  GURL GetNewTabURL() override;
+  bool HasLastSession() override;
+  void GetLastSession(const sessions::GetLastSessionCallback& callback,
+                      base::CancelableTaskTracker* tracker) override;
+
+  ios::ChromeBrowserState* browser_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(IOSChromeTabRestoreServiceClient);
+};
+
+#endif  // IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_CLIENT_H_
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.cc b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.cc
new file mode 100644
index 0000000..2492391
--- /dev/null
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.cc
@@ -0,0 +1,62 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "components/sessions/core/persistent_tab_restore_service.h"
+#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h"
+#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h"
+
+namespace {
+
+scoped_ptr<KeyedService> BuildTabRestoreService(web::BrowserState* context) {
+  DCHECK(!context->IsOffTheRecord());
+
+  ios::ChromeBrowserState* browser_state =
+      ios::ChromeBrowserState::FromBrowserState(context);
+  return make_scoped_ptr(new sessions::PersistentTabRestoreService(
+      make_scoped_ptr(new IOSChromeTabRestoreServiceClient(browser_state)),
+      nullptr));
+}
+
+}  // namespace
+
+// static
+sessions::TabRestoreService*
+IOSChromeTabRestoreServiceFactory::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  return static_cast<sessions::TabRestoreService*>(
+      GetInstance()->GetServiceForBrowserState(browser_state, true));
+}
+
+// static
+IOSChromeTabRestoreServiceFactory*
+IOSChromeTabRestoreServiceFactory::GetInstance() {
+  return base::Singleton<IOSChromeTabRestoreServiceFactory>::get();
+}
+
+// static
+BrowserStateKeyedServiceFactory::TestingFactoryFunction
+IOSChromeTabRestoreServiceFactory::GetDefaultFactory() {
+  return &BuildTabRestoreService;
+}
+
+IOSChromeTabRestoreServiceFactory::IOSChromeTabRestoreServiceFactory()
+    : BrowserStateKeyedServiceFactory(
+          "TabRestoreService",
+          BrowserStateDependencyManager::GetInstance()) {}
+
+IOSChromeTabRestoreServiceFactory::~IOSChromeTabRestoreServiceFactory() {}
+
+bool IOSChromeTabRestoreServiceFactory::ServiceIsNULLWhileTesting() const {
+  return true;
+}
+
+scoped_ptr<KeyedService>
+IOSChromeTabRestoreServiceFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  return BuildTabRestoreService(context);
+}
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h
new file mode 100644
index 0000000..24463ed
--- /dev/null
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h
@@ -0,0 +1,52 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_FACTORY_H_
+#define IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_FACTORY_H_
+
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace sessions {
+class TabRestoreService;
+}
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// Singleton that owns all TabRestoreServices and associates them with
+// ChromeBrowserStates.
+class IOSChromeTabRestoreServiceFactory
+    : public BrowserStateKeyedServiceFactory {
+ public:
+  static sessions::TabRestoreService* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state);
+
+  static IOSChromeTabRestoreServiceFactory* GetInstance();
+
+  // Returns the default factory used to build TabRestoreService. Can be
+  // registered with SetTestingFactory to use the TabRestoreService instance
+  // during testing.
+  static TestingFactoryFunction GetDefaultFactory();
+
+ private:
+  friend struct base::DefaultSingletonTraits<IOSChromeTabRestoreServiceFactory>;
+
+  IOSChromeTabRestoreServiceFactory();
+  ~IOSChromeTabRestoreServiceFactory() override;
+
+  // BrowserStateKeyedServiceFactory:
+  scoped_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+  bool ServiceIsNULLWhileTesting() const override;
+
+  DISALLOW_COPY_AND_ASSIGN(IOSChromeTabRestoreServiceFactory);
+};
+
+#endif  // IOS_CHROME_BROWSER_SESSIONS_IOS_CHROME_TAB_RESTORE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h
index 7111bf2..7fbc770 100644
--- a/ios/chrome/browser/ui/commands/ios_command_ids.h
+++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -55,6 +55,7 @@
 #define IDC_CLOSE_SETTINGS                             40944
 #define IDC_SHOW_SAVE_PASSWORDS_SETTINGS               40945
 #define IDC_READER_MODE                                40947
+#define IDC_RATE_THIS_APP                              40948
 // Do not use IDs above 40999 while the iOS build still depends on //chrome, to
 // avoid conflicts.
 // TODO(droger): Remove this comment once iOS no longer depends on //chrome.
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index 8cb49594..3e18a40 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -334,6 +334,10 @@
         'browser/search_engines/ui_thread_search_terms_data.h',
         'browser/sessions/ios_chrome_session_tab_helper.cc',
         'browser/sessions/ios_chrome_session_tab_helper.h',
+        'browser/sessions/ios_chrome_tab_restore_service_client.cc',
+        'browser/sessions/ios_chrome_tab_restore_service_client.h',
+        'browser/sessions/ios_chrome_tab_restore_service_factory.cc',
+        'browser/sessions/ios_chrome_tab_restore_service_factory.h',
         'browser/signin/about_signin_internals_factory.cc',
         'browser/signin/about_signin_internals_factory.h',
         'browser/signin/account_consistency_service_factory.h',
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.cc b/ios/public/provider/chrome/browser/chrome_browser_provider.cc
index 9f109a6..f46f388 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.cc
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.cc
@@ -76,6 +76,10 @@
   return nullptr;
 }
 
+LiveTabContextProvider* ChromeBrowserProvider::GetLiveTabContextProvider() {
+  return nullptr;
+}
+
 GeolocationUpdaterProvider*
 ChromeBrowserProvider::GetGeolocationUpdaterProvider() {
   return nullptr;
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h
index d120a5f..427cace10 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.h
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -58,6 +58,7 @@
 class ChromeIdentityService;
 class GeolocationUpdaterProvider;
 class StringProvider;
+class LiveTabContextProvider;
 class UpdatableResourceProvider;
 
 // Setter and getter for the provider. The provider should be set early, before
@@ -100,6 +101,8 @@
   virtual ChromeIdentityService* GetChromeIdentityService();
   // Returns an instance of a string provider.
   virtual StringProvider* GetStringProvider();
+  // Returns an instance of a LiveTabContextProvider.
+  virtual LiveTabContextProvider* GetLiveTabContextProvider();
   virtual GeolocationUpdaterProvider* GetGeolocationUpdaterProvider();
   // Returns the distribution brand code.
   virtual std::string GetDistributionBrandCode();
diff --git a/ios/public/provider/chrome/browser/sessions/live_tab_context_provider.h b/ios/public/provider/chrome/browser/sessions/live_tab_context_provider.h
new file mode 100644
index 0000000..7c1436f
--- /dev/null
+++ b/ios/public/provider/chrome/browser/sessions/live_tab_context_provider.h
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_PROVIDER_H_
+#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_PROVIDER_H_
+
+#include "base/basictypes.h"
+
+namespace sessions {
+class LiveTab;
+class LiveTabContext;
+}
+
+namespace ios {
+
+class ChromeBrowserState;
+
+// A class that allows retrieving a sessions::LiveTabContext.
+class LiveTabContextProvider {
+ public:
+  virtual ~LiveTabContextProvider() {}
+
+  // Creates a new context.
+  virtual sessions::LiveTabContext* Create(
+      ios::ChromeBrowserState* browser_state) = 0;
+
+  // Retrieves the context with the given ID, if one exists.
+  virtual sessions::LiveTabContext* FindContextWithID(int32 desired_id) = 0;
+
+  // Retrieves the context for the given tab, if one exists.
+  virtual sessions::LiveTabContext* FindContextForTab(
+      const sessions::LiveTab* tab) = 0;
+};
+
+}  // namespace ios
+
+#endif  // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_PROVIDER_H_
diff --git a/ios/web/interstitials/html_web_interstitial_impl.h b/ios/web/interstitials/html_web_interstitial_impl.h
index 8e469a9..f482f6e 100644
--- a/ios/web/interstitials/html_web_interstitial_impl.h
+++ b/ios/web/interstitials/html_web_interstitial_impl.h
@@ -24,6 +24,7 @@
 class HtmlWebInterstitialImpl : public WebInterstitialImpl {
  public:
   HtmlWebInterstitialImpl(WebStateImpl* web_state,
+                          bool new_navigation,
                           const GURL& url,
                           scoped_ptr<HtmlWebInterstitialDelegate> delegate);
   ~HtmlWebInterstitialImpl() override;
diff --git a/ios/web/interstitials/html_web_interstitial_impl.mm b/ios/web/interstitials/html_web_interstitial_impl.mm
index 77fe8cac..98439fe 100644
--- a/ios/web/interstitials/html_web_interstitial_impl.mm
+++ b/ios/web/interstitials/html_web_interstitial_impl.mm
@@ -62,17 +62,21 @@
 // static
 WebInterstitial* WebInterstitial::CreateHtmlInterstitial(
     WebState* web_state,
+    bool new_navigation,
     const GURL& url,
     scoped_ptr<HtmlWebInterstitialDelegate> delegate) {
   WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state);
-  return new HtmlWebInterstitialImpl(web_state_impl, url, delegate.Pass());
+  return new HtmlWebInterstitialImpl(web_state_impl, new_navigation, url,
+                                     delegate.Pass());
 }
 
 HtmlWebInterstitialImpl::HtmlWebInterstitialImpl(
     WebStateImpl* web_state,
+    bool new_navigation,
     const GURL& url,
     scoped_ptr<HtmlWebInterstitialDelegate> delegate)
-    : WebInterstitialImpl(web_state, url), delegate_(delegate.Pass()) {
+    : WebInterstitialImpl(web_state, new_navigation, url),
+      delegate_(delegate.Pass()) {
   DCHECK(delegate_);
 }
 
diff --git a/ios/web/interstitials/native_web_interstitial_impl.h b/ios/web/interstitials/native_web_interstitial_impl.h
index 5957ea9..1280ef49 100644
--- a/ios/web/interstitials/native_web_interstitial_impl.h
+++ b/ios/web/interstitials/native_web_interstitial_impl.h
@@ -19,6 +19,7 @@
 class NativeWebInterstitialImpl : public WebInterstitialImpl {
  public:
   NativeWebInterstitialImpl(WebStateImpl* web_state,
+                            bool new_navigation,
                             const GURL& url,
                             scoped_ptr<NativeWebInterstitialDelegate> delegate);
   ~NativeWebInterstitialImpl() override;
diff --git a/ios/web/interstitials/native_web_interstitial_impl.mm b/ios/web/interstitials/native_web_interstitial_impl.mm
index 1a86b23..ea76b30 100644
--- a/ios/web/interstitials/native_web_interstitial_impl.mm
+++ b/ios/web/interstitials/native_web_interstitial_impl.mm
@@ -15,17 +15,21 @@
 // static
 WebInterstitial* WebInterstitial::CreateNativeInterstitial(
     WebState* web_state,
+    bool new_navigation,
     const GURL& url,
     scoped_ptr<NativeWebInterstitialDelegate> delegate) {
   WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state);
-  return new NativeWebInterstitialImpl(web_state_impl, url, delegate.Pass());
+  return new NativeWebInterstitialImpl(web_state_impl, new_navigation, url,
+                                       delegate.Pass());
 }
 
 NativeWebInterstitialImpl::NativeWebInterstitialImpl(
     WebStateImpl* web_state,
+    bool new_navigation,
     const GURL& url,
     scoped_ptr<NativeWebInterstitialDelegate> delegate)
-    : web::WebInterstitialImpl(web_state, url), delegate_(delegate.Pass()) {
+    : web::WebInterstitialImpl(web_state, new_navigation, url),
+      delegate_(delegate.Pass()) {
   DCHECK(delegate_);
 }
 
diff --git a/ios/web/interstitials/web_interstitial_impl.h b/ios/web/interstitials/web_interstitial_impl.h
index c1826ca..8124662 100644
--- a/ios/web/interstitials/web_interstitial_impl.h
+++ b/ios/web/interstitials/web_interstitial_impl.h
@@ -15,6 +15,7 @@
 
 namespace web {
 
+class NavigationManagerImpl;
 class WebInterstitialDelegate;
 class WebInterstitialFacadeDelegate;
 class WebInterstitialImpl;
@@ -30,7 +31,9 @@
 // embed the interstitial into a WebState.
 class WebInterstitialImpl : public WebInterstitial, public WebStateObserver {
  public:
-  WebInterstitialImpl(WebStateImpl* web_state, const GURL& url);
+  WebInterstitialImpl(WebStateImpl* web_state,
+                      bool new_navigation,
+                      const GURL& url);
   ~WebInterstitialImpl() override;
 
   // Returns the transient content view used to display interstitial content.
@@ -71,10 +74,15 @@
                                   JavaScriptCompletion completionHandler) = 0;
 
  private:
+  // The navigation manager corresponding to the WebState the interstiatial was
+  // created for.
+  NavigationManagerImpl* navigation_manager_;
   // The URL corresponding to the page that resulted in this interstitial.
   GURL url_;
   // The delegate used to communicate with the InterstitialPageImplsIOS facade.
   WebInterstitialFacadeDelegate* facade_delegate_;
+  // Whether or not to create a new transient entry on display.
+  bool new_navigation_;
   // Whether or not either Proceed() or DontProceed() has been called.
   bool action_taken_;
 
diff --git a/ios/web/interstitials/web_interstitial_impl.mm b/ios/web/interstitials/web_interstitial_impl.mm
index b40a1895..33f22e87 100644
--- a/ios/web/interstitials/web_interstitial_impl.mm
+++ b/ios/web/interstitials/web_interstitial_impl.mm
@@ -6,7 +6,10 @@
 
 #include "base/logging.h"
 #include "ios/web/interstitials/web_interstitial_facade_delegate.h"
+#include "ios/web/navigation/crw_session_controller.h"
+#include "ios/web/navigation/navigation_manager_impl.h"
 #include "ios/web/public/interstitials/web_interstitial_delegate.h"
+#include "ios/web/public/navigation_manager.h"
 #include "ios/web/web_state/web_state_impl.h"
 
 namespace web {
@@ -17,10 +20,13 @@
 }
 
 WebInterstitialImpl::WebInterstitialImpl(WebStateImpl* web_state,
+                                         bool new_navigation,
                                          const GURL& url)
     : WebStateObserver(web_state),
+      navigation_manager_(&web_state->GetNavigationManagerImpl()),
       url_(url),
       facade_delegate_(nullptr),
+      new_navigation_(new_navigation),
       action_taken_(false) {
   DCHECK(web_state);
 }
@@ -47,6 +53,15 @@
 void WebInterstitialImpl::Show() {
   PrepareForDisplay();
   GetWebStateImpl()->ShowWebInterstitial(this);
+
+  if (new_navigation_) {
+    // TODO(stuartmorgan): Plumb transient entry handling through
+    // NavigationManager, and remove the NavigationManagerImpl and
+    // SessionController usage here.
+    CRWSessionController* sessionController =
+        navigation_manager_->GetSessionController();
+    [sessionController addTransientEntryWithURL:url_];
+  }
 }
 
 void WebInterstitialImpl::Hide() {
@@ -58,8 +73,13 @@
   if (action_taken_)
     return;
   action_taken_ = true;
+
+  // Clear the pending entry, since that's the page that's not being
+  // proceeded to.
+  GetWebStateImpl()->GetNavigationManager()->DiscardNonCommittedItems();
+
   Hide();
-  // Clean up unsafe nav items.
+
   GetDelegate()->OnDontProceed();
   delete this;
 }
diff --git a/ios/web/navigation/crw_session_controller.h b/ios/web/navigation/crw_session_controller.h
index 5e0d583..84d6012 100644
--- a/ios/web/navigation/crw_session_controller.h
+++ b/ios/web/navigation/crw_session_controller.h
@@ -81,14 +81,11 @@
 // TODO(pinkerton): Desktop Chrome broadcasts a notification here, should we?
 - (void)commitPendingEntry;
 
-// Adds a transient entry with the given information. A transient entry will be
+// Adds a transient entry with the given URL. A transient entry will be
 // discarded on any navigation.
 // TODO(stuartmorgan): Make this work more like upstream, where the entry can
-// be made from outside and then handed in, instead of having to pass a bunch
-// of construction params here.
-- (void)addTransientEntry:(const GURL&)url
-                    title:(const base::string16&)title
-                sslStatus:(const web::SSLStatus*)status;
+// be made from outside and then handed in.
+- (void)addTransientEntryWithURL:(const GURL&)URL;
 
 // Creates a new CRWSessionEntry with the given URL and state object. A state
 // object is a serialized generic JavaScript object that contains details of the
diff --git a/ios/web/navigation/crw_session_controller.mm b/ios/web/navigation/crw_session_controller.mm
index f5c1c3c..5e270b0 100644
--- a/ios/web/navigation/crw_session_controller.mm
+++ b/ios/web/navigation/crw_session_controller.mm
@@ -308,15 +308,11 @@
   return [NSString
       stringWithFormat:
           @"id: %@\nname: %@\nlast visit: %f\ncurrent index: %" PRIdNS
-          @"\nprevious index: %" PRIdNS "\n%@\npending: %@\nxCallback:\n%@\n",
-          _tabId,
-          self.windowName,
-          _lastVisitedTimestamp,
-          _currentNavigationIndex,
-          _previousNavigationIndex,
-          _entries,
-          _pendingEntry.get(),
-          _xCallbackParameters];
+          @"\nprevious index: %" PRIdNS "\n%@\npending: %@\ntransient: %@\n"
+          @"xCallback:\n%@\n",
+          _tabId, self.windowName, _lastVisitedTimestamp,
+          _currentNavigationIndex, _previousNavigationIndex, _entries,
+          _pendingEntry.get(), _transientEntry.get(), _xCallbackParameters];
 }
 
 // Returns the current entry in the session list, or the pending entry if there
@@ -424,8 +420,6 @@
 }
 
 - (void)updatePendingEntry:(const GURL&)url {
-  [self discardTransientEntry];
-
   // If there is no pending entry, navigation is probably happening within the
   // session history. Don't modify the entry list.
   if (!_pendingEntry)
@@ -433,6 +427,11 @@
 
   web::NavigationItemImpl* item = [_pendingEntry navigationItemImpl];
   if (url != item->GetURL()) {
+    // Assume a redirection, and discard any transient entry.
+    // TODO(stuartmorgan): Once the current safe browsing code is gone,
+    // consider making this a DCHECK that there's no transient entry.
+    [self discardTransientEntry];
+
     item->SetURL(url);
     item->SetVirtualURL(url);
     // Redirects (3xx response code), or client side navigation must change
@@ -495,18 +494,9 @@
     _navigationManager->OnNavigationItemCommitted();
 }
 
-- (void)addTransientEntry:(const GURL&)url
-                    title:(const base::string16&)title
-                sslStatus:(const web::SSLStatus*)status {
-  // TODO(stuartmorgan): Don't do this; this is here only to preserve the old
-  // behavior from when transient entries were faked with pending entries, so
-  // any actual pending entry had to be committed. This shouldn't be necessary
-  // now, but things may rely on the old behavior and need to be fixed
-  // (crbug.com/524491).
-  [self commitPendingEntry];
-
+- (void)addTransientEntryWithURL:(const GURL&)URL {
   _transientEntry.reset(
-      [[self sessionEntryWithURL:url
+      [[self sessionEntryWithURL:URL
                         referrer:web::Referrer()
                       transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT
              useDesktopUserAgent:NO
@@ -514,17 +504,8 @@
 
   web::NavigationItem* navigationItem = [_transientEntry navigationItem];
   DCHECK(navigationItem);
-  if (status)
-    navigationItem->GetSSL() = *status;
-  navigationItem->SetTitle(title);
   navigationItem->SetTimestamp(
       _timeSmoother.GetSmoothedTime(base::Time::Now()));
-
-  // This doesn't match upstream, but matches what we've traditionally done and
-  // will hopefully continue to be good enough for as long as we need the
-  // facade.
-  if (_navigationManager)
-    _navigationManager->OnNavigationItemChanged();
 }
 
 - (void)pushNewEntryWithURL:(const GURL&)URL
@@ -647,6 +628,12 @@
   if ([_entries count] == 0)
     return NO;
 
+  // A transient entry behaves from a user perspective in most ways like a
+  // committed entry, so allow going back from a transient entry as long as
+  // there is something to go back to.
+  if (_transientEntry && [_entries count] > 0)
+    return YES;
+
   NSInteger lastNonRedirectedIndex = _currentNavigationIndex;
   while (lastNonRedirectedIndex >= 0 &&
          ui::PageTransitionIsRedirect(
@@ -672,7 +659,14 @@
   if (![self canGoBack])
     return;
 
-  [self discardTransientEntry];
+  BOOL hadTransientEntry = _transientEntry != nil;
+
+  [self discardNonCommittedEntries];
+
+  // Going back from a transient entry doesn't require anything beyond
+  // discarding the pending entry.
+  if (hadTransientEntry)
+    return;
 
   web::RecordAction(UserMetricsAction("Back"));
   _previousNavigationIndex = _currentNavigationIndex;
diff --git a/ios/web/public/interstitials/web_interstitial.h b/ios/web/public/interstitials/web_interstitial.h
index 8a573c3a1..35ba5d9 100644
--- a/ios/web/public/interstitials/web_interstitial.h
+++ b/ios/web/public/interstitials/web_interstitial.h
@@ -34,10 +34,12 @@
   // manage their own deletion after calling |Show()|.
   static WebInterstitial* CreateHtmlInterstitial(
       WebState* web_state,
+      bool new_navigation,
       const GURL& url,
       scoped_ptr<HtmlWebInterstitialDelegate> delegate);
   static WebInterstitial* CreateNativeInterstitial(
       WebState* web_state,
+      bool new_navigation,
       const GURL& url,
       scoped_ptr<NativeWebInterstitialDelegate> delegate);
 
diff --git a/ios/web/shell/shell_url_request_context_getter.cc b/ios/web/shell/shell_url_request_context_getter.cc
index bca712c..8de48364 100644
--- a/ios/web/shell/shell_url_request_context_getter.cc
+++ b/ios/web/shell/shell_url_request_context_getter.cc
@@ -83,10 +83,8 @@
     net::CookieStoreIOS::SwitchSynchronizedStore(nullptr, cookie_store.get());
 
     std::string user_agent = web::GetWebClient()->GetUserAgent(false);
-    storage_->set_http_user_agent_settings(
-        make_scoped_ptr(
-            new net::StaticHttpUserAgentSettings("en-us,en", user_agent))
-            .Pass());
+    storage_->set_http_user_agent_settings(make_scoped_ptr(
+        new net::StaticHttpUserAgentSettings("en-us,en", user_agent)));
     storage_->set_proxy_service(
         net::ProxyService::CreateUsingSystemProxyResolver(
             proxy_config_service_.Pass(), 0, url_request_context_->net_log()));
@@ -137,10 +135,8 @@
                                            net::CACHE_BACKEND_DEFAULT,
                                            cache_path, 0, cache_task_runner_);
 
-    storage_->set_http_transaction_factory(
-        make_scoped_ptr(
-            new net::HttpCache(network_session_params, main_backend))
-            .Pass());
+    storage_->set_http_transaction_factory(make_scoped_ptr(
+        new net::HttpCache(network_session_params, main_backend)));
 
     scoped_ptr<net::URLRequestJobFactoryImpl> job_factory(
         new net::URLRequestJobFactoryImpl());
diff --git a/ios/web/shell/view_controller.mm b/ios/web/shell/view_controller.mm
index c15bf1cd..39fc2eff 100644
--- a/ios/web/shell/view_controller.mm
+++ b/ios/web/shell/view_controller.mm
@@ -293,11 +293,31 @@
 - (BOOL)openExternalURL:(const GURL&)url {
   return NO;
 }
+
 - (void)presentSSLError:(const net::SSLInfo&)info
            forSSLStatus:(const web::SSLStatus&)status
             recoverable:(BOOL)recoverable
                callback:(SSLErrorCallback)shouldContinue {
+  UIAlertController* alert = [UIAlertController
+      alertControllerWithTitle:@"Your connection is not private"
+                       message:nil
+                preferredStyle:UIAlertControllerStyleActionSheet];
+  [alert addAction:[UIAlertAction actionWithTitle:@"Go Back"
+                                            style:UIAlertActionStyleCancel
+                                          handler:^(UIAlertAction*) {
+                                            shouldContinue(NO);
+                                          }]];
+
+  if (recoverable) {
+    [alert addAction:[UIAlertAction actionWithTitle:@"Continue"
+                                              style:UIAlertActionStyleDefault
+                                            handler:^(UIAlertAction*) {
+                                              shouldContinue(YES);
+                                            }]];
+  }
+  [self presentViewController:alert animated:YES completion:nil];
 }
+
 - (void)presentSpoofingError {
 }
 - (void)webLoadCancelled:(const GURL&)url {
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index d95db1da..c06ee2e 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1605,10 +1605,23 @@
   _lastUserInteraction.reset();
   web::RecordAction(UserMetricsAction("Reload"));
   if (self.webView) {
-    // Just as we don't use the WebView native back and forward navigation
-    // (preferring to load the URLs manually) we don't use the native reload.
-    // This ensures state processing and delegate calls are consistent.
-    [self loadCurrentURL];
+    web::NavigationItem* transientItem =
+        _webStateImpl->GetNavigationManagerImpl().GetTransientItem();
+    if (transientItem) {
+      // If there's a transient item, a reload is considered a new navigation to
+      // the transient item's URL (as on other platforms).
+      web::WebLoadParams reloadParams(transientItem->GetURL());
+      reloadParams.transition_type = ui::PAGE_TRANSITION_RELOAD;
+      reloadParams.extra_headers.reset(
+          [transientItem->GetHttpRequestHeaders() copy]);
+      [self loadWithParams:reloadParams];
+    } else {
+      // As with back and forward navigation, load the URL manually instead of
+      // using the web view's reload. This ensures state processing and delegate
+      // calls are consistent.
+      // TODO(eugenebut): revisit this for WKWebView.
+      [self loadCurrentURL];
+    }
   } else {
     [self.nativeController reload];
   }
@@ -1665,11 +1678,6 @@
     [self injectEarlyInjectionScripts];
     [self checkForUnexpectedURLChange];
   }
-  // Discard any outstanding pending entries before adjusting the navigation
-  // index.
-  CRWSessionController* sessionController =
-      _webStateImpl->GetNavigationManagerImpl().GetSessionController();
-  [sessionController discardNonCommittedEntries];
 
   bool wasShowingInterstitial = _webStateImpl->IsShowingWebInterstitial();
 
diff --git a/ios/web/web_state/ui/crw_wk_simple_web_view_controller.mm b/ios/web/web_state/ui/crw_wk_simple_web_view_controller.mm
index fa4412b..065555c2 100644
--- a/ios/web/web_state/ui/crw_wk_simple_web_view_controller.mm
+++ b/ios/web/web_state/ui/crw_wk_simple_web_view_controller.mm
@@ -4,6 +4,7 @@
 
 #import "ios/web/web_state/ui/crw_wk_simple_web_view_controller.h"
 
+#include "base/ios/ios_util.h"
 #include "base/ios/weak_nsobject.h"
 #include "base/logging.h"
 #import "base/mac/scoped_nsobject.h"
@@ -62,10 +63,15 @@
 }
 
 - (void)loadPDFAtFilePath:(NSString*)filePath {
+  if (!base::ios::IsRunningOnIOS9OrLater()) {
+    // WKWebView on iOS 8 can't load local files, so just bail.
+    NOTIMPLEMENTED();
+    return;
+  }
   DCHECK([[NSFileManager defaultManager] fileExistsAtPath:filePath]);
-  NSURLRequest* request =
-      [NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]];
-  [_webView loadRequest:request];
+  NSURL* fileURL = [NSURL fileURLWithPath:filePath];
+  DCHECK(fileURL);
+  [_webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
 }
 
 - (void)setDelegate:(id<CRWSimpleWebViewControllerDelegate>)delegate {
diff --git a/ios/web/web_state/web_state_facade_delegate.h b/ios/web/web_state/web_state_facade_delegate.h
index cf407d7..d88177f 100644
--- a/ios/web/web_state/web_state_facade_delegate.h
+++ b/ios/web/web_state/web_state_facade_delegate.h
@@ -28,8 +28,6 @@
   WebStateFacadeDelegate() {}
   virtual ~WebStateFacadeDelegate() {}
 
-  // Sets the WebStateImpl that backs the WebContents facade.
-  virtual void SetWebState(WebStateImpl* web_state) = 0;
   // Returns the facade object being driven by this delegate.
   virtual content::WebContents* GetWebContentsFacade() = 0;
 
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 2071eae..39c58d95 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -351,19 +351,6 @@
 
 void WebStateImpl::ClearTransientContentView() {
   if (interstitial_) {
-    CRWSessionController* sessionController =
-        navigation_manager_.GetSessionController();
-    web::NavigationItem* currentItem =
-        [sessionController.currentEntry navigationItem];
-    if (currentItem->IsUnsafe()) {
-      // The unsafe page or page with bad SSL cert should be removed from the
-      // history, and, in fact, Safe Browsing and SSL interstitials will do
-      // just that *provided* that it isn't the current page.
-      // So to make this happen, before removing the interstitial, have the
-      // session controller go back one page.
-      [sessionController goBack];
-    }
-    [sessionController discardNonCommittedEntries];
     // Store the currently displayed interstitial in a local variable and reset
     // |interstitial_| early.  This is to prevent an infinite loop, as
     // |DontProceed()| internally calls |ClearTransientContentView()|.
diff --git a/ipc/attachment_broker.cc b/ipc/attachment_broker.cc
index 7e04bcd..362fc1f 100644
--- a/ipc/attachment_broker.cc
+++ b/ipc/attachment_broker.cc
@@ -14,7 +14,10 @@
 
 // static
 void AttachmentBroker::SetGlobal(AttachmentBroker* broker) {
-  CHECK(!g_attachment_broker);
+  // TODO(erikchen): There should be a CHECK here to make sure that
+  // |g_attachment_broker| is nullptr. Right now, this causes problems with
+  // --single_process and similar testing conditions. I'm temporarily removing
+  // this CHECK. http://crbug.com/534539.
   g_attachment_broker = broker;
 }
 
diff --git a/ipc/ipc_channel_reader.cc b/ipc/ipc_channel_reader.cc
index 031417b0..5ca0e46 100644
--- a/ipc/ipc_channel_reader.cc
+++ b/ipc/ipc_channel_reader.cc
@@ -78,17 +78,15 @@
     p = input_data;
     end = input_data + input_data_len;
   } else {
-    if (input_overflow_buf_.size() + input_data_len >
-        Channel::kMaximumMessageSize) {
-      input_overflow_buf_.clear();
-      LOG(ERROR) << "IPC message is too big";
+    if (!CheckMessageSize(input_overflow_buf_.size() + input_data_len))
       return false;
-    }
     input_overflow_buf_.append(input_data, input_data_len);
     p = input_overflow_buf_.data();
     end = p + input_overflow_buf_.size();
   }
 
+  size_t next_message_size = 0;
+
   // Dispatch all complete messages in the data buffer.
   while (p < end) {
     Message::NextMessageInfo info;
@@ -127,6 +125,9 @@
       p = info.message_end;
     } else {
       // Last message is partial.
+      next_message_size = info.message_size;
+      if (!CheckMessageSize(next_message_size))
+        return false;
       break;
     }
   }
@@ -134,6 +135,17 @@
   // Save any partial data in the overflow buffer.
   input_overflow_buf_.assign(p, end - p);
 
+  if (!input_overflow_buf_.empty()) {
+    // We have something in the overflow buffer, which means that we will
+    // append the next data chunk (instead of parsing it directly). So we
+    // resize the buffer to fit the next message, to avoid repeatedly
+    // growing the buffer as we receive all message' data chunks.
+    next_message_size += Channel::kReadBufferSize - 1;
+    if (next_message_size > input_overflow_buf_.capacity()) {
+      input_overflow_buf_.reserve(next_message_size);
+    }
+  }
+
   if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
     return false;
   return true;
@@ -249,5 +261,14 @@
 #endif  // USE_ATTACHMENT_BROKER
 }
 
+bool ChannelReader::CheckMessageSize(size_t size) {
+  if (size <= Channel::kMaximumMessageSize) {
+    return true;
+  }
+  input_overflow_buf_.clear();
+  LOG(ERROR) << "IPC message is too big: " << size;
+  return false;
+}
+
 }  // namespace internal
 }  // namespace IPC
diff --git a/ipc/ipc_channel_reader.h b/ipc/ipc_channel_reader.h
index 3f3fc4579..4677522 100644
--- a/ipc/ipc_channel_reader.h
+++ b/ipc/ipc_channel_reader.h
@@ -127,6 +127,8 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, AttachmentAlreadyBrokered);
   FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, AttachmentNotYetBrokered);
+  FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, ResizeOverflowBuffer);
+  FRIEND_TEST_ALL_PREFIXES(ChannelReaderTest, InvalidMessageSize);
 
   typedef std::set<BrokerableAttachment::AttachmentId> AttachmentIdSet;
 
@@ -156,6 +158,9 @@
   void StartObservingAttachmentBroker();
   void StopObservingAttachmentBroker();
 
+  // Checks that |size| is a valid message size. Has side effects if it's not.
+  bool CheckMessageSize(size_t size);
+
   Listener* listener_;
 
   // We read from the pipe into this buffer. Managed by DispatchInputData, do
diff --git a/ipc/ipc_channel_reader_unittest.cc b/ipc/ipc_channel_reader_unittest.cc
index 00589801..7728a817 100644
--- a/ipc/ipc_channel_reader_unittest.cc
+++ b/ipc/ipc_channel_reader_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "build/build_config.h"
 
+#include <limits>
 #include <set>
 
 #include "ipc/attachment_broker.h"
@@ -12,12 +13,13 @@
 #include "ipc/placeholder_brokerable_attachment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if USE_ATTACHMENT_BROKER
 namespace IPC {
 namespace internal {
 
 namespace {
 
+#if USE_ATTACHMENT_BROKER
+
 class MockAttachment : public BrokerableAttachment {
  public:
   MockAttachment() {}
@@ -53,6 +55,8 @@
   }
 };
 
+#endif  // USE_ATTACHMENT_BROKER
+
 class MockChannelReader : public ChannelReader {
  public:
   MockChannelReader()
@@ -92,8 +96,16 @@
   AttachmentBroker* broker_;
 };
 
+class ExposedMessage: public Message {
+ public:
+  using Message::Header;
+  using Message::header;
+};
+
 }  // namespace
 
+#if USE_ATTACHMENT_BROKER
+
 TEST(ChannelReaderTest, AttachmentAlreadyBrokered) {
   MockAttachmentBroker broker;
   MockChannelReader reader;
@@ -129,6 +141,55 @@
   EXPECT_EQ(m, reader.get_last_dispatched_message());
 }
 
+#endif  // USE_ATTACHMENT_BROKER
+
+#if !USE_ATTACHMENT_BROKER
+
+// We can determine message size from its header (and hence resize the buffer)
+// only when attachment broker is not used, see IPC::Message::FindNext().
+
+TEST(ChannelReaderTest, ResizeOverflowBuffer) {
+  MockChannelReader reader;
+
+  ExposedMessage::Header header = {};
+
+  header.payload_size = 128 * 1024;
+  EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size);
+  EXPECT_TRUE(reader.TranslateInputData(
+      reinterpret_cast<const char*>(&header), sizeof(header)));
+
+  // Once message header is available we resize overflow buffer to
+  // fit the entire message.
+  EXPECT_GE(reader.input_overflow_buf_.capacity(), header.payload_size);
+}
+
+TEST(ChannelReaderTest, InvalidMessageSize) {
+  MockChannelReader reader;
+
+  ExposedMessage::Header header = {};
+
+  size_t capacity_before = reader.input_overflow_buf_.capacity();
+
+  // Message is slightly larger than maximum allowed size
+  header.payload_size = Channel::kMaximumMessageSize + 1;
+  EXPECT_FALSE(reader.TranslateInputData(
+      reinterpret_cast<const char*>(&header), sizeof(header)));
+  EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
+
+  // Payload size is negative, overflow is detected by Pickle::PeekNext()
+  header.payload_size = static_cast<uint32_t>(-1);
+  EXPECT_FALSE(reader.TranslateInputData(
+      reinterpret_cast<const char*>(&header), sizeof(header)));
+  EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
+
+  // Payload size is maximum int32 value
+  header.payload_size = std::numeric_limits<int32_t>::max();
+  EXPECT_FALSE(reader.TranslateInputData(
+      reinterpret_cast<const char*>(&header), sizeof(header)));
+  EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
+}
+
+#endif  // !USE_ATTACHMENT_BROKER
+
 }  // namespace internal
 }  // namespace IPC
-#endif  // USE_ATTACHMENT_BROKER
diff --git a/ipc/ipc_message.cc b/ipc/ipc_message.cc
index df7a7239..df28464e 100644
--- a/ipc/ipc_message.cc
+++ b/ipc/ipc_message.cc
@@ -49,6 +49,9 @@
 Message::Message() : base::Pickle(sizeof(Header)) {
   header()->routing = header()->type = 0;
   header()->flags = GetRefNumUpper24();
+#if defined(OS_MACOSX)
+  header()->num_brokered_attachments = 0;
+#endif
 #if defined(OS_POSIX)
   header()->num_fds = 0;
   header()->pad = 0;
@@ -62,6 +65,9 @@
   header()->type = type;
   DCHECK((priority & 0xffffff00) == 0);
   header()->flags = priority | GetRefNumUpper24();
+#if defined(OS_MACOSX)
+  header()->num_brokered_attachments = 0;
+#endif
 #if defined(OS_POSIX)
   header()->num_fds = 0;
   header()->pad = 0;
@@ -131,7 +137,8 @@
 #endif
 
 Message::NextMessageInfo::NextMessageInfo()
-    : message_found(false), pickle_end(nullptr), message_end(nullptr) {}
+    : message_size(0), message_found(false), pickle_end(nullptr),
+      message_end(nullptr) {}
 Message::NextMessageInfo::~NextMessageInfo() {}
 
 Message::SerializedAttachmentIds
@@ -160,17 +167,28 @@
                        const char* range_end,
                        NextMessageInfo* info) {
   DCHECK(info);
-  const char* pickle_end =
-      base::Pickle::FindNext(sizeof(Header), range_start, range_end);
-  if (!pickle_end)
+  info->message_found = false;
+  info->message_size = 0;
+
+  size_t pickle_size = 0;
+  if (!base::Pickle::PeekNext(sizeof(Header),
+                              range_start, range_end, &pickle_size))
     return;
-  info->pickle_end = pickle_end;
+
+  bool have_entire_pickle =
+      static_cast<size_t>(range_end - range_start) >= pickle_size;
 
 #if USE_ATTACHMENT_BROKER
+  // TODO(dskiba): determine message_size when entire pickle is not available
+
+  if (!have_entire_pickle)
+    return;
+
+  const char* pickle_end = range_start + pickle_size;
+
   // The data is not copied.
-  size_t pickle_len = static_cast<size_t>(pickle_end - range_start);
-  Message message(range_start, static_cast<int>(pickle_len));
-  int num_attachments = message.header()->num_brokered_attachments;
+  Message message(range_start, static_cast<int>(pickle_size));
+  size_t num_attachments = message.header()->num_brokered_attachments;
 
   // Check for possible overflows.
   size_t max_size_t = std::numeric_limits<size_t>::max();
@@ -178,12 +196,12 @@
     return;
 
   size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
-  if (pickle_len > max_size_t - attachment_length)
+  if (pickle_size > max_size_t - attachment_length)
     return;
 
   // Check whether the range includes the attachments.
   size_t buffer_length = static_cast<size_t>(range_end - range_start);
-  if (buffer_length < attachment_length + pickle_len)
+  if (buffer_length < attachment_length + pickle_size)
     return;
 
   for (int i = 0; i < num_attachments; ++i) {
@@ -195,10 +213,19 @@
   }
   info->message_end =
       pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
+  info->message_size = info->message_end - range_start;
 #else
+  info->message_size = pickle_size;
+
+  if (!have_entire_pickle)
+    return;
+
+  const char* pickle_end = range_start + pickle_size;
+
   info->message_end = pickle_end;
 #endif  // USE_ATTACHMENT_BROKER
 
+  info->pickle_end = pickle_end;
   info->message_found = true;
 }
 
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
index 64909df..22d1c99 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/pickle.h"
 #include "base/trace_event/trace_event.h"
@@ -168,10 +169,14 @@
 
   // The static method FindNext() returns several pieces of information, which
   // are aggregated into an instance of this struct.
-  struct NextMessageInfo {
+  struct IPC_EXPORT NextMessageInfo {
     NextMessageInfo();
     ~NextMessageInfo();
 
+    // Total message size. Always valid if |message_found| is true.
+    // If |message_found| is false but we could determine message size
+    // from the header, this field is non-zero. Otherwise it's zero.
+    size_t message_size;
     // Whether an entire message was found in the given memory range.
     bool message_found;
     // Only filled in if |message_found| is true.
@@ -263,6 +268,12 @@
     int32_t routing;  // ID of the view that this message is destined for
     uint32_t type;    // specifies the user-defined message type
     uint32_t flags;   // specifies control flags for the message
+#if defined(OS_MACOSX)
+    // The number of brokered attachments included with this message. The
+    // ids of the brokered attachment ids are sent immediately after the pickled
+    // message, before the next pickled message is sent.
+    uint32_t num_brokered_attachments;
+#endif
 #if defined(OS_POSIX)
     uint16_t num_fds; // the number of descriptors included with this message
     uint16_t pad;     // explicitly initialize this to appease valgrind
@@ -307,6 +318,9 @@
   mutable LogData* log_data_;
   mutable bool dont_log_;
 #endif
+
+  FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNext);
+  FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNextOverflow);
 };
 
 //------------------------------------------------------------------------------
diff --git a/ipc/ipc_message_unittest.cc b/ipc/ipc_message_unittest.cc
index aea7054..a4f9af0 100644
--- a/ipc/ipc_message_unittest.cc
+++ b/ipc/ipc_message_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <string.h>
 
+#include <limits>
+
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -25,7 +27,7 @@
 
 IPC_SYNC_MESSAGE_CONTROL1_1(TestMsgClassIS, int, std::string)
 
-namespace {
+namespace IPC {
 
 TEST(IPCMessageTest, BasicMessageTest) {
   int v1 = 10;
@@ -115,6 +117,101 @@
   EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
 }
 
+TEST(IPCMessageTest, FindNext) {
+  IPC::Message message;
+  EXPECT_TRUE(message.WriteString("Goooooooogle"));
+  EXPECT_TRUE(message.WriteInt(111));
+
+  std::vector<char> message_data(message.size() + 7);
+  memcpy(message_data.data(), message.data(), message.size());
+
+  const char* data_start = message_data.data();
+  const char* data_end = data_start + message.size();
+
+  IPC::Message::NextMessageInfo next;
+
+  // Data range contains the entire message plus some extra bytes
+  IPC::Message::FindNext(data_start, data_end + 1, &next);
+  EXPECT_TRUE(next.message_found);
+  EXPECT_EQ(next.message_size, message.size());
+  EXPECT_EQ(next.pickle_end, data_end);
+  EXPECT_EQ(next.message_end, data_end);
+
+  // Data range exactly contains the entire message
+  IPC::Message::FindNext(data_start, data_end, &next);
+  EXPECT_TRUE(next.message_found);
+  EXPECT_EQ(next.message_size, message.size());
+  EXPECT_EQ(next.pickle_end, data_end);
+  EXPECT_EQ(next.message_end, data_end);
+
+  // Data range doesn't contain the entire message
+  // (but contains the message header)
+  IPC::Message::FindNext(data_start, data_end - 1, &next);
+  EXPECT_FALSE(next.message_found);
+#if USE_ATTACHMENT_BROKER
+  EXPECT_EQ(next.message_size, 0u);
+#else
+  EXPECT_EQ(next.message_size, message.size());
+#endif
+
+  // Data range doesn't contain the message header
+  // (but contains the pickle header)
+  IPC::Message::FindNext(data_start,
+                         data_start + sizeof(IPC::Message::Header) - 1,
+                         &next);
+  EXPECT_FALSE(next.message_found);
+  EXPECT_EQ(next.message_size, 0u);
+
+  // Data range doesn't contain the pickle header
+  IPC::Message::FindNext(data_start,
+                         data_start + sizeof(base::Pickle::Header) - 1,
+                         &next);
+  EXPECT_FALSE(next.message_found);
+  EXPECT_EQ(next.message_size, 0u);
+}
+
+TEST(IPCMessageTest, FindNextOverflow) {
+  IPC::Message message;
+  EXPECT_TRUE(message.WriteString("Data"));
+  EXPECT_TRUE(message.WriteInt(777));
+
+  const char* data_start = reinterpret_cast<const char*>(message.data());
+  const char* data_end = data_start + message.size();
+
+  IPC::Message::NextMessageInfo next;
+
+  // Payload size is negative (defeats 'start + size > end' check)
+  message.header()->payload_size = static_cast<uint32_t>(-1);
+  IPC::Message::FindNext(data_start, data_end, &next);
+  EXPECT_FALSE(next.message_found);
+#if USE_ATTACHMENT_BROKER
+  EXPECT_EQ(next.message_size, 0u);
+#else
+  if (sizeof(size_t) > sizeof(uint32_t)) {
+    // No overflow, just insane message size
+    EXPECT_EQ(next.message_size,
+              message.header()->payload_size + sizeof(IPC::Message::Header));
+  } else {
+    // Actual overflow, reported as max size_t
+    EXPECT_EQ(next.message_size, std::numeric_limits<size_t>::max());
+  }
+#endif
+
+  // Payload size is max positive integer (defeats size < 0 check, while
+  // still potentially causing overflow down the road).
+  message.header()->payload_size = std::numeric_limits<int32_t>::max();
+  IPC::Message::FindNext(data_start, data_end, &next);
+  EXPECT_FALSE(next.message_found);
+#if USE_ATTACHMENT_BROKER
+  EXPECT_EQ(next.message_size, 0u);
+#else
+  EXPECT_EQ(next.message_size,
+            message.header()->payload_size + sizeof(IPC::Message::Header));
+#endif
+}
+
+namespace {
+
 class IPCMessageParameterTest : public testing::Test {
  public:
   IPCMessageParameterTest() : extra_param_("extra_param"), called_(false) {}
@@ -160,6 +257,8 @@
   bool called_;
 };
 
+}  // namespace
+
 TEST_F(IPCMessageParameterTest, EmptyDispatcherWithParam) {
   TestMsgClassEmpty message;
   EXPECT_TRUE(OnMessageReceived(message));
@@ -186,4 +285,4 @@
   EXPECT_EQ(output, std::string("out"));
 }*/
 
-}  // namespace
+}  // namespace IPC
diff --git a/jingle/glue/DEPS b/jingle/glue/DEPS
index 790c9b7..44fa5732 100644
--- a/jingle/glue/DEPS
+++ b/jingle/glue/DEPS
@@ -2,4 +2,5 @@
 include_rules = [
   "+third_party/libjingle/overrides",
   "+third_party/webrtc",
-]
\ No newline at end of file
+  '+third_party/webrtc_overrides',
+]
diff --git a/jingle/glue/logging_unittest.cc b/jingle/glue/logging_unittest.cc
index 96401784..a5613f7 100644
--- a/jingle/glue/logging_unittest.cc
+++ b/jingle/glue/logging_unittest.cc
@@ -17,7 +17,7 @@
 // libjingle style logging is used.
 #define LOGGING_INSIDE_WEBRTC
 
-#include "third_party/webrtc/overrides/webrtc/base/logging.h"
+#include "third_party/webrtc_overrides/webrtc/base/logging.h"
 
 #if defined(OS_WIN)
 static const wchar_t* const log_file_name = L"libjingle_logging.log";
diff --git a/mandoline/BUILD.gn b/mandoline/BUILD.gn
index 6bfe2b4..cfb9b290 100644
--- a/mandoline/BUILD.gn
+++ b/mandoline/BUILD.gn
@@ -38,7 +38,7 @@
       "//components/html_viewer:apptests",
       "//components/html_viewer:html_viewer_unittests",
       "//components/html_viewer:layout_test_html_viewer",
-      "//components/mus:tests",
+      "//components/mus/vm:tests",
       "//components/resource_provider:apptests",
       "//components/resource_provider:resource_provider_unittests",
       "//components/web_view:apptests",
diff --git a/mandoline/ui/aura/BUILD.gn b/mandoline/ui/aura/BUILD.gn
index 831f176..873539fb 100644
--- a/mandoline/ui/aura/BUILD.gn
+++ b/mandoline/ui/aura/BUILD.gn
@@ -36,7 +36,6 @@
     "//skia",
     "//mojo/application/public/cpp",
     "//mojo/application/public/interfaces",
-    "//mojo/cc",
     "//mojo/converters/geometry",
     "//mojo/converters/ime",
     "//mojo/converters/input_events",
diff --git a/mandoline/ui/aura/surface_binding.cc b/mandoline/ui/aura/surface_binding.cc
index 8048373..321defd 100644
--- a/mandoline/ui/aura/surface_binding.cc
+++ b/mandoline/ui/aura/surface_binding.cc
@@ -14,14 +14,14 @@
 #include "cc/output/output_surface_client.h"
 #include "cc/output/software_output_device.h"
 #include "cc/resources/shared_bitmap_manager.h"
+#include "components/mus/public/cpp/context_provider.h"
+#include "components/mus/public/cpp/output_surface.h"
 #include "components/mus/public/cpp/view.h"
 #include "components/mus/public/cpp/view_tree_connection.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
 #include "mandoline/ui/aura/window_tree_host_mojo.h"
 #include "mojo/application/public/cpp/connect.h"
 #include "mojo/application/public/interfaces/shell.mojom.h"
-#include "mojo/cc/context_provider_mojo.h"
-#include "mojo/cc/output_surface_mojo.h"
 #include "mojo/converters/geometry/geometry_type_converters.h"
 #include "mojo/converters/surfaces/surfaces_type_converters.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -98,9 +98,9 @@
   gpu_->CreateOffscreenGLES2Context(GetProxy(&cb));
 
   scoped_refptr<cc::ContextProvider> context_provider(
-      new mojo::ContextProviderMojo(cb.PassInterface().PassHandle()));
+      new mus::ContextProvider(cb.PassInterface().PassHandle()));
   return make_scoped_ptr(
-      new mojo::OutputSurfaceMojo(context_provider, view->RequestSurface()));
+      new mus::OutputSurface(context_provider, view->RequestSurface()));
 }
 
 SurfaceBinding::PerConnectionState::PerConnectionState(
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 369d7d0..28e424e 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -303,8 +303,6 @@
   if (is_android) {
     sources += [ "android/audio_android_unittest.cc" ]
     deps += [ "//ui/gl" ]
-  } else {
-    sources += [ "audio_input_volume_unittest.cc" ]
   }
 
   if (is_mac) {
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc
index 325c3720..1d658fc 100644
--- a/media/audio/alsa/audio_manager_alsa.cc
+++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -163,9 +163,9 @@
     // still empty.  Note, pulse has exclusively opened the default
     // device, so we must open the device via the "default" moniker.
     if (device_names->empty()) {
-      device_names->push_front(media::AudioDeviceName(
-          AudioManagerBase::kDefaultDeviceName,
-          AudioManagerBase::kDefaultDeviceId));
+      device_names->push_front(
+          media::AudioDeviceName(AudioManager::GetDefaultDeviceName(),
+                                 AudioManagerBase::kDefaultDeviceId));
     }
 
     // Get the unique device name for the device.
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc
index 38269bc..a6f9421 100644
--- a/media/audio/android/audio_android_unittest.cc
+++ b/media/audio/android/audio_android_unittest.cc
@@ -35,6 +35,7 @@
 using ::testing::Return;
 
 namespace media {
+namespace {
 
 ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) {
   if (++*count >= limit) {
@@ -42,17 +43,17 @@
   }
 }
 
-static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
-static const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw";
-static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
-static const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw";
+const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
+const char kSpeechFile_16b_m_48k[] = "speech_16b_mono_48kHz.raw";
+const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
+const char kSpeechFile_16b_m_44k[] = "speech_16b_mono_44kHz.raw";
 
-static const float kCallbackTestTimeMs = 2000.0;
-static const int kBitsPerSample = 16;
-static const int kBytesPerSample = kBitsPerSample / 8;
+const float kCallbackTestTimeMs = 2000.0;
+const int kBitsPerSample = 16;
+const int kBytesPerSample = kBitsPerSample / 8;
 
 // Converts AudioParameters::Format enumerator to readable string.
-static std::string FormatToString(AudioParameters::Format format) {
+std::string FormatToString(AudioParameters::Format format) {
   switch (format) {
     case AudioParameters::AUDIO_PCM_LINEAR:
       return std::string("AUDIO_PCM_LINEAR");
@@ -67,7 +68,7 @@
 
 // Converts ChannelLayout enumerator to readable string. Does not include
 // multi-channel cases since these layouts are not supported on Android.
-static std::string LayoutToString(ChannelLayout channel_layout) {
+std::string LayoutToString(ChannelLayout channel_layout) {
   switch (channel_layout) {
     case CHANNEL_LAYOUT_NONE:
       return std::string("CHANNEL_LAYOUT_NONE");
@@ -81,7 +82,7 @@
   }
 }
 
-static double ExpectedTimeBetweenCallbacks(AudioParameters params) {
+double ExpectedTimeBetweenCallbacks(AudioParameters params) {
   return (base::TimeDelta::FromMicroseconds(
               params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
               static_cast<double>(params.sample_rate()))).InMillisecondsF();
@@ -89,7 +90,7 @@
 
 // Helper method which verifies that the device list starts with a valid
 // default device name followed by non-default device names.
-static void CheckDeviceNames(const AudioDeviceNames& device_names) {
+void CheckDeviceNames(const AudioDeviceNames& device_names) {
   DVLOG(2) << "Got " << device_names.size() << " audio devices.";
   if (device_names.empty()) {
     // Log a warning so we can see the status on the build bots.  No need to
@@ -102,8 +103,7 @@
   AudioDeviceNames::const_iterator it = device_names.begin();
 
   // The first device in the list should always be the default device.
-  EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName),
-            it->device_name);
+  EXPECT_EQ(AudioManager::GetDefaultDeviceName(), it->device_name);
   EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
   ++it;
 
@@ -114,20 +114,20 @@
     EXPECT_FALSE(it->unique_id.empty());
     DVLOG(2) << "Device ID(" << it->unique_id
              << "), label: " << it->device_name;
-    EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName),
-              it->device_name);
-    EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId),
-              it->unique_id);
+    EXPECT_NE(AudioManager::GetDefaultDeviceName(), it->device_name);
+    EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
     ++it;
   }
 }
 
 // We clear the data bus to ensure that the test does not cause noise.
-static int RealOnMoreData(AudioBus* dest, uint32 total_bytes_delay) {
+int RealOnMoreData(AudioBus* dest, uint32 total_bytes_delay) {
   dest->Zero();
   return dest->frames();
 }
 
+}  // namespace
+
 std::ostream& operator<<(std::ostream& os, const AudioParameters& params) {
   using namespace std;
   os << endl << "format: " << FormatToString(params.format()) << endl
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc
index e231cd1..01379b8a 100644
--- a/media/audio/android/audio_manager_android.cc
+++ b/media/audio/android/audio_manager_android.cc
@@ -28,19 +28,21 @@
 using base::android::ScopedJavaLocalRef;
 
 namespace media {
+namespace {
 
-static void AddDefaultDevice(AudioDeviceNames* device_names) {
+void AddDefaultDevice(AudioDeviceNames* device_names) {
   DCHECK(device_names->empty());
-  device_names->push_front(
-      AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
-                      AudioManagerBase::kDefaultDeviceId));
+  device_names->push_front(AudioDeviceName(AudioManager::GetDefaultDeviceName(),
+                                           AudioManagerBase::kDefaultDeviceId));
 }
 
 // Maximum number of output streams that can be open simultaneously.
-static const int kMaxOutputStreams = 10;
+const int kMaxOutputStreams = 10;
 
-static const int kDefaultInputBufferSize = 1024;
-static const int kDefaultOutputBufferSize = 2048;
+const int kDefaultInputBufferSize = 1024;
+const int kDefaultOutputBufferSize = 2048;
+
+}  // namespace
 
 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
   return new AudioManagerAndroid(audio_log_factory);
diff --git a/media/audio/audio_input_volume_unittest.cc b/media/audio/audio_input_volume_unittest.cc
deleted file mode 100644
index 3fa1f40..0000000
--- a/media/audio/audio_input_volume_unittest.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cmath>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager_base.h"
-#include "media/audio/audio_unittest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/win/scoped_com_initializer.h"
-#include "media/audio/win/core_audio_util_win.h"
-#endif
-
-namespace media {
-
-double GetVolumeAfterSetVolumeOnLinux(AudioInputStream* ais,
-                                      double target_volume) {
-  // SetVolume() is asynchronous on Linux, we need to keep trying until
-  // the SetVolume() operation is done.
-  static const int kTimesToRun = 10;
-  double volume = 0.0;
-  for (int i = 0; i < kTimesToRun; ++i) {
-    volume = ais->GetVolume();
-    if (volume == target_volume)
-      break;
-
-    // Sleep 100ms to wait for the operation.
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
-  }
-
-  return volume;
-}
-
-class AudioInputVolumeTest : public ::testing::Test {
- protected:
-  AudioInputVolumeTest() : audio_manager_(AudioManager::CreateForTesting()) {}
-
-  bool HasCoreAudioAndInputDevices() {
-#if defined(OS_WIN)
-    // TODO(henrika): add support for volume control on Windows XP as well.
-    if (!CoreAudioUtil::IsSupported())
-      return false;
-#endif
-    return audio_manager_->HasAudioInputDevices();
-  }
-
-  // Helper method which checks if the stream has volume support.
-  bool HasDeviceVolumeControl(AudioInputStream* stream) {
-    if (!stream)
-      return false;
-
-    return (stream->GetMaxVolume() != 0.0);
-  }
-
-  AudioInputStream* CreateAndOpenStream(const std::string& device_id) {
-    const AudioParameters& params =
-        audio_manager_->GetInputStreamParameters(device_id);
-    AudioInputStream* ais = audio_manager_->MakeAudioInputStream(
-        params, device_id);
-    EXPECT_TRUE(NULL != ais);
-
-#if defined(OS_LINUX) || defined(OS_OPENBSD)
-    // Some linux devices do not support our settings, we may fail to open
-    // those devices.
-    if (!ais->Open()) {
-      // Default device should always be able to be opened.
-      EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id);
-      ais->Close();
-      ais = NULL;
-    }
-#elif defined(OS_WIN) || defined(OS_MACOSX)
-    EXPECT_TRUE(ais->Open());
-#endif
-
-    return ais;
-  }
-
-  scoped_ptr<AudioManager> audio_manager_;
-};
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-// Currently failing on linux ARM bot: http://crbug/238490
-// Also flaky on x86_64: http://crbug/236936
-#define MAYBE_InputVolumeTest DISABLED_InputVolumeTest
-#else
-#define MAYBE_InputVolumeTest InputVolumeTest
-#endif
-
-TEST_F(AudioInputVolumeTest, MAYBE_InputVolumeTest) {
-  ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices());
-
-  // Retrieve a list of all available input devices.
-  AudioDeviceNames device_names;
-  audio_manager_->GetAudioInputDeviceNames(&device_names);
-  if (device_names.empty()) {
-    LOG(WARNING) << "Could not find any available input device";
-    return;
-  }
-
-  // Scan all available input devices and repeat the same test for all of them.
-  for (AudioDeviceNames::const_iterator it = device_names.begin();
-       it != device_names.end();
-       ++it) {
-    AudioInputStream* ais = CreateAndOpenStream(it->unique_id);
-    if (!ais) {
-      DLOG(WARNING) << "Failed to open stream for device " << it->unique_id;
-      continue;
-    }
-
-    if (!HasDeviceVolumeControl(ais)) {
-      DLOG(WARNING) << "Device: " << it->unique_id
-                    << ", does not have volume control.";
-      ais->Close();
-      continue;
-    }
-
-    double max_volume = ais->GetMaxVolume();
-    EXPECT_GT(max_volume, 0.0);
-
-    // Store the current input-device volume level.
-    double original_volume = ais->GetVolume();
-    EXPECT_GE(original_volume, 0.0);
-#if defined(OS_WIN) || defined(OS_MACOSX)
-    // Note that |original_volume| can be higher than |max_volume| on Linux.
-    EXPECT_LE(original_volume, max_volume);
-#endif
-
-    // Set the volume to the maxiumum level..
-    ais->SetVolume(max_volume);
-    double current_volume = ais->GetVolume();
-    EXPECT_EQ(max_volume, current_volume);
-
-    // Set the volume to the minimum level (=0).
-    double new_volume = 0.0;
-    ais->SetVolume(new_volume);
-#if defined(OS_LINUX)
-    current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume);
-#else
-    current_volume = ais->GetVolume();
-#endif
-    EXPECT_EQ(new_volume, current_volume);
-
-    // Set the volume to the mid level (50% of max).
-    // Verify that the absolute error is small enough.
-    new_volume = max_volume / 2;
-    ais->SetVolume(new_volume);
-#if defined(OS_LINUX)
-    current_volume = GetVolumeAfterSetVolumeOnLinux(ais, new_volume);
-#else
-    current_volume = ais->GetVolume();
-#endif
-    EXPECT_LT(current_volume, max_volume);
-    EXPECT_GT(current_volume, 0);
-    EXPECT_NEAR(current_volume, new_volume, 0.25 * max_volume);
-
-    // Restores the volume to the original value.
-    ais->SetVolume(original_volume);
-    current_volume = ais->GetVolume();
-    EXPECT_EQ(original_volume, current_volume);
-
-    ais->Close();
-  }
-}
-
-}  // namespace media
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index f39b82b..ebdfc4e 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -15,6 +15,7 @@
 #include "build/build_config.h"
 #include "media/audio/audio_manager_factory.h"
 #include "media/audio/fake_audio_log_factory.h"
+#include "media/base/media_resources.h"
 #include "media/base/media_switches.h"
 
 #if defined(OS_WIN)
@@ -283,4 +284,19 @@
   return g_last_created;
 }
 
+// static
+std::string AudioManager::GetDefaultDeviceName() {
+  return GetLocalizedStringUTF8(DEFAULT_AUDIO_DEVICE_NAME);
+}
+
+// static
+std::string AudioManager::GetCommunicationsDeviceName() {
+#if defined(OS_WIN)
+  return GetLocalizedStringUTF8(COMMUNICATIONS_AUDIO_DEVICE_NAME);
+#else
+  NOTREACHED();
+  return "";
+#endif
+}
+
 }  // namespace media
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 3739973..4da250d 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -79,6 +79,13 @@
   // like src/chrome.
   static AudioManager* Get();
 
+  // Returns the localized name of the generic "default" device.
+  static std::string GetDefaultDeviceName();
+
+  // Returns the localized name of the generic default communications device.
+  // This device is not supported on all platforms.
+  static std::string GetCommunicationsDeviceName();
+
   // Returns true if the OS reports existence of audio devices. This does not
   // guarantee that the existing devices support all formats and sample rates.
   virtual bool HasAudioOutputDevices() = 0;
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 43568cf..8c1dda2 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -19,23 +19,24 @@
 #include "media/base/media_switches.h"
 
 namespace media {
+namespace {
 
-static const int kStreamCloseDelaySeconds = 5;
+const int kStreamCloseDelaySeconds = 5;
 
 // Default maximum number of output streams that can be open simultaneously
 // for all platforms.
-static const int kDefaultMaxOutputStreams = 16;
+const int kDefaultMaxOutputStreams = 16;
 
 // Default maximum number of input streams that can be open simultaneously
 // for all platforms.
-static const int kDefaultMaxInputStreams = 16;
+const int kDefaultMaxInputStreams = 16;
 
-static const int kMaxInputChannels = 3;
+const int kMaxInputChannels = 3;
 
-const char AudioManagerBase::kDefaultDeviceName[] = "Default";
+}  // namespace
+
 const char AudioManagerBase::kDefaultDeviceId[] = "default";
 const char AudioManagerBase::kCommunicationsDeviceId[] = "communications";
-const char AudioManagerBase::kCommunicationsDeviceName[] = "Communications";
 const char AudioManagerBase::kLoopbackInputDeviceId[] = "loopback";
 
 struct AudioManagerBase::DispatcherParams {
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index 346fe47..cd947131 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -28,17 +28,14 @@
 // AudioManagerBase provides AudioManager functions common for all platforms.
 class MEDIA_EXPORT AudioManagerBase : public AudioManager {
  public:
-  // TODO(sergeyu): The constants below belong to AudioManager interface, not
-  // to the base implementation.
-
-  // Name of the generic "default" device.
-  static const char kDefaultDeviceName[];
-  // Unique Id of the generic "default" device.
+  // TODO(ajm): Move these strings to AudioManager.
+  // Unique Id of the generic "default" device. Associated with the localized
+  // name returned from GetDefaultDeviceName().
   static const char kDefaultDeviceId[];
-  // Unique Id of the generic default communications device (where supported).
+
+  // Unique Id of the generic default communications device. Associated with
+  // the localized name returned from GetCommunicationsDeviceName().
   static const char kCommunicationsDeviceId[];
-  // Name of the generic default communications device (where supported).
-  static const char kCommunicationsDeviceName[];
 
   // Input device ID used to capture the default system playback stream. When
   // this device ID is passed to MakeAudioInputStream() the returned
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 48bb51c..9fb0182 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -81,8 +81,7 @@
       AudioDeviceNames::const_iterator it = device_names.begin();
 
       // The first device in the list should always be the default device.
-      EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceName),
-                it->device_name);
+      EXPECT_EQ(AudioManager::GetDefaultDeviceName(), it->device_name);
       EXPECT_EQ(std::string(AudioManagerBase::kDefaultDeviceId), it->unique_id);
       ++it;
 
@@ -93,8 +92,7 @@
         EXPECT_FALSE(it->unique_id.empty());
         DVLOG(2) << "Device ID(" << it->unique_id
                  << "), label: " << it->device_name;
-        EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceName),
-                  it->device_name);
+        EXPECT_NE(AudioManager::GetDefaultDeviceName(), it->device_name);
         EXPECT_NE(std::string(AudioManagerBase::kDefaultDeviceId),
                   it->unique_id);
         ++it;
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index 3e9229da..dd7cb80 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -217,7 +217,7 @@
           .WillOnce(SignalEvent(&play_event_));
     }
 
-    controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName,
+    controller_->SwitchOutputDevice(AudioManager::GetDefaultDeviceName(),
                                     base::Bind(&base::DoNothing));
   }
 
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc
index 32f88d9..8452bd65 100644
--- a/media/audio/audio_output_device.cc
+++ b/media/audio/audio_output_device.cc
@@ -54,7 +54,8 @@
       security_origin_(security_origin),
       stopping_hack_(false),
       switch_output_device_on_start_(false),
-      did_set_output_params_(true, false) {
+      did_receive_auth_(true, false),
+      device_status_(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL) {
   CHECK(ipc_);
 
   // The correctness of the code depends on the relative values assigned in the
@@ -86,11 +87,8 @@
   // them in the thread where this destructor runs.
   if (!current_switch_callback_.is_null()) {
     base::ResetAndReturn(&current_switch_callback_)
-        .Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+        .Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
   }
-
-  // Unblock any blocked threads waiting for parameters
-  did_set_output_params_.Signal();
 }
 
 void AudioOutputDevice::RequestDeviceAuthorization() {
@@ -155,10 +153,16 @@
 
 AudioParameters AudioOutputDevice::GetOutputParameters() {
   CHECK(!task_runner()->BelongsToCurrentThread());
-  did_set_output_params_.Wait();
+  did_receive_auth_.Wait();
   return output_params_;
 }
 
+OutputDeviceStatus AudioOutputDevice::GetDeviceStatus() {
+  CHECK(!task_runner()->BelongsToCurrentThread());
+  did_receive_auth_.Wait();
+  return device_status_;
+}
+
 void AudioOutputDevice::RequestDeviceAuthorizationOnIOThread() {
   DCHECK(task_runner()->BelongsToCurrentThread());
   DCHECK_EQ(state_, IDLE);
@@ -176,7 +180,7 @@
       break;
 
     case IDLE:
-      if (did_set_output_params_.IsSignaled() && device_id_.empty() &&
+      if (did_receive_auth_.IsSignaled() && device_id_.empty() &&
           security_origin_.unique()) {
         state_ = CREATING_STREAM;
         ipc_->CreateStream(this, params);
@@ -267,7 +271,7 @@
 
   // Do not allow concurrent SwitchOutputDevice requests
   if (!current_switch_callback_.is_null()) {
-    callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+    callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
     return;
   }
 
@@ -313,20 +317,33 @@
 }
 
 void AudioOutputDevice::OnDeviceAuthorized(
-    bool success,
+    OutputDeviceStatus device_status,
     const media::AudioParameters& output_params) {
   DCHECK(task_runner()->BelongsToCurrentThread());
   DCHECK_EQ(state_, AUTHORIZING);
 
-  if (success) {
+  // It may happen that a second authorization is received as a result to a
+  // call to Start() after Stop(). If the status for the second authorization
+  // differs from the first, it will not be reflected in |device_status_|
+  // to avoid a race.
+  // This scenario is unlikely. If it occurs, the new value will be
+  // different from OUTPUT_DEVICE_STATUS_OK, so the AudioOutputDevice
+  // will enter the IPC_CLOSED state anyway, which is the safe thing to do.
+  // This is preferable to holding a lock.
+  if (!did_receive_auth_.IsSignaled())
+    device_status_ = device_status;
+
+  if (device_status == OUTPUT_DEVICE_STATUS_OK) {
     state_ = AUTHORIZED;
-    if (!did_set_output_params_.IsSignaled()) {
+    if (!did_receive_auth_.IsSignaled()) {
       output_params_ = output_params;
-      did_set_output_params_.Signal();
+      did_receive_auth_.Signal();
     }
     if (start_on_authorized_)
       CreateStreamOnIOThread(audio_parameters_);
   } else {
+    // Closing IPC forces a Signal(), so no clients are locked waiting
+    // indefinitely after this method returns.
     ipc_->CloseStream();
     OnIPCClosed();
     if (callback_)
@@ -386,10 +403,9 @@
   }
 }
 
-void AudioOutputDevice::OnOutputDeviceSwitched(
-    SwitchOutputDeviceResult result) {
+void AudioOutputDevice::OnOutputDeviceSwitched(OutputDeviceStatus result) {
   DCHECK(task_runner()->BelongsToCurrentThread());
-  if (result == SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS) {
+  if (result == OUTPUT_DEVICE_STATUS_OK) {
     session_id_ = 0;  // Output device is no longer attached to an input device
     device_id_ = current_switch_device_id_;
     security_origin_ = current_switch_security_origin_;
@@ -404,7 +420,7 @@
   ipc_.reset();
 
   // Signal to unblock any blocked threads waiting for parameters
-  did_set_output_params_.Signal();
+  did_receive_auth_.Signal();
 }
 
 void AudioOutputDevice::WillDestroyCurrentMessageLoop() {
diff --git a/media/audio/audio_output_device.h b/media/audio/audio_output_device.h
index d5ce695..a3618c82 100644
--- a/media/audio/audio_output_device.h
+++ b/media/audio/audio_output_device.h
@@ -113,16 +113,17 @@
                           const url::Origin& security_origin,
                           const SwitchOutputDeviceCB& callback) override;
   AudioParameters GetOutputParameters() override;
+  OutputDeviceStatus GetDeviceStatus() override;
 
   // Methods called on IO thread ----------------------------------------------
   // AudioOutputIPCDelegate methods.
   void OnStateChanged(AudioOutputIPCDelegateState state) override;
-  void OnDeviceAuthorized(bool success,
+  void OnDeviceAuthorized(OutputDeviceStatus device_status,
                           const media::AudioParameters& output_params) override;
   void OnStreamCreated(base::SharedMemoryHandle handle,
                        base::SyncSocket::Handle socket_handle,
                        int length) override;
-  void OnOutputDeviceSwitched(SwitchOutputDeviceResult result) override;
+  void OnOutputDeviceSwitched(OutputDeviceStatus result) override;
   void OnIPCClosed() override;
 
  protected:
@@ -164,7 +165,7 @@
   void SetCurrentSwitchRequest(const SwitchOutputDeviceCB& callback,
                                const std::string& device_id,
                                const url::Origin& security_origin);
-  void SetOutputParams(const media::AudioParameters& output_params);
+  void SetDeviceStatus(OutputDeviceStatus status);
 
   AudioParameters audio_parameters_;
 
@@ -215,8 +216,9 @@
   url::Origin current_switch_security_origin_;
   bool switch_output_device_on_start_;
 
-  base::WaitableEvent did_set_output_params_;
+  base::WaitableEvent did_receive_auth_;
   media::AudioParameters output_params_;
+  OutputDeviceStatus device_status_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioOutputDevice);
 };
diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc
index 6e881a2..15ed4c3f1 100644
--- a/media/audio/audio_output_device_unittest.cc
+++ b/media/audio/audio_output_device_unittest.cc
@@ -35,8 +35,10 @@
 
 namespace {
 
+const std::string kDefaultDeviceId;
 const std::string kNonDefaultDeviceId("valid-nondefault-device-id");
 const std::string kUnauthorizedDeviceId("unauthorized-device-id");
+const url::Origin kDefaultSecurityOrigin;
 
 class MockRenderCallback : public AudioRendererSink::RenderCallback {
  public:
@@ -71,7 +73,7 @@
 
 class MockSwitchOutputDeviceCallback {
  public:
-  MOCK_METHOD1(Callback, void(media::SwitchOutputDeviceResult result));
+  MOCK_METHOD1(Callback, void(OutputDeviceStatus result));
 };
 
 ACTION_P2(SendPendingBytes, socket, pending_bytes) {
@@ -93,7 +95,7 @@
   AudioOutputDeviceTest();
   ~AudioOutputDeviceTest();
 
-  void ReceiveAuthorization(bool success);
+  void ReceiveAuthorization(OutputDeviceStatus device_status);
   void StartAudioDevice();
   void CreateStream();
   void ExpectRenderCallback();
@@ -112,11 +114,11 @@
   MockAudioOutputIPC* audio_output_ipc_;  // owned by audio_device_
   scoped_refptr<AudioOutputDevice> audio_device_;
   MockSwitchOutputDeviceCallback switch_output_device_callback_;
-  bool successful_auth_;
+  OutputDeviceStatus device_status_;
 
  private:
   int CalculateMemorySize();
-  void SwitchOutputDeviceCallback(SwitchOutputDeviceResult result);
+  void SwitchOutputDeviceCallback(OutputDeviceStatus result);
 
   SharedMemory shared_memory_;
   CancelableSyncSocket browser_socket_;
@@ -130,10 +132,11 @@
   return AudioBus::CalculateMemorySize(default_audio_parameters_);
 }
 
-AudioOutputDeviceTest::AudioOutputDeviceTest() : successful_auth_(false) {
+AudioOutputDeviceTest::AudioOutputDeviceTest()
+    : device_status_(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL) {
   default_audio_parameters_.Reset(AudioParameters::AUDIO_PCM_LINEAR,
                                   CHANNEL_LAYOUT_STEREO, 48000, 16, 1024);
-  SetDevice(std::string());  // Use default device
+  SetDevice(kDefaultDeviceId);
 }
 
 AudioOutputDeviceTest::~AudioOutputDeviceTest() {
@@ -144,31 +147,34 @@
   audio_output_ipc_ = new MockAudioOutputIPC();
   audio_device_ = new AudioOutputDevice(
       scoped_ptr<AudioOutputIPC>(audio_output_ipc_), io_loop_.task_runner(), 0,
-      device_id, url::Origin());
+      device_id, kDefaultSecurityOrigin);
   EXPECT_CALL(*audio_output_ipc_,
               RequestDeviceAuthorization(audio_device_.get(), 0, device_id, _));
   audio_device_->RequestDeviceAuthorization();
   io_loop_.RunUntilIdle();
 
   // Simulate response from browser
-  bool successful_auth = device_id != kUnauthorizedDeviceId;
-  ReceiveAuthorization(successful_auth);
+  OutputDeviceStatus device_status =
+      (device_id == kUnauthorizedDeviceId)
+          ? OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
+          : OUTPUT_DEVICE_STATUS_OK;
+  ReceiveAuthorization(device_status);
 
   audio_device_->Initialize(default_audio_parameters_,
                             &callback_);
 }
 
-void AudioOutputDeviceTest::ReceiveAuthorization(bool success) {
-  successful_auth_ = success;
-  if (!successful_auth_)
+void AudioOutputDeviceTest::ReceiveAuthorization(OutputDeviceStatus status) {
+  device_status_ = status;
+  if (device_status_ != OUTPUT_DEVICE_STATUS_OK)
     EXPECT_CALL(*audio_output_ipc_, CloseStream());
 
-  audio_device_->OnDeviceAuthorized(success, default_audio_parameters_);
+  audio_device_->OnDeviceAuthorized(device_status_, default_audio_parameters_);
   io_loop_.RunUntilIdle();
 }
 
 void AudioOutputDeviceTest::StartAudioDevice() {
-  if (successful_auth_)
+  if (device_status_ == OUTPUT_DEVICE_STATUS_OK)
     EXPECT_CALL(*audio_output_ipc_, CreateStream(audio_device_.get(), _));
   else
     EXPECT_CALL(callback_, OnRenderError());
@@ -234,7 +240,7 @@
 }
 
 void AudioOutputDeviceTest::StopAudioDevice() {
-  if (successful_auth_)
+  if (device_status_ == OUTPUT_DEVICE_STATUS_OK)
     EXPECT_CALL(*audio_output_ipc_, CloseStream());
 
   audio_device_->Stop();
@@ -252,8 +258,8 @@
 
   // Simulate the reception of a successful response from the browser
   EXPECT_CALL(switch_output_device_callback_,
-              Callback(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS));
-  audio_device_->OnOutputDeviceSwitched(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+              Callback(OUTPUT_DEVICE_STATUS_OK));
+  audio_device_->OnOutputDeviceSwitched(OUTPUT_DEVICE_STATUS_OK);
   io_loop_.RunUntilIdle();
 }
 
@@ -328,7 +334,7 @@
               RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
   StartAudioDevice();
   // Simulate reply from browser
-  ReceiveAuthorization(true);
+  ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
 
   StopAudioDevice();
 }
diff --git a/media/audio/audio_output_ipc.h b/media/audio/audio_output_ipc.h
index 6a16d813..fa9c08e 100644
--- a/media/audio/audio_output_ipc.h
+++ b/media/audio/audio_output_ipc.h
@@ -37,7 +37,7 @@
   // Called when an authorization request for an output device has been
   // completed
   virtual void OnDeviceAuthorized(
-      bool success,
+      OutputDeviceStatus device_status,
       const media::AudioParameters& output_params) = 0;
 
   // Called when an audio stream has been created.
@@ -53,7 +53,7 @@
                                int length) = 0;
 
   // Called when an attempt to switch the output device has been completed
-  virtual void OnOutputDeviceSwitched(SwitchOutputDeviceResult result) = 0;
+  virtual void OnOutputDeviceSwitched(OutputDeviceStatus result) = 0;
 
   // Called when the AudioOutputIPC object is going away and/or when the IPC
   // channel has been closed and no more ipc requests can be made.
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 2b47de40..fc58004 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -16,6 +16,7 @@
 #include "media/audio/cras/cras_input.h"
 #include "media/audio/cras/cras_unified.h"
 #include "media/base/channel_layout.h"
+#include "media/base/media_resources.h"
 
 // cras_util.h headers pull in min/max macros...
 // TODO(dgreid): Fix headers such that these aren't imported.
@@ -38,32 +39,27 @@
 // Default input buffer size.
 const int kDefaultInputBufferSize = 1024;
 
+const char kBeamformingOnUniqueId[] = "beamforming-on";
+const char kBeamformingOffUniqueId[] = "beamforming-off";
+
 void AddDefaultDevice(AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+
   // Cras will route audio from a proper physical device automatically.
-  device_names->push_back(
-      AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
-                      AudioManagerBase::kDefaultDeviceId));
+  device_names->push_back(AudioDeviceName(AudioManager::GetDefaultDeviceName(),
+                                          AudioManagerBase::kDefaultDeviceId));
 }
 
-// Returns the AudioDeviceName of the virtual device with beamforming on.
-AudioDeviceName BeamformingOnDeviceName() {
-  // TODO(ajm): Replace these strings with properly localized ones.
-  // (crbug.com/497001)
-  static const char kBeamformingOnNameSuffix[] = " (pick up just one person)";
-  static const char kBeamformingOnIdSuffix[] = "-beamforming";
+// Adds the beamforming on and off devices to |device_names|.
+void AddBeamformingDevices(AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
 
-  return AudioDeviceName(
-      std::string(AudioManagerBase::kDefaultDeviceName) +
-          kBeamformingOnNameSuffix,
-      std::string(AudioManagerBase::kDefaultDeviceId) + kBeamformingOnIdSuffix);
-}
-
-// Returns the AudioDeviceName of the virtual device with beamforming off.
-AudioDeviceName BeamformingOffDeviceName() {
-  static const char kBeamformingOffNameSuffix[] = " (pick up everything)";
-  return AudioDeviceName(std::string(AudioManagerBase::kDefaultDeviceName) +
-                             kBeamformingOffNameSuffix,
-                         AudioManagerBase::kDefaultDeviceId);
+  device_names->push_back(AudioDeviceName(
+      GetLocalizedStringUTF8(BEAMFORMING_ON_DEFAULT_AUDIO_INPUT_DEVICE_NAME),
+      kBeamformingOnUniqueId));
+  device_names->push_back(AudioDeviceName(
+      GetLocalizedStringUTF8(BEAMFORMING_OFF_DEFAULT_AUDIO_INPUT_DEVICE_NAME),
+      kBeamformingOffUniqueId));
 }
 
 // Returns a mic positions string if the machine has a beamforming capable
@@ -99,10 +95,7 @@
 }
 
 AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
-    : AudioManagerBase(audio_log_factory),
-      has_keyboard_mic_(false),
-      beamforming_on_device_name_(BeamformingOnDeviceName()),
-      beamforming_off_device_name_(BeamformingOffDeviceName()) {
+    : AudioManagerBase(audio_log_factory), has_keyboard_mic_(false) {
   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
 }
 
@@ -122,18 +115,14 @@
   // At least two mic positions indicates we have a beamforming capable mic
   // array. Add the virtual beamforming device to the list. When this device is
   // queried through GetInputStreamParameters, provide the cached mic positions.
-  if (mic_positions_.size() > 1) {
-    device_names->push_back(beamforming_on_device_name_);
-    device_names->push_back(beamforming_off_device_name_);
-  } else {
+  if (mic_positions_.size() > 1)
+    AddBeamformingDevices(device_names);
+  else
     AddDefaultDevice(device_names);
-  }
 }
 
 void AudioManagerCras::GetAudioOutputDeviceNames(
     AudioDeviceNames* device_names) {
-  DCHECK(device_names->empty());
-
   AddDefaultDevice(device_names);
 }
 
@@ -152,7 +141,7 @@
                          buffer_size);
   if (has_keyboard_mic_)
     params.set_effects(AudioParameters::KEYBOARD_MIC);
-  if (device_id == beamforming_on_device_name_.unique_id)
+  if (device_id == kBeamformingOnUniqueId)
     params.set_mic_positions(mic_positions_);
   return params;
 }
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h
index d55756dc..275f5c2 100644
--- a/media/audio/cras/audio_manager_cras.h
+++ b/media/audio/cras/audio_manager_cras.h
@@ -61,10 +61,6 @@
 
   bool has_keyboard_mic_;
 
-  // Holds the name and ID of the virtual beamforming devices.
-  const AudioDeviceName beamforming_on_device_name_;
-  const AudioDeviceName beamforming_off_device_name_;
-
   // Stores the mic positions field from the device.
   std::vector<Point> mic_positions_;
 
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 33dbfdf..f2f73da 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -152,7 +152,7 @@
     // on the top of the list for all platforms. There is no duplicate
     // counting here since the default device has been abstracted out before.
     media::AudioDeviceName name;
-    name.device_name = AudioManagerBase::kDefaultDeviceName;
+    name.device_name = AudioManager::GetDefaultDeviceName();
     name.unique_id = AudioManagerBase::kDefaultDeviceId;
     device_names->push_front(name);
   }
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc
index f3d88326..50a322f 100644
--- a/media/audio/pulse/audio_manager_pulse.cc
+++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -113,7 +113,7 @@
   // Prepend the default device if the list is not empty.
   if (!device_names->empty()) {
     device_names->push_front(
-        AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
+        AudioDeviceName(AudioManager::GetDefaultDeviceName(),
                         AudioManagerBase::kDefaultDeviceId));
   }
 }
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 7ef9a84..70e6c1b 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -286,12 +286,12 @@
   if (!device_names->empty()) {
     AudioDeviceName name;
     if (enumeration_type() == kMMDeviceEnumeration) {
-      name.device_name = AudioManagerBase::kCommunicationsDeviceName;
+      name.device_name = AudioManager::GetCommunicationsDeviceName();
       name.unique_id = AudioManagerBase::kCommunicationsDeviceId;
       device_names->push_front(name);
     }
     // Always add default device parameters as first element.
-    name.device_name = AudioManagerBase::kDefaultDeviceName;
+    name.device_name = AudioManager::GetDefaultDeviceName();
     name.unique_id = AudioManagerBase::kDefaultDeviceId;
     device_names->push_front(name);
   }
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 40641c4..3565553 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -118,6 +118,8 @@
     "media_log_event.h",
     "media_permission.cc",
     "media_permission.h",
+    "media_resources.cc",
+    "media_resources.h",
     "media_switches.cc",
     "media_switches.h",
     "mime_util.cc",
@@ -336,6 +338,8 @@
     "fake_audio_renderer_sink.h",
     "fake_demuxer_stream.cc",
     "fake_demuxer_stream.h",
+    "fake_media_resources.cc",
+    "fake_media_resources.h",
     "fake_output_device.cc",
     "fake_output_device.h",
     "fake_text_track_stream.cc",
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 8e197edc..84405c8 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -52,6 +52,8 @@
     "media_resource_getter.h",
     "media_source_player.cc",
     "media_source_player.h",
+    "media_task_runner.cc",
+    "media_task_runner.h",
     "media_url_interceptor.h",
     "video_decoder_job.cc",
     "video_decoder_job.h",
diff --git a/media/base/android/browser_cdm_factory_android.cc b/media/base/android/browser_cdm_factory_android.cc
index 82f11d1..7e6d919 100644
--- a/media/base/android/browser_cdm_factory_android.cc
+++ b/media/base/android/browser_cdm_factory_android.cc
@@ -13,7 +13,7 @@
 
 namespace media {
 
-scoped_ptr<BrowserCdm> BrowserCdmFactoryAndroid::CreateBrowserCdm(
+ScopedBrowserCdmPtr BrowserCdmFactoryAndroid::CreateBrowserCdm(
     const std::string& key_system,
     bool use_hw_secure_codecs,
     const SessionMessageCB& session_message_cb,
@@ -23,16 +23,16 @@
     const SessionExpirationUpdateCB& session_expiration_update_cb) {
   if (!MediaDrmBridge::IsKeySystemSupported(key_system)) {
     NOTREACHED() << "Unsupported key system: " << key_system;
-    return scoped_ptr<BrowserCdm>();
+    return ScopedBrowserCdmPtr();
   }
 
-  scoped_ptr<MediaDrmBridge> cdm(
+  ScopedMediaDrmBridgePtr cdm(
       MediaDrmBridge::Create(key_system, session_message_cb, session_closed_cb,
                              legacy_session_error_cb, session_keys_change_cb,
                              session_expiration_update_cb));
   if (!cdm) {
     NOTREACHED() << "MediaDrmBridge cannot be created for " << key_system;
-    return scoped_ptr<BrowserCdm>();
+    return ScopedBrowserCdmPtr();
   }
 
   if (key_system == kWidevineKeySystem) {
@@ -41,7 +41,7 @@
                           : MediaDrmBridge::SECURITY_LEVEL_3;
     if (!cdm->SetSecurityLevel(security_level)) {
       DVLOG(1) << "failed to set security level " << security_level;
-      return scoped_ptr<BrowserCdm>();
+      return ScopedBrowserCdmPtr();
     }
   } else {
     // Assume other key systems require hardware-secure codecs and thus do not
@@ -50,7 +50,7 @@
       NOTREACHED()
           << key_system
           << " may require use_video_overlay_for_embedded_encrypted_video";
-      return scoped_ptr<BrowserCdm>();
+      return ScopedBrowserCdmPtr();
     }
   }
 
diff --git a/media/base/android/browser_cdm_factory_android.h b/media/base/android/browser_cdm_factory_android.h
index 71b7970c..df6ca19 100644
--- a/media/base/android/browser_cdm_factory_android.h
+++ b/media/base/android/browser_cdm_factory_android.h
@@ -16,7 +16,7 @@
   BrowserCdmFactoryAndroid() {}
   ~BrowserCdmFactoryAndroid() final {};
 
-  scoped_ptr<BrowserCdm> CreateBrowserCdm(
+  ScopedBrowserCdmPtr CreateBrowserCdm(
       const std::string& key_system,
       bool use_hw_secure_codecs,
       const SessionMessageCB& session_message_cb,
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index c639d4b6..38a08187 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -790,6 +790,8 @@
         }
     }
 
+    // TODO(xhwang): fix deprecation warnings crbug.com/527916
+    @SuppressWarnings("deprecation")
     private int getAudioFormat(int channelCount) {
         switch (channelCount) {
             case 1:
diff --git a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
index 431a0a5..6d71eb6 100644
--- a/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java
@@ -946,6 +946,8 @@
         });
     }
 
+    // TODO(xhwang): fix deprecation warnings crbug.com/527916
+    @SuppressWarnings("deprecation")
     private class EventListener implements MediaDrm.OnEventListener {
         @Override
         public void onEvent(
diff --git a/media/base/android/media_codec_player.cc b/media/base/android/media_codec_player.cc
index 997a3e0..85f2a1d 100644
--- a/media/base/android/media_codec_player.cc
+++ b/media/base/android/media_codec_player.cc
@@ -13,6 +13,7 @@
 #include "media/base/android/media_codec_audio_decoder.h"
 #include "media/base/android/media_codec_video_decoder.h"
 #include "media/base/android/media_player_manager.h"
+#include "media/base/android/media_task_runner.h"
 #include "media/base/timestamp_constants.h"
 
 #define RUN_ON_MEDIA_THREAD(METHOD, ...)                                     \
@@ -28,22 +29,6 @@
 
 namespace media {
 
-class MediaThread : public base::Thread {
- public:
-  MediaThread() : base::Thread("BrowserMediaThread") {
-    Start();
-  }
-};
-
-// Create media thread
-base::LazyInstance<MediaThread>::Leaky
-    g_media_thread = LAZY_INSTANCE_INITIALIZER;
-
-
-scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner() {
-  return g_media_thread.Pointer()->task_runner();
-}
-
 // MediaCodecPlayer implementation.
 
 MediaCodecPlayer::MediaCodecPlayer(
diff --git a/media/base/android/media_codec_player.h b/media/base/android/media_codec_player.h
index cbbc910..1bc02542 100644
--- a/media/base/android/media_codec_player.h
+++ b/media/base/android/media_codec_player.h
@@ -159,9 +159,6 @@
 class MediaCodecAudioDecoder;
 class MediaCodecVideoDecoder;
 
-// Returns the task runner for the media thread
-MEDIA_EXPORT scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
-
 class MEDIA_EXPORT MediaCodecPlayer : public MediaPlayerAndroid,
                                       public DemuxerAndroidClient {
  public:
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc
index 4940f48..46b95fcb 100644
--- a/media/base/android/media_codec_player_unittest.cc
+++ b/media/base/android/media_codec_player_unittest.cc
@@ -11,6 +11,7 @@
 #include "media/base/android/media_codec_bridge.h"
 #include "media/base/android/media_codec_player.h"
 #include "media/base/android/media_player_manager.h"
+#include "media/base/android/media_task_runner.h"
 #include "media/base/android/test_data_factory.h"
 #include "media/base/android/test_statistics.h"
 #include "media/base/timestamp_constants.h"
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index 14bdbda0..778693a 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -9,6 +9,7 @@
 #include "base/android/build_info.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
+#include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/hash_tables.h"
 #include "base/lazy_instance.h"
@@ -24,6 +25,7 @@
 #include "jni/MediaDrmBridge_jni.h"
 #include "media/base/android/media_client_android.h"
 #include "media/base/android/media_drm_bridge_delegate.h"
+#include "media/base/android/media_task_runner.h"
 #include "media/base/cdm_key_information.h"
 
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
@@ -32,6 +34,7 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertJavaStringToUTF8;
 using base::android::JavaByteArrayToByteVector;
+using base::android::ScopedJavaGlobalRef;
 using base::android::ScopedJavaLocalRef;
 
 namespace media {
@@ -254,6 +257,7 @@
   return IsKeySystemSupportedWithTypeImpl(key_system, container_mime_type);
 }
 
+// static
 bool MediaDrmBridge::RegisterMediaDrmBridge(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
@@ -270,7 +274,13 @@
       session_closed_cb_(session_closed_cb),
       legacy_session_error_cb_(legacy_session_error_cb),
       session_keys_change_cb_(session_keys_change_cb),
-      session_expiration_update_cb_(session_expiration_update_cb) {
+      session_expiration_update_cb_(session_expiration_update_cb),
+      ui_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      use_media_thread_(UseMediaThreadForMediaPlayback()),
+      media_weak_factory_(this),
+      ui_weak_factory_(this) {
+  DVLOG(1) << __FUNCTION__;
+
   JNIEnv* env = AttachCurrentThread();
   CHECK(env);
 
@@ -280,22 +290,43 @@
       env, j_scheme_uuid.obj(), reinterpret_cast<intptr_t>(this)));
 }
 
-MediaDrmBridge::~MediaDrmBridge() {
+void MediaDrmBridge::DeleteOnCorrectThread() {
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DVLOG(1) << __FUNCTION__;
+
   JNIEnv* env = AttachCurrentThread();
-  player_tracker_.NotifyCdmUnset();
   if (!j_media_drm_.is_null())
     Java_MediaDrmBridge_destroy(env, j_media_drm_.obj());
+
+  // After the call to Java_MediaDrmBridge_destroy() Java won't call native
+  // methods anymore, this is ensured by MediaDrmBridge.java.
+
+  // Post deletion onto Media thread if we use it.
+  if (use_media_thread_) {
+    ui_weak_factory_.InvalidateWeakPtrs();
+    GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this);
+  } else {
+    delete this;
+  }
+}
+
+MediaDrmBridge::~MediaDrmBridge() {
+  DVLOG(1) << __FUNCTION__;
+
+  DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread());
+
+  player_tracker_.NotifyCdmUnset();
 }
 
 // static
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::Create(
+ScopedMediaDrmBridgePtr MediaDrmBridge::Create(
     const std::string& key_system,
     const SessionMessageCB& session_message_cb,
     const SessionClosedCB& session_closed_cb,
     const LegacySessionErrorCB& legacy_session_error_cb,
     const SessionKeysChangeCB& session_keys_change_cb,
     const SessionExpirationUpdateCB& session_expiration_update_cb) {
-  scoped_ptr<MediaDrmBridge> media_drm_bridge;
+  scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> media_drm_bridge;
   if (!IsAvailable())
     return media_drm_bridge.Pass();
 
@@ -315,8 +346,8 @@
 }
 
 // static
-scoped_ptr<MediaDrmBridge> MediaDrmBridge::CreateWithoutSessionSupport(
-    const std::string& key_system) {
+ScopedMediaDrmBridgePtr
+MediaDrmBridge::CreateWithoutSessionSupport(const std::string& key_system) {
   return MediaDrmBridge::Create(
       key_system, SessionMessageCB(), SessionClosedCB(), LegacySessionErrorCB(),
       SessionKeysChangeCB(), SessionExpirationUpdateCB());
@@ -464,33 +495,61 @@
 
 int MediaDrmBridge::RegisterPlayer(const base::Closure& new_key_cb,
                                    const base::Closure& cdm_unset_cb) {
+  DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread());
   return player_tracker_.RegisterPlayer(new_key_cb, cdm_unset_cb);
 }
 
 void MediaDrmBridge::UnregisterPlayer(int registration_id) {
+  DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread());
   player_tracker_.UnregisterPlayer(registration_id);
 }
 
-void MediaDrmBridge::SetMediaCryptoReadyCB(const base::Closure& closure) {
-  if (closure.is_null()) {
+void MediaDrmBridge::SetMediaCryptoReadyCB(
+    const MediaCryptoReadyCB& media_crypto_ready_cb) {
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DVLOG(1) << __FUNCTION__;
+
+  if (media_crypto_ready_cb.is_null()) {
     media_crypto_ready_cb_.Reset();
     return;
   }
 
   DCHECK(media_crypto_ready_cb_.is_null());
 
+  // |media_crypto_ready_cb| is already bound to the correct thread
+  // (either UI or Media).
   if (!GetMediaCrypto().is_null()) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
+    NotifyMediaCryptoReady(media_crypto_ready_cb);
     return;
   }
 
-  media_crypto_ready_cb_ = closure;
+  media_crypto_ready_cb_ = media_crypto_ready_cb;
 }
 
-void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject) {
+void MediaDrmBridge::OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm) {
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+  DVLOG(1) << __FUNCTION__;
+
   DCHECK(!GetMediaCrypto().is_null());
-  if (!media_crypto_ready_cb_.is_null())
-    base::ResetAndReturn(&media_crypto_ready_cb_).Run();
+
+  if (media_crypto_ready_cb_.is_null())
+    return;
+
+  NotifyMediaCryptoReady(base::ResetAndReturn(&media_crypto_ready_cb_));
+}
+
+void MediaDrmBridge::NotifyMediaCryptoReady(const MediaCryptoReadyCB& cb) {
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+
+  DCHECK(!cb.is_null());
+  DCHECK(!GetMediaCrypto().is_null());
+
+  // We can use scoped_ptr to pass ScopedJavaGlobalRef with a callback.
+  scoped_ptr<ScopedJavaGlobalRef<jobject>> j_object_ptr(
+      new ScopedJavaGlobalRef<jobject>());
+  j_object_ptr->Reset(AttachCurrentThread(), GetMediaCrypto().obj());
+
+  cb.Run(j_object_ptr.Pass(), IsProtectedSurfaceRequired());
 }
 
 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env,
@@ -545,7 +604,7 @@
                                          jobjectArray j_keys_info,
                                          bool has_additional_usable_key) {
   if (has_additional_usable_key)
-    player_tracker_.NotifyNewKey();
+    NotifyNewKeyOnCorrectThread();
 
   CdmKeysInfo cdm_keys_info;
 
@@ -583,6 +642,21 @@
                               has_additional_usable_key, cdm_keys_info.Pass());
 }
 
+void MediaDrmBridge::NotifyNewKeyOnCorrectThread() {
+  // Repost this method onto the Media thread if |use_media_thread_| is true.
+  if (use_media_thread_ && !GetMediaTaskRunner()->BelongsToCurrentThread()) {
+    GetMediaTaskRunner()->PostTask(
+        FROM_HERE, base::Bind(&MediaDrmBridge::NotifyNewKeyOnCorrectThread,
+                              media_weak_factory_.GetWeakPtr()));
+    return;
+  }
+
+  DCHECK(!use_media_thread_ || GetMediaTaskRunner()->BelongsToCurrentThread());
+  DVLOG(1) << __FUNCTION__;
+
+  player_tracker_.NotifyNewKey();
+}
+
 // According to MeidaDrm documentation [1], zero |expiry_time_ms| means the keys
 // will never expire. This will be translated into a NULL base::Time() [2],
 // which will then be mapped to a zero Java time [3]. The zero Java time is
@@ -613,6 +687,8 @@
 }
 
 ScopedJavaLocalRef<jobject> MediaDrmBridge::GetMediaCrypto() {
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
+
   JNIEnv* env = AttachCurrentThread();
   return Java_MediaDrmBridge_getMediaCrypto(env, j_media_drm_.obj());
 }
@@ -635,6 +711,10 @@
   return true;
 }
 
+base::WeakPtr<MediaDrmBridge> MediaDrmBridge::WeakPtrForUIThread() {
+  return ui_weak_factory_.GetWeakPtr();
+}
+
 void MediaDrmBridge::ResetDeviceCredentials(
     const ResetCredentialsCB& callback) {
   DCHECK(reset_credentials_cb_.is_null());
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h
index f6a951f..8202866 100644
--- a/media/base/android/media_drm_bridge.h
+++ b/media/base/android/media_drm_bridge.h
@@ -12,6 +12,7 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "media/base/browser_cdm.h"
 #include "media/base/cdm_promise_adapter.h"
 #include "media/base/media_export.h"
@@ -22,8 +23,11 @@
 
 namespace media {
 
+class MediaDrmBridge;
 class MediaPlayerManager;
 
+using ScopedMediaDrmBridgePtr = scoped_ptr<MediaDrmBridge, BrowserCdmDeleter>;
+
 // This class provides DRM services for android EME implementation.
 class MEDIA_EXPORT MediaDrmBridge : public BrowserCdm {
  public:
@@ -34,10 +38,21 @@
     SECURITY_LEVEL_3 = 3,
   };
 
-  typedef base::Callback<void(bool)> ResetCredentialsCB;
+  using JavaObjectPtr = scoped_ptr<base::android::ScopedJavaGlobalRef<jobject>>;
+
+  using ResetCredentialsCB = base::Callback<void(bool)>;
+
+  // Notification called when MediaCrypto object is ready.
+  // Parameters:
+  // |media_crypto| - global reference to MediaCrypto object
+  // |needs_protected_surface| - true if protected surface is required.
+  using MediaCryptoReadyCB = base::Callback<void(JavaObjectPtr media_crypto,
+                                                 bool needs_protected_surface)>;
 
   ~MediaDrmBridge() override;
 
+  void DeleteOnCorrectThread() override;
+
   // Checks whether MediaDRM is available.
   // All other static methods check IsAvailable() internally. There's no need
   // to check IsAvailable() explicitly before calling them.
@@ -61,7 +76,7 @@
   // Returns a MediaDrmBridge instance if |key_system| is supported, or a NULL
   // pointer otherwise.
   // TODO(xhwang): Is it okay not to update session expiration info?
-  static scoped_ptr<MediaDrmBridge> Create(
+  static ScopedMediaDrmBridgePtr Create(
       const std::string& key_system,
       const SessionMessageCB& session_message_cb,
       const SessionClosedCB& session_closed_cb,
@@ -72,7 +87,7 @@
   // Returns a MediaDrmBridge instance if |key_system| is supported, or a NULL
   // otherwise. No session callbacks are provided. This is used when we need to
   // use MediaDrmBridge without creating any sessions.
-  static scoped_ptr<MediaDrmBridge> CreateWithoutSessionSupport(
+  static ScopedMediaDrmBridgePtr CreateWithoutSessionSupport(
       const std::string& key_system);
 
   // Returns true if |security_level| is successfully set, or false otherwise.
@@ -114,11 +129,11 @@
   // otherwise.
   base::android::ScopedJavaLocalRef<jobject> GetMediaCrypto();
 
-  // Sets callback which will be called when MediaCrypto is ready.
-  // If |closure| is null, previously set callback will be cleared.
-  void SetMediaCryptoReadyCB(const base::Closure& closure);
+  // Sets callback which will be called when MediaCrypto is ready. If
+  // |media_crypto_ready_cb| is null, previously set callback will be cleared.
+  void SetMediaCryptoReadyCB(const MediaCryptoReadyCB& media_crypto_ready_cb);
 
-  // Called after a MediaCrypto object is created.
+  // Called by Java after a MediaCrypto object is created.
   void OnMediaCryptoReady(JNIEnv* env, jobject j_media_drm);
 
   // Callbacks to resolve the promise for |promise_id|.
@@ -186,6 +201,9 @@
   // video playback.
   bool IsProtectedSurfaceRequired();
 
+  // We use this pointer when we post SetMediaCryptoReadyCB onto UI thread.
+  base::WeakPtr<MediaDrmBridge> WeakPtrForUIThread();
+
  private:
   MediaDrmBridge(const std::vector<uint8>& scheme_uuid,
                  const SessionMessageCB& session_message_cb,
@@ -199,6 +217,13 @@
   // Get the security level of the media.
   SecurityLevel GetSecurityLevel();
 
+  // A helper method that calls a |player_tracker_| method on correct thread.
+  void NotifyNewKeyOnCorrectThread();
+
+  // A helper method that calculates the |media_crypto_ready_cb_| arguments and
+  // run this callback.
+  void NotifyMediaCryptoReady(const MediaCryptoReadyCB& cb);
+
   // UUID of the key system.
   std::vector<uint8> scheme_uuid_;
 
@@ -212,14 +237,26 @@
   SessionKeysChangeCB session_keys_change_cb_;
   SessionExpirationUpdateCB session_expiration_update_cb_;
 
-  base::Closure media_crypto_ready_cb_;
+  MediaCryptoReadyCB media_crypto_ready_cb_;
 
   ResetCredentialsCB reset_credentials_cb_;
 
+  // The |player_tracker_| must be accessed by one thread only. It is accessed
+  // by the Media thread when |use_media_thread_| is true.
   PlayerTrackerImpl player_tracker_;
 
   CdmPromiseAdapter cdm_promise_adapter_;
 
+  // Object for posting tasks on UI thread.
+  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+  // This flag is set when we use media thread for certain callbacks.
+  const bool use_media_thread_;
+
+  // NOTE: Weak pointers must be invalidated before all other member variables.
+  base::WeakPtrFactory<MediaDrmBridge> media_weak_factory_;
+  base::WeakPtrFactory<MediaDrmBridge> ui_weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaDrmBridge);
 };
 
diff --git a/media/base/android/media_drm_bridge_unittest.cc b/media/base/android/media_drm_bridge_unittest.cc
index e4c08000..f215a42 100644
--- a/media/base/android/media_drm_bridge_unittest.cc
+++ b/media/base/android/media_drm_bridge_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/android/build_info.h"
 #include "base/basictypes.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -76,17 +77,20 @@
 }
 
 TEST(MediaDrmBridgeTest, CreateWithoutSessionSupport_Widevine) {
+  base::MessageLoop message_loop_;
   EXPECT_TRUE_IF_WIDEVINE_AVAILABLE(
       MediaDrmBridge::CreateWithoutSessionSupport(kWidevineKeySystem));
 }
 
 // Invalid key system is NOT supported regardless whether MediaDrm is available.
 TEST(MediaDrmBridgeTest, CreateWithoutSessionSupport_InvalidKeySystem) {
+  base::MessageLoop message_loop_;
   EXPECT_FALSE(MediaDrmBridge::CreateWithoutSessionSupport(kInvalidKeySystem));
 }
 
 TEST(MediaDrmBridgeTest, SetSecurityLevel_Widevine) {
-  scoped_ptr<MediaDrmBridge> media_drm_bridge =
+  base::MessageLoop message_loop_;
+  scoped_ptr<MediaDrmBridge, BrowserCdmDeleter> media_drm_bridge =
       MediaDrmBridge::CreateWithoutSessionSupport(kWidevineKeySystem);
   EXPECT_TRUE_IF_WIDEVINE_AVAILABLE(media_drm_bridge);
   if (!media_drm_bridge)
diff --git a/media/base/android/media_player_android.cc b/media/base/android/media_player_android.cc
index f583932c..ed38d971 100644
--- a/media/base/android/media_player_android.cc
+++ b/media/base/android/media_player_android.cc
@@ -5,15 +5,11 @@
 #include "media/base/android/media_player_android.h"
 
 #include "base/android/jni_android.h"
-#include "base/command_line.h"
 #include "base/logging.h"
-#include "base/metrics/field_trial.h"
 #include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
 #include "base/thread_task_runner_handle.h"
 #include "media/base/android/media_drm_bridge.h"
 #include "media/base/android/media_player_manager.h"
-#include "media/base/media_switches.h"
 
 namespace media {
 
@@ -89,19 +85,6 @@
   listener_->ReleaseMediaPlayerListenerResources();
 }
 
-// static
-bool MediaPlayerAndroid::UseMediaThread() {
-  const std::string group_name =
-      base::FieldTrialList::FindFullName("EnableMediaThreadForMediaPlayback");
-
-  if (base::CommandLine::ForCurrentProcess()->
-      HasSwitch(switches::kEnableMediaThreadForMediaPlayback)) {
-    return true;
-  }
-
-  return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE);
-}
-
 void MediaPlayerAndroid::DestroyListenerOnUIThread() {
   weak_factory_.InvalidateWeakPtrs();
   listener_.reset();
diff --git a/media/base/android/media_player_android.h b/media/base/android/media_player_android.h
index 864c024..303f8a6 100644
--- a/media/base/android/media_player_android.h
+++ b/media/base/android/media_player_android.h
@@ -102,9 +102,6 @@
   void AttachListener(jobject j_media_player);
   void DetachListener();
 
-  // Behavior controlled by finch flag.
-  static bool UseMediaThread();
-
  protected:
   MediaPlayerAndroid(int player_id,
                      MediaPlayerManager* manager,
diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc
index 4551520..1c117b70 100644
--- a/media/base/android/media_source_player.cc
+++ b/media/base/android/media_source_player.cc
@@ -18,6 +18,7 @@
 #include "media/base/android/audio_decoder_job.h"
 #include "media/base/android/media_player_manager.h"
 #include "media/base/android/video_decoder_job.h"
+#include "media/base/bind_to_current_loop.h"
 #include "media/base/timestamp_constants.h"
 
 namespace media {
@@ -258,9 +259,13 @@
   duration_ = duration;
 }
 
-void MediaSourcePlayer::OnMediaCryptoReady() {
+void MediaSourcePlayer::OnMediaCryptoReady(
+    MediaDrmBridge::JavaObjectPtr /* media_crypto */,
+    bool /* needs_protected_surface */) {
+  // Callback parameters are ignored in this player. They are intended for
+  // MediaCodecPlayer which uses a different threading scheme.
   DCHECK(!drm_bridge_->GetMediaCrypto().is_null());
-  drm_bridge_->SetMediaCryptoReadyCB(base::Closure());
+  drm_bridge_->SetMediaCryptoReadyCB(MediaDrmBridge::MediaCryptoReadyCB());
 
   // Retry decoder creation if the decoders are waiting for MediaCrypto.
   RetryDecoderCreation(true, true);
@@ -292,8 +297,9 @@
   video_decoder_job_->SetDrmBridge(drm_bridge_);
 
   if (drm_bridge_->GetMediaCrypto().is_null()) {
-    drm_bridge_->SetMediaCryptoReadyCB(
+    MediaDrmBridge::MediaCryptoReadyCB cb = BindToCurrentLoop(
         base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_));
+    drm_bridge_->SetMediaCryptoReadyCB(cb);
     return;
   }
 
diff --git a/media/base/android/media_source_player.h b/media/base/android/media_source_player.h
index ab3bda3e..bfa3935c 100644
--- a/media/base/android/media_source_player.h
+++ b/media/base/android/media_source_player.h
@@ -94,7 +94,8 @@
   base::android::ScopedJavaLocalRef<jobject> GetMediaCrypto();
 
   // Callback to notify that MediaCrypto is ready in |drm_bridge_|.
-  void OnMediaCryptoReady();
+  void OnMediaCryptoReady(MediaDrmBridge::JavaObjectPtr media_crypto,
+                          bool needs_protected_surface);
 
   // Handle pending events if all the decoder jobs are not currently decoding.
   void ProcessPendingEvents();
diff --git a/media/base/android/media_task_runner.cc b/media/base/android/media_task_runner.cc
new file mode 100644
index 0000000..a52919c
--- /dev/null
+++ b/media/base/android/media_task_runner.cc
@@ -0,0 +1,43 @@
+// Copyright 2015 The Chromium Authors. 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/android/media_task_runner.h"
+
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+class MediaThread : public base::Thread {
+ public:
+  MediaThread() : base::Thread("BrowserMediaThread") {
+    Start();
+  }
+};
+
+// Create media thread
+base::LazyInstance<MediaThread>::Leaky g_media_thread =
+    LAZY_INSTANCE_INITIALIZER;
+
+scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner() {
+  return g_media_thread.Pointer()->task_runner();
+}
+
+bool UseMediaThreadForMediaPlayback() {
+  const std::string group_name =
+      base::FieldTrialList::FindFullName("EnableMediaThreadForMediaPlayback");
+
+  if (base::CommandLine::ForCurrentProcess()->
+      HasSwitch(switches::kEnableMediaThreadForMediaPlayback)) {
+    return true;
+  }
+
+  return base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE);
+}
+
+}  // namespace media
diff --git a/media/base/android/media_task_runner.h b/media/base/android/media_task_runner.h
new file mode 100644
index 0000000..b91c547
--- /dev/null
+++ b/media/base/android/media_task_runner.h
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. 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_ANDROID_MEDIA_TASK_RUNNER_H_
+#define MEDIA_BASE_ANDROID_MEDIA_TASK_RUNNER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+// Returns the task runner for the media thread.
+MEDIA_EXPORT scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
+
+// Returns true if the MediaCodecPlayer (which works on Media thread) should be
+// used. This behavior is controlled by a finch flag.
+MEDIA_EXPORT bool UseMediaThreadForMediaPlayback();
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_ANDROID_MEDIA_TASK_RUNNER_H_
diff --git a/media/base/audio_renderer_mixer_input.cc b/media/base/audio_renderer_mixer_input.cc
index 21d0d35c..1b097ae 100644
--- a/media/base/audio_renderer_mixer_input.cc
+++ b/media/base/audio_renderer_mixer_input.cc
@@ -46,7 +46,11 @@
   DCHECK(initialized_);
   DCHECK(!playing_);
   DCHECK(!mixer_);
-  mixer_ = get_mixer_cb_.Run(params_, device_id_, security_origin_);
+  mixer_ = get_mixer_cb_.Run(params_, device_id_, security_origin_, nullptr);
+  if (!mixer_) {
+    callback_->OnRenderError();
+    return;
+  }
 
   // Note: OnRenderError() may be called immediately after this call returns.
   mixer_->AddErrorCallback(error_cb_);
@@ -98,7 +102,7 @@
 }
 
 OutputDevice* AudioRendererMixerInput::GetOutputDevice() {
-  return mixer_ ? this : nullptr;
+  return this;
 }
 
 void AudioRendererMixerInput::SwitchOutputDevice(
@@ -106,17 +110,23 @@
     const url::Origin& security_origin,
     const SwitchOutputDeviceCB& callback) {
   if (!mixer_) {
-    callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+    callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
     return;
   }
 
   if (device_id == device_id_) {
-    callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+    callback.Run(OUTPUT_DEVICE_STATUS_OK);
     return;
   }
 
+  OutputDeviceStatus new_mixer_status = OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
   AudioRendererMixer* new_mixer =
-      get_mixer_cb_.Run(params_, device_id, security_origin);
+      get_mixer_cb_.Run(params_, device_id, security_origin, &new_mixer_status);
+  if (new_mixer_status != OUTPUT_DEVICE_STATUS_OK) {
+    callback.Run(new_mixer_status);
+    return;
+  }
+
   bool was_playing = playing_;
   Stop();
   device_id_ = device_id;
@@ -127,13 +137,20 @@
   if (was_playing)
     Play();
 
-  callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+  callback.Run(OUTPUT_DEVICE_STATUS_OK);
 }
 
 AudioParameters AudioRendererMixerInput::GetOutputParameters() {
   return mixer_->GetOutputDevice()->GetOutputParameters();
 }
 
+OutputDeviceStatus AudioRendererMixerInput::GetDeviceStatus() {
+  if (!mixer_)
+    return OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
+
+  return mixer_->GetOutputDevice()->GetDeviceStatus();
+}
+
 double AudioRendererMixerInput::ProvideInput(AudioBus* audio_bus,
                                              base::TimeDelta buffer_delay) {
   int frames_filled = callback_->Render(
diff --git a/media/base/audio_renderer_mixer_input.h b/media/base/audio_renderer_mixer_input.h
index 10b43bd1..db7e8c70 100644
--- a/media/base/audio_renderer_mixer_input.h
+++ b/media/base/audio_renderer_mixer_input.h
@@ -21,10 +21,11 @@
       NON_EXPORTED_BASE(public OutputDevice),
       public AudioConverter::InputCallback {
  public:
-  typedef base::Callback<AudioRendererMixer*(
-      const AudioParameters& params,
-      const std::string& device_id,
-      const url::Origin& security_origin)> GetMixerCB;
+  typedef base::Callback<AudioRendererMixer*(const AudioParameters& params,
+                                             const std::string& device_id,
+                                             const url::Origin& security_origin,
+                                             OutputDeviceStatus* device_status)>
+      GetMixerCB;
   typedef base::Callback<void(const AudioParameters& params,
                               const std::string& device_id,
                               const url::Origin& security_origin)>
@@ -50,6 +51,7 @@
                           const url::Origin& security_origin,
                           const SwitchOutputDeviceCB& callback) override;
   AudioParameters GetOutputParameters() override;
+  OutputDeviceStatus GetDeviceStatus() override;
 
   // Called by AudioRendererMixer when an error occurs.
   void OnRenderError();
diff --git a/media/base/audio_renderer_mixer_input_unittest.cc b/media/base/audio_renderer_mixer_input_unittest.cc
index 31dd3a3..b660b89 100644
--- a/media/base/audio_renderer_mixer_input_unittest.cc
+++ b/media/base/audio_renderer_mixer_input_unittest.cc
@@ -19,6 +19,8 @@
 static const int kBufferSize = 8192;
 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
 static const std::string kDefaultDeviceId;
+static const std::string kUnauthorizedDeviceId("unauthorized");
+static const std::string kNonexistentDeviceId("nonexistent");
 static const url::Origin kDefaultSecurityOrigin;
 
 class AudioRendererMixerInputTest : public testing::Test {
@@ -45,7 +47,20 @@
 
   AudioRendererMixer* GetMixer(const AudioParameters& params,
                                const std::string& device_id,
-                               const url::Origin& security_origin) {
+                               const url::Origin& security_origin,
+                               OutputDeviceStatus* device_status) {
+    if (device_id == kNonexistentDeviceId) {
+      if (device_status)
+        *device_status = OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
+      return nullptr;
+    }
+
+    if (device_id == kUnauthorizedDeviceId) {
+      if (device_status)
+        *device_status = OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED;
+      return nullptr;
+    }
+
     size_t idx = device_id.empty() ? 0 : 1;
     if (!mixers_[idx]) {
       scoped_refptr<MockAudioRendererSink> sink = new MockAudioRendererSink();
@@ -56,6 +71,9 @@
           new AudioRendererMixer(audio_parameters_, audio_parameters_, sink));
     }
     EXPECT_CALL(*this, RemoveMixer(testing::_, device_id, testing::_));
+
+    if (device_status)
+      *device_status = OUTPUT_DEVICE_STATUS_OK;
     return mixers_[idx].get();
   }
 
@@ -68,8 +86,8 @@
                     const std::string&,
                     const url::Origin&));
 
-  MOCK_METHOD1(SwitchCallbackCalled, void(SwitchOutputDeviceResult));
-  void SwitchCallback(base::RunLoop* loop, SwitchOutputDeviceResult result) {
+  MOCK_METHOD1(SwitchCallbackCalled, void(OutputDeviceStatus));
+  void SwitchCallback(base::RunLoop* loop, OutputDeviceStatus result) {
     SwitchCallbackCalled(result);
     loop->Quit();
   }
@@ -140,7 +158,7 @@
 TEST_F(AudioRendererMixerInputTest, SwitchOutputDevice) {
   mixer_input_->Start();
   const std::string kDeviceId("mock-device-id");
-  EXPECT_CALL(*this, SwitchCallbackCalled(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS));
+  EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
   AudioRendererMixer* old_mixer = GetInputMixer();
   EXPECT_EQ(old_mixer, mixers_[0].get());
   base::RunLoop run_loop;
@@ -158,11 +176,11 @@
 // Test SwitchOutputDevice() to the same device as the current (default) device
 TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceToSameDevice) {
   mixer_input_->Start();
-  EXPECT_CALL(*this, SwitchCallbackCalled(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS));
+  EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
   AudioRendererMixer* old_mixer = GetInputMixer();
   base::RunLoop run_loop;
   mixer_input_->SwitchOutputDevice(
-      std::string(), url::Origin(),
+      kDefaultDeviceId, kDefaultSecurityOrigin,
       base::Bind(&AudioRendererMixerInputTest::SwitchCallback,
                  base::Unretained(this), &run_loop));
   run_loop.Run();
@@ -171,10 +189,37 @@
   mixer_input_->Stop();
 }
 
+// Test SwitchOutputDevice() to a nonexistent device
+TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceToNonexistentDevice) {
+  mixer_input_->Start();
+  EXPECT_CALL(*this,
+              SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND));
+  base::RunLoop run_loop;
+  mixer_input_->SwitchOutputDevice(
+      kNonexistentDeviceId, kDefaultSecurityOrigin,
+      base::Bind(&AudioRendererMixerInputTest::SwitchCallback,
+                 base::Unretained(this), &run_loop));
+  run_loop.Run();
+  mixer_input_->Stop();
+}
+
+// Test SwitchOutputDevice() to an unauthorized device
+TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceToUnauthorizedDevice) {
+  mixer_input_->Start();
+  EXPECT_CALL(*this,
+              SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED));
+  base::RunLoop run_loop;
+  mixer_input_->SwitchOutputDevice(
+      kUnauthorizedDeviceId, kDefaultSecurityOrigin,
+      base::Bind(&AudioRendererMixerInputTest::SwitchCallback,
+                 base::Unretained(this), &run_loop));
+  run_loop.Run();
+  mixer_input_->Stop();
+}
+
 // Test that calling SwitchOutputDevice() before Start() fails.
 TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceBeforeStart) {
-  EXPECT_CALL(*this,
-              SwitchCallbackCalled(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL));
+  EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
   base::RunLoop run_loop;
   mixer_input_->SwitchOutputDevice(
       std::string(), url::Origin(),
diff --git a/media/base/audio_renderer_mixer_unittest.cc b/media/base/audio_renderer_mixer_unittest.cc
index 836e9daa..b218fa0 100644
--- a/media/base/audio_renderer_mixer_unittest.cc
+++ b/media/base/audio_renderer_mixer_unittest.cc
@@ -73,7 +73,8 @@
 
   AudioRendererMixer* GetMixer(const AudioParameters& params,
                                const std::string& device_id,
-                               const url::Origin& security_origin) {
+                               const url::Origin& security_origin,
+                               OutputDeviceStatus* device_status) {
     return mixer_.get();
   }
 
diff --git a/media/base/browser_cdm.cc b/media/base/browser_cdm.cc
index 2c44e16..45a2ea2d 100644
--- a/media/base/browser_cdm.cc
+++ b/media/base/browser_cdm.cc
@@ -12,4 +12,9 @@
 BrowserCdm::~BrowserCdm() {
 }
 
+// For most subclasses we can delete on the caller thread.
+void BrowserCdm::DeleteOnCorrectThread() {
+  delete this;
+}
+
 }  // namespace media
diff --git a/media/base/browser_cdm.h b/media/base/browser_cdm.h
index f4902d8..5e4cb28 100644
--- a/media/base/browser_cdm.h
+++ b/media/base/browser_cdm.h
@@ -5,6 +5,7 @@
 #ifndef MEDIA_BASE_BROWSER_CDM_H_
 #define MEDIA_BASE_BROWSER_CDM_H_
 
+#include "base/memory/scoped_ptr.h"
 #include "media/base/media_export.h"
 #include "media/base/media_keys.h"
 #include "media/base/player_tracker.h"
@@ -16,6 +17,9 @@
  public:
   ~BrowserCdm() override;
 
+  // Virtual destructor. For most subclasses we can delete on the caller thread.
+  virtual void DeleteOnCorrectThread();
+
  protected:
    BrowserCdm();
 
@@ -23,6 +27,14 @@
   DISALLOW_COPY_AND_ASSIGN(BrowserCdm);
 };
 
+struct MEDIA_EXPORT BrowserCdmDeleter {
+  inline void operator()(BrowserCdm* ptr) const {
+    ptr->DeleteOnCorrectThread();
+  }
+};
+
+using ScopedBrowserCdmPtr = scoped_ptr<BrowserCdm, BrowserCdmDeleter>;
+
 }  // namespace media
 
 #endif  // MEDIA_BASE_BROWSER_CDM_H_
diff --git a/media/base/browser_cdm_factory.cc b/media/base/browser_cdm_factory.cc
index 88445d89..73fd4c7 100644
--- a/media/base/browser_cdm_factory.cc
+++ b/media/base/browser_cdm_factory.cc
@@ -21,7 +21,7 @@
   g_cdm_factory = factory;
 }
 
-scoped_ptr<BrowserCdm> CreateBrowserCdm(
+ScopedBrowserCdmPtr CreateBrowserCdm(
     const std::string& key_system,
     bool use_hw_secure_codecs,
     const SessionMessageCB& session_message_cb,
@@ -34,7 +34,7 @@
     SetBrowserCdmFactory(new BrowserCdmFactoryAndroid);
 #else
     LOG(ERROR) << "Cannot create BrowserCdm: no BrowserCdmFactory available!";
-    return scoped_ptr<BrowserCdm>();
+    return ScopedBrowserCdmPtr();
 #endif
   }
 
diff --git a/media/base/browser_cdm_factory.h b/media/base/browser_cdm_factory.h
index 2ccf1b41..99525a7 100644
--- a/media/base/browser_cdm_factory.h
+++ b/media/base/browser_cdm_factory.h
@@ -19,7 +19,7 @@
   BrowserCdmFactory() {}
   virtual ~BrowserCdmFactory() {}
 
-  virtual scoped_ptr<BrowserCdm> CreateBrowserCdm(
+  virtual ScopedBrowserCdmPtr CreateBrowserCdm(
       const std::string& key_system,
       bool use_hw_secure_codecs,
       const SessionMessageCB& session_message_cb,
@@ -41,7 +41,7 @@
 // |use_hw_secure_codecs| indicates that the CDM should be configured to use
 // hardware-secure codecs (for platforms that support it).
 // TODO(xhwang): Add ifdef for IPC based CDM.
-scoped_ptr<BrowserCdm> MEDIA_EXPORT
+ScopedBrowserCdmPtr MEDIA_EXPORT
 CreateBrowserCdm(const std::string& key_system,
                  bool use_hw_secure_codecs,
                  const SessionMessageCB& session_message_cb,
diff --git a/media/base/cdm_promise_adapter.cc b/media/base/cdm_promise_adapter.cc
index 70993b58..aed2830 100644
--- a/media/base/cdm_promise_adapter.cc
+++ b/media/base/cdm_promise_adapter.cc
@@ -13,10 +13,12 @@
 
 CdmPromiseAdapter::~CdmPromiseAdapter() {
   DCHECK(promises_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
   Clear();
 }
 
 uint32_t CdmPromiseAdapter::SavePromise(scoped_ptr<CdmPromise> promise) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   uint32_t promise_id = next_promise_id_++;
   promises_.add(promise_id, promise.Pass());
   return promise_id;
@@ -57,12 +59,14 @@
 
 void CdmPromiseAdapter::Clear() {
   // Reject all outstanding promises.
+  DCHECK(thread_checker_.CalledOnValidThread());
   for (auto& promise : promises_)
     promise.second->reject(MediaKeys::UNKNOWN_ERROR, 0, "Operation aborted.");
   promises_.clear();
 }
 
 scoped_ptr<CdmPromise> CdmPromiseAdapter::TakePromise(uint32_t promise_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   PromiseMap::iterator it = promises_.find(promise_id);
   if (it == promises_.end())
     return nullptr;
diff --git a/media/base/cdm_promise_adapter.h b/media/base/cdm_promise_adapter.h
index b078c0dd0..b6d5a89 100644
--- a/media/base/cdm_promise_adapter.h
+++ b/media/base/cdm_promise_adapter.h
@@ -9,6 +9,7 @@
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "media/base/cdm_promise.h"
 #include "media/base/media_export.h"
 
@@ -51,6 +52,7 @@
   uint32_t next_promise_id_;
   PromiseMap promises_;
 
+  base::ThreadChecker thread_checker_;
   DISALLOW_COPY_AND_ASSIGN(CdmPromiseAdapter);
 };
 
diff --git a/media/base/fake_media_resources.cc b/media/base/fake_media_resources.cc
new file mode 100644
index 0000000..67ac726
--- /dev/null
+++ b/media/base/fake_media_resources.cc
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/utf_string_conversions.h"
+#include "media/base/media_resources.h"
+
+namespace media {
+
+base::string16 FakeLocalizedStringProvider(MessageId message_id) {
+  if (message_id == DEFAULT_AUDIO_DEVICE_NAME)
+    return base::ASCIIToUTF16("Default");
+
+  return base::ASCIIToUTF16("FakeString");
+}
+
+void SetUpFakeMediaResources() {
+  SetLocalizedStringProvider(FakeLocalizedStringProvider);
+}
+
+}  // namespace media
diff --git a/media/base/fake_media_resources.h b/media/base/fake_media_resources.h
new file mode 100644
index 0000000..9a374bf
--- /dev/null
+++ b/media/base/fake_media_resources.h
@@ -0,0 +1,15 @@
+// Copyright 2015 The Chromium Authors. 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_FAKE_MEDIA_RESOURCES_H_
+#define MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_
+
+namespace media {
+
+// Call if tests require non-empty resource strings.
+void SetUpFakeMediaResources();
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_FAKE_MEDIA_RESOURCES_H_
diff --git a/media/base/fake_output_device.cc b/media/base/fake_output_device.cc
index 287aff9..2f7c8e7 100644
--- a/media/base/fake_output_device.cc
+++ b/media/base/fake_output_device.cc
@@ -8,14 +8,19 @@
 
 namespace media {
 
-FakeOutputDevice::FakeOutputDevice() {}
+FakeOutputDevice::FakeOutputDevice()
+    : FakeOutputDevice(OUTPUT_DEVICE_STATUS_OK) {}
+
+FakeOutputDevice::FakeOutputDevice(OutputDeviceStatus device_status)
+    : device_status_(device_status) {}
+
 FakeOutputDevice::~FakeOutputDevice() {}
 
 void FakeOutputDevice::SwitchOutputDevice(
     const std::string& device_id,
     const url::Origin& security_origin,
     const SwitchOutputDeviceCB& callback) {
-  callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
+  callback.Run(device_status_);
 }
 
 AudioParameters FakeOutputDevice::GetOutputParameters() {
@@ -24,4 +29,8 @@
       media::AudioParameters::kTelephoneSampleRate, 16, 1);
 }
 
+OutputDeviceStatus FakeOutputDevice::GetDeviceStatus() {
+  return device_status_;
+}
+
 }  // namespace media
diff --git a/media/base/fake_output_device.h b/media/base/fake_output_device.h
index 1d9129c..121a375 100644
--- a/media/base/fake_output_device.h
+++ b/media/base/fake_output_device.h
@@ -14,6 +14,7 @@
 class FakeOutputDevice : public OutputDevice {
  public:
   FakeOutputDevice();
+  explicit FakeOutputDevice(OutputDeviceStatus status);
   ~FakeOutputDevice() override;
 
   // OutputDevice implementation.
@@ -21,8 +22,10 @@
                           const url::Origin& security_origin,
                           const SwitchOutputDeviceCB& callback) override;
   AudioParameters GetOutputParameters() override;
+  OutputDeviceStatus GetDeviceStatus() override;
 
  private:
+  OutputDeviceStatus device_status_;
   DISALLOW_COPY_AND_ASSIGN(FakeOutputDevice);
 };
 
diff --git a/media/base/media_resources.cc b/media/base/media_resources.cc
new file mode 100644
index 0000000..d7259e91
--- /dev/null
+++ b/media/base/media_resources.cc
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. 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_resources.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace media {
+
+static LocalizedStringProvider g_localized_string_provider = nullptr;
+
+void SetLocalizedStringProvider(LocalizedStringProvider func) {
+  g_localized_string_provider = func;
+}
+
+#if !defined(OS_IOS)
+std::string GetLocalizedStringUTF8(MessageId message_id) {
+  return base::UTF16ToUTF8(GetLocalizedStringUTF16(message_id));
+}
+
+base::string16 GetLocalizedStringUTF16(MessageId message_id) {
+  return g_localized_string_provider ? g_localized_string_provider(message_id)
+                                     : base::string16();
+}
+#endif
+
+}  // namespace media
diff --git a/media/base/media_resources.h b/media/base/media_resources.h
new file mode 100644
index 0000000..52053f7
--- /dev/null
+++ b/media/base/media_resources.h
@@ -0,0 +1,52 @@
+// Copyright 2015 The Chromium Authors. 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_RESOURCES_H_
+#define MEDIA_BASE_MEDIA_RESOURCES_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+// The media layer can't access Chrome's resource bundle directly. This facility
+// allows clients to provide indirect access.
+
+// IDs that will get mapped to corresponding entries with IDS_ prefixes in
+// chrome/app/generated_resources.grd.
+enum MessageId {
+  DEFAULT_AUDIO_DEVICE_NAME,
+#if defined(OS_WIN)
+  COMMUNICATIONS_AUDIO_DEVICE_NAME,
+#endif
+#if defined(OS_CHROMEOS)
+  BEAMFORMING_ON_DEFAULT_AUDIO_INPUT_DEVICE_NAME,
+  BEAMFORMING_OFF_DEFAULT_AUDIO_INPUT_DEVICE_NAME,
+#endif
+};
+
+// Implementations are expected to convert MessageIds to generated_resources.grd
+// IDs and extract the matching string from Chrome's resource bundle (e.g.
+// through l10n_util::GetStringUTF16).
+using LocalizedStringProvider = base::string16 (*)(MessageId message_id);
+
+// Initializes the global LocalizedStringProvider function.
+MEDIA_EXPORT void SetLocalizedStringProvider(LocalizedStringProvider func);
+
+#if !defined(OS_IOS)
+// The LocalizedStringProvider has probably not been initialized on iOS. This
+// will give an early compile warning for clients attempting to use it.
+
+// Returns a resource string corresponding to |message_id|. See l10n_util.h.
+// Returns an empty string if the LocalizedStringProvider has not been
+// initialized or if the ID is unrecognized.
+std::string GetLocalizedStringUTF8(MessageId message_id);
+base::string16 GetLocalizedStringUTF16(MessageId message_id);
+#endif
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_MEDIA_RESOURCES_H_
diff --git a/media/base/mock_audio_renderer_sink.cc b/media/base/mock_audio_renderer_sink.cc
index f8ebec73..79653b2 100644
--- a/media/base/mock_audio_renderer_sink.cc
+++ b/media/base/mock_audio_renderer_sink.cc
@@ -6,9 +6,12 @@
 #include "media/base/fake_output_device.h"
 
 namespace media {
-
 MockAudioRendererSink::MockAudioRendererSink()
-    : output_device_(new FakeOutputDevice()) {}
+    : MockAudioRendererSink(OUTPUT_DEVICE_STATUS_OK) {}
+
+MockAudioRendererSink::MockAudioRendererSink(OutputDeviceStatus device_status)
+    : output_device_(new FakeOutputDevice(device_status)) {}
+
 MockAudioRendererSink::~MockAudioRendererSink() {}
 
 void MockAudioRendererSink::Initialize(const AudioParameters& params,
diff --git a/media/base/mock_audio_renderer_sink.h b/media/base/mock_audio_renderer_sink.h
index 9182c41..c44ac401 100644
--- a/media/base/mock_audio_renderer_sink.h
+++ b/media/base/mock_audio_renderer_sink.h
@@ -18,6 +18,7 @@
 class MockAudioRendererSink : public AudioRendererSink {
  public:
   MockAudioRendererSink();
+  explicit MockAudioRendererSink(OutputDeviceStatus device_status);
 
   MOCK_METHOD0(Start, void());
   MOCK_METHOD0(Stop, void());
diff --git a/media/base/output_device.h b/media/base/output_device.h
index fe35d6d..76f88c7 100644
--- a/media/base/output_device.h
+++ b/media/base/output_device.h
@@ -15,15 +15,15 @@
 namespace media {
 
 // Result of an audio output device switch operation
-enum SwitchOutputDeviceResult {
-  SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS = 0,
-  SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND,
-  SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED,
-  SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL,
-  SWITCH_OUTPUT_DEVICE_RESULT_LAST = SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL,
+enum OutputDeviceStatus {
+  OUTPUT_DEVICE_STATUS_OK = 0,
+  OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
+  OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
+  OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
+  OUTPUT_DEVICE_STATUS_LAST = OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
 };
 
-typedef base::Callback<void(SwitchOutputDeviceResult)> SwitchOutputDeviceCB;
+typedef base::Callback<void(OutputDeviceStatus)> SwitchOutputDeviceCB;
 
 // OutputDevice is an interface that allows performing operations related
 // audio output devices.
@@ -46,10 +46,18 @@
                                   const SwitchOutputDeviceCB& callback) = 0;
 
   // Returns the device's audio output parameters.
-  // If the parameters are not available, this method blocks until they
-  // become available. Must never be called on the IO thread.
+  // The return value is undefined if the device status (as returned by
+  // GetDeviceStatus()) is different from OUTPUT_DEVICE_STATUS_OK.
+  // If the parameters are not available, this method may block until they
+  // become available.
+  // This method must never be called on the IO thread.
   virtual AudioParameters GetOutputParameters() = 0;
 
+  // Returns the status of output device.
+  // If the status is not available, this method may block until it becomes
+  // available. Must never be called on the IO thread.
+  virtual OutputDeviceStatus GetDeviceStatus() = 0;
+
  protected:
   virtual ~OutputDevice() {}
 };
diff --git a/media/base/run_all_unittests.cc b/media/base/run_all_unittests.cc
index dfde2b5..97e799b 100644
--- a/media/base/run_all_unittests.cc
+++ b/media/base/run_all_unittests.cc
@@ -8,6 +8,7 @@
 #include "base/test/test_discardable_memory_allocator.h"
 #include "base/test/test_suite.h"
 #include "build/build_config.h"
+#include "media/base/fake_media_resources.h"
 #include "media/base/media.h"
 #include "media/base/media_switches.h"
 
@@ -47,6 +48,7 @@
   // Run this here instead of main() to ensure an AtExitManager is already
   // present.
   media::InitializeMediaLibrary();
+  media::SetUpFakeMediaResources();
 
   base::DiscardableMemoryAllocator::SetInstance(&discardable_memory_allocator_);
 }
diff --git a/media/blink/new_session_cdm_result_promise.cc b/media/blink/new_session_cdm_result_promise.cc
index 0a07614..f7f1446 100644
--- a/media/blink/new_session_cdm_result_promise.cc
+++ b/media/blink/new_session_cdm_result_promise.cc
@@ -10,6 +10,22 @@
 
 namespace media {
 
+static blink::WebContentDecryptionModuleResult::SessionStatus ConvertStatus(
+    SessionInitStatus status) {
+  switch (status) {
+    case SessionInitStatus::UNKNOWN_STATUS:
+      break;
+    case SessionInitStatus::NEW_SESSION:
+      return blink::WebContentDecryptionModuleResult::NewSession;
+    case SessionInitStatus::SESSION_NOT_FOUND:
+      return blink::WebContentDecryptionModuleResult::SessionNotFound;
+    case SessionInitStatus::SESSION_ALREADY_EXISTS:
+      return blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
+  }
+  NOTREACHED();
+  return blink::WebContentDecryptionModuleResult::SessionNotFound;
+}
+
 NewSessionCdmResultPromise::NewSessionCdmResultPromise(
     const blink::WebContentDecryptionModuleResult& result,
     const std::string& uma_name,
@@ -23,11 +39,20 @@
 }
 
 void NewSessionCdmResultPromise::resolve(const std::string& session_id) {
+  // |new_session_created_cb_| uses a WeakPtr<> and may not do anything
+  // if the session object has been destroyed.
+  SessionInitStatus status = SessionInitStatus::UNKNOWN_STATUS;
+  new_session_created_cb_.Run(session_id, &status);
+
+  if (status == SessionInitStatus::UNKNOWN_STATUS) {
+    reject(MediaKeys::INVALID_STATE_ERROR, 0,
+           "Cannot finish session initialization");
+    return;
+  }
+
   MarkPromiseSettled();
   ReportCdmResultUMA(uma_name_, SUCCESS);
-  blink::WebContentDecryptionModuleResult::SessionStatus status =
-      new_session_created_cb_.Run(session_id);
-  web_cdm_result_.completeWithSession(status);
+  web_cdm_result_.completeWithSession(ConvertStatus(status));
 }
 
 void NewSessionCdmResultPromise::reject(MediaKeys::Exception exception_code,
diff --git a/media/blink/new_session_cdm_result_promise.h b/media/blink/new_session_cdm_result_promise.h
index c4b657d..78e70b6 100644
--- a/media/blink/new_session_cdm_result_promise.h
+++ b/media/blink/new_session_cdm_result_promise.h
@@ -15,8 +15,23 @@
 
 namespace media {
 
-typedef base::Callback<blink::WebContentDecryptionModuleResult::SessionStatus(
-    const std::string& session_id)> SessionInitializedCB;
+enum class SessionInitStatus {
+  // Error creating the session.
+  UNKNOWN_STATUS,
+
+  // New session has been initialized.
+  NEW_SESSION,
+
+  // CDM could not find the requested session.
+  SESSION_NOT_FOUND,
+
+  // CDM already has a non-closed session that matches the provided
+  // parameters.
+  SESSION_ALREADY_EXISTS
+};
+
+typedef base::Callback<void(const std::string& session_id,
+                            SessionInitStatus* status)> SessionInitializedCB;
 
 // Special class for resolving a new session promise. Resolving a new session
 // promise returns the session ID (as a string), but the blink promise needs
@@ -43,7 +58,7 @@
   // UMA name to report result to.
   std::string uma_name_;
 
-  // Called on resolve() to convert the session ID into a SessionStatus to
+  // Called on resolve() to convert the session ID into a SessionInitStatus to
   // be reported to blink.
   SessionInitializedCB new_session_created_cb_;
 
diff --git a/media/blink/skcanvas_video_renderer.cc b/media/blink/skcanvas_video_renderer.cc
index 546ab8a..132e0da 100644
--- a/media/blink/skcanvas_video_renderer.cc
+++ b/media/blink/skcanvas_video_renderer.cc
@@ -510,7 +510,8 @@
           static_cast<uint8*>(rgb_pixels),
           row_bytes,
           video_frame->visible_rect().width(),
-          video_frame->visible_rect().height());
+          video_frame->visible_rect().height(),
+          1);  // 1 = enable RGB premultiplication by Alpha.
       break;
 
     case PIXEL_FORMAT_YV24:
diff --git a/media/blink/webcontentdecryptionmodulesession_impl.cc b/media/blink/webcontentdecryptionmodulesession_impl.cc
index 8b4ebdb..55b69d5b 100644
--- a/media/blink/webcontentdecryptionmodulesession_impl.cc
+++ b/media/blink/webcontentdecryptionmodulesession_impl.cc
@@ -18,7 +18,6 @@
 #include "media/base/media_keys.h"
 #include "media/blink/cdm_result_promise.h"
 #include "media/blink/cdm_session_adapter.h"
-#include "media/blink/new_session_cdm_result_promise.h"
 #include "media/blink/webmediaplayer_util.h"
 #include "media/cdm/json_web_key.h"
 #include "media/cdm/key_system_names.h"
@@ -226,6 +225,7 @@
 
 WebContentDecryptionModuleSessionImpl::
     ~WebContentDecryptionModuleSessionImpl() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   if (!session_id_.empty())
     adapter_->UnregisterSession(session_id_);
 }
@@ -246,6 +246,7 @@
     blink::WebContentDecryptionModuleResult result) {
   DCHECK(init_data);
   DCHECK(session_id_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   // From https://w3c.github.io/encrypted-media/#generateRequest.
   // 5. If the Key System implementation represented by this object's cdm
@@ -302,7 +303,7 @@
           result, adapter_->GetKeySystemUMAPrefix() + kGenerateRequestUMAName,
           base::Bind(
               &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
-              base::Unretained(this)))));
+              weak_ptr_factory_.GetWeakPtr()))));
 }
 
 void WebContentDecryptionModuleSessionImpl::load(
@@ -310,6 +311,7 @@
     blink::WebContentDecryptionModuleResult result) {
   DCHECK(!session_id.isEmpty());
   DCHECK(session_id_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   std::string sanitized_session_id;
   if (!SanitizeSessionId(session_id, &sanitized_session_id)) {
@@ -328,7 +330,7 @@
           result, adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName,
           base::Bind(
               &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
-              base::Unretained(this)))));
+              weak_ptr_factory_.GetWeakPtr()))));
 }
 
 void WebContentDecryptionModuleSessionImpl::update(
@@ -337,6 +339,7 @@
     blink::WebContentDecryptionModuleResult result) {
   DCHECK(response);
   DCHECK(!session_id_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   std::vector<uint8> sanitized_response;
   if (!SanitizeResponse(adapter_->GetKeySystem(), response, response_length,
@@ -356,6 +359,7 @@
 void WebContentDecryptionModuleSessionImpl::close(
     blink::WebContentDecryptionModuleResult result) {
   DCHECK(!session_id_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
   adapter_->CloseSession(
       session_id_,
       scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>(
@@ -365,6 +369,7 @@
 void WebContentDecryptionModuleSessionImpl::remove(
     blink::WebContentDecryptionModuleResult result) {
   DCHECK(!session_id_.empty());
+  DCHECK(thread_checker_.CalledOnValidThread());
   adapter_->RemoveSession(
       session_id_,
       scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>(
@@ -375,6 +380,7 @@
     MediaKeys::MessageType message_type,
     const std::vector<uint8>& message) {
   DCHECK(client_) << "Client not set before message event";
+  DCHECK(thread_checker_.CalledOnValidThread());
   client_->message(convertMessageType(message_type), vector_as_array(&message),
                    message.size());
 }
@@ -382,6 +388,7 @@
 void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
     bool has_additional_usable_key,
     CdmKeysInfo keys_info) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   blink::WebVector<blink::WebEncryptedMediaKeyInformation> keys(
       keys_info.size());
   for (size_t i = 0; i < keys_info.size(); ++i) {
@@ -398,10 +405,12 @@
 
 void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
     const base::Time& new_expiry_time) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   client_->expirationChanged(new_expiry_time.ToJsTime());
 }
 
 void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   if (is_closed_)
     return;
 
@@ -409,18 +418,22 @@
   client_->close();
 }
 
-blink::WebContentDecryptionModuleResult::SessionStatus
-WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
-    const std::string& session_id) {
+void WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
+    const std::string& session_id,
+    SessionInitStatus* status) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   // CDM will return NULL if the session to be loaded can't be found.
-  if (session_id.empty())
-    return blink::WebContentDecryptionModuleResult::SessionNotFound;
+  if (session_id.empty()) {
+    *status = SessionInitStatus::SESSION_NOT_FOUND;
+    return;
+  }
 
   DCHECK(session_id_.empty()) << "Session ID may not be changed once set.";
   session_id_ = session_id;
-  return adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr())
-             ? blink::WebContentDecryptionModuleResult::NewSession
-             : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
+  *status =
+      adapter_->RegisterSession(session_id_, weak_ptr_factory_.GetWeakPtr())
+          ? SessionInitStatus::NEW_SESSION
+          : SessionInitStatus::SESSION_ALREADY_EXISTS;
 }
 
 }  // namespace media
diff --git a/media/blink/webcontentdecryptionmodulesession_impl.h b/media/blink/webcontentdecryptionmodulesession_impl.h
index a9a3649..9a635097 100644
--- a/media/blink/webcontentdecryptionmodulesession_impl.h
+++ b/media/blink/webcontentdecryptionmodulesession_impl.h
@@ -12,7 +12,9 @@
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "media/base/media_keys.h"
+#include "media/blink/new_session_cdm_result_promise.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModuleSession.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 
@@ -55,9 +57,10 @@
   void OnSessionClosed();
 
  private:
-  // Called when a new session is created.
-  blink::WebContentDecryptionModuleResult::SessionStatus OnSessionInitialized(
-      const std::string& session_id);
+  // Called when a new session is created or loaded. |status| is set as
+  // appropriate, depending on whether the session already exists or not.
+  void OnSessionInitialized(const std::string& session_id,
+                            SessionInitStatus* status);
 
   scoped_refptr<CdmSessionAdapter> adapter_;
 
@@ -74,6 +77,7 @@
   // closed() event.
   bool is_closed_;
 
+  base::ThreadChecker thread_checker_;
   // Since promises will live until they are fired, use a weak reference when
   // creating a promise in case this class disappears before the promise
   // actually fires.
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 2b7cd1a..2726552 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -410,7 +410,7 @@
         GURL(frame_->securityOrigin().toString().utf8()));
     output_device->SwitchOutputDevice(device_id_str, security_origin, callback);
   } else {
-    callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
+    callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
   }
 }
 
diff --git a/media/blink/webmediaplayer_util.cc b/media/blink/webmediaplayer_util.cc
index 15707de..f017975 100644
--- a/media/blink/webmediaplayer_util.cc
+++ b/media/blink/webmediaplayer_util.cc
@@ -199,7 +199,7 @@
       : web_callback_(other.web_callback_.Pass()) {}
   ~SetSinkIdCallback() {}
   friend void RunSetSinkIdCallback(const SetSinkIdCallback& callback,
-                                   SwitchOutputDeviceResult result);
+                                   OutputDeviceStatus result);
 
  private:
   // Mutable is required so that Pass() can be called in the copy
@@ -208,25 +208,25 @@
 };
 
 void RunSetSinkIdCallback(const SetSinkIdCallback& callback,
-                          SwitchOutputDeviceResult result) {
+                          OutputDeviceStatus result) {
   DVLOG(1) << __FUNCTION__;
   if (!callback.web_callback_)
     return;
 
   switch (result) {
-    case SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS:
+    case OUTPUT_DEVICE_STATUS_OK:
       callback.web_callback_->onSuccess();
       break;
-    case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND:
+    case OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND:
       callback.web_callback_->onError(new blink::WebSetSinkIdError(
           blink::WebSetSinkIdError::ErrorTypeNotFound, "Device not found"));
       break;
-    case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED:
+    case OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED:
       callback.web_callback_->onError(new blink::WebSetSinkIdError(
           blink::WebSetSinkIdError::ErrorTypeSecurity,
           "No permission to access device"));
       break;
-    case SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL:
+    case OUTPUT_DEVICE_STATUS_ERROR_INTERNAL:
       callback.web_callback_->onError(new blink::WebSetSinkIdError(
           blink::WebSetSinkIdError::ErrorTypeAbort,
           "The requested operation could be performed and was aborted"));
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn
index 61452ea..188cfca8 100644
--- a/media/cast/BUILD.gn
+++ b/media/cast/BUILD.gn
@@ -137,6 +137,8 @@
     "sender/video_sender.h",
     "sender/vp8_encoder.cc",
     "sender/vp8_encoder.h",
+    "sender/vp8_quantizer_parser.cc",
+    "sender/vp8_quantizer_parser.h",
   ]
 
   deps = [
@@ -164,6 +166,8 @@
       "sender/video_encoder_impl.h",
       "sender/vp8_encoder.cc",
       "sender/vp8_encoder.h",
+      "sender/vp8_quantizer_parser.cc",
+      "sender/vp8_quantizer_parser.h",
     ]
   }
 
@@ -324,6 +328,7 @@
     "sender/fake_video_encode_accelerator_factory.h",
     "sender/video_encoder_unittest.cc",
     "sender/video_sender_unittest.cc",
+    "sender/vp8_quantizer_parser_unittest.cc",
     "test/end2end_unittest.cc",
     "test/fake_receiver_time_offset_estimator.cc",
     "test/fake_receiver_time_offset_estimator.h",
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp
index 044ad2db..b2acc85 100644
--- a/media/cast/cast.gyp
+++ b/media/cast/cast.gyp
@@ -178,6 +178,8 @@
         'sender/video_sender.h',
         'sender/vp8_encoder.cc',
         'sender/vp8_encoder.h',
+        'sender/vp8_quantizer_parser.h',
+        'sender/vp8_quantizer_parser.cc',
       ], # source
       'conditions': [
         # use a restricted subset of media and no software codecs on iOS
@@ -195,6 +197,8 @@
             'sender/video_encoder_impl.h',
             'sender/vp8_encoder.cc',
             'sender/vp8_encoder.h',
+            'sender/vp8_quantizer_parser.cc',
+	    'sender/vp8_quantizer_parser.h', 
           ],
         }], # OS=="ios"
         # iOS and OS X encoders
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi
index 9e439e0..b13bb5b0 100644
--- a/media/cast/cast_testing.gypi
+++ b/media/cast/cast_testing.gypi
@@ -68,6 +68,7 @@
         # the tools compile correctly.
         'cast_tools',
         '<(DEPTH)/base/base.gyp:test_support_base',
+        '<(DEPTH)/media/media.gyp:media_test_support',
         '<(DEPTH)/net/net.gyp:net',
         '<(DEPTH)/testing/gmock.gyp:gmock',
         '<(DEPTH)/testing/gtest.gyp:gtest',
@@ -120,6 +121,7 @@
         'sender/fake_video_encode_accelerator_factory.h',
         'sender/video_encoder_unittest.cc',
         'sender/video_sender_unittest.cc',
+        'sender/vp8_quantizer_parser_unittest.cc',
         'test/end2end_unittest.cc',
         'test/fake_receiver_time_offset_estimator.cc',
         'test/fake_receiver_time_offset_estimator.h',
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc
index 3a81f3e..a44888e3 100644
--- a/media/cast/sender/external_video_encoder.cc
+++ b/media/cast/sender/external_video_encoder.cc
@@ -18,6 +18,7 @@
 #include "media/cast/cast_defines.h"
 #include "media/cast/logging/logging_defines.h"
 #include "media/cast/net/cast_transport_config.h"
+#include "media/cast/sender/vp8_quantizer_parser.h"
 
 namespace {
 
@@ -92,8 +93,9 @@
         encoder_active_(false),
         next_frame_id_(0u),
         key_frame_encountered_(false),
-        requested_bit_rate_(-1) {
-  }
+        codec_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
+        vp8_key_frame_parsable_(false),
+        requested_bit_rate_(-1) {}
 
   base::SingleThreadTaskRunner* task_runner() const {
     return task_runner_.get();
@@ -110,6 +112,7 @@
         media::PIXEL_FORMAT_I420, frame_size, codec_profile, start_bit_rate,
         this);
     next_frame_id_ = first_frame_id;
+    codec_profile_ = codec_profile;
 
     UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess",
                           encoder_active_);
@@ -249,18 +252,48 @@
         encoded_frame->deadline_utilization =
             processing_time.InSecondsF() / frame_duration.InSecondsF();
 
-        // See vp8_encoder.cc for an explanation of this math.  Here, we are
-        // computing a substitute value for |quantizer| using the
-        // QuantizerEstimator.
         const double actual_bit_rate =
             encoded_frame->data.size() * 8.0 / frame_duration.InSecondsF();
         DCHECK_GT(request.target_bit_rate, 0);
         const double bitrate_utilization =
             actual_bit_rate / request.target_bit_rate;
-        const double quantizer =
-            (encoded_frame->dependency == EncodedFrame::KEY) ?
-            quantizer_estimator_.EstimateForKeyFrame(*request.video_frame) :
-            quantizer_estimator_.EstimateForDeltaFrame(*request.video_frame);
+        double quantizer = QuantizerEstimator::NO_RESULT;
+        if (codec_profile_ == media::VP8PROFILE_ANY) {
+          // If the quantizer can be parsed from the key frame, try to parse
+          // the following delta frames as well.
+          // Otherwise, switch back to entropy estimation for the key frame
+          // and all the following delta frames.
+          if (key_frame || vp8_key_frame_parsable_) {
+            quantizer = ParseVp8HeaderQuantizer(
+                reinterpret_cast<const uint8*>(encoded_frame->data.data()),
+                encoded_frame->data.size());
+            if (quantizer < 0) {
+              LOG(ERROR) << "Unable to parse VP8 quantizer from encoded "
+                         << (key_frame ? "key" : "delta")
+                         << " frame, id=" << encoded_frame->frame_id;
+              if (key_frame) {
+                vp8_key_frame_parsable_ = false;
+                quantizer = quantizer_estimator_.EstimateForKeyFrame(
+                    *request.video_frame);
+              } else {
+                quantizer = QuantizerEstimator::NO_RESULT;
+              }
+            } else {
+              if (key_frame) {
+                vp8_key_frame_parsable_ = true;
+              }
+            }
+          } else {
+            quantizer = quantizer_estimator_.EstimateForDeltaFrame(
+                *request.video_frame);
+          }
+        } else {
+          quantizer = (encoded_frame->dependency == EncodedFrame::KEY)
+                          ? quantizer_estimator_.EstimateForKeyFrame(
+                                *request.video_frame)
+                          : quantizer_estimator_.EstimateForDeltaFrame(
+                                *request.video_frame);
+        }
         if (quantizer != QuantizerEstimator::NO_RESULT) {
           encoded_frame->lossy_utilization = bitrate_utilization *
               (quantizer / QuantizerEstimator::MAX_VP8_QUANTIZER);
@@ -345,6 +378,8 @@
   uint32 next_frame_id_;
   bool key_frame_encountered_;
   std::string stream_header_;
+  VideoCodecProfile codec_profile_;
+  bool vp8_key_frame_parsable_;
 
   // Shared memory buffers for output with the VideoAccelerator.
   ScopedVector<base::SharedMemory> output_buffers_;
diff --git a/media/cast/sender/vp8_quantizer_parser.cc b/media/cast/sender/vp8_quantizer_parser.cc
new file mode 100644
index 0000000..1af91f9
--- /dev/null
+++ b/media/cast/sender/vp8_quantizer_parser.cc
@@ -0,0 +1,209 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/sender/vp8_quantizer_parser.h"
+#include "base/logging.h"
+
+namespace media {
+namespace cast {
+
+namespace {
+// Vp8BitReader is a re-implementation of a subset of the VP8 entropy decoder.
+// It is used to decompress the VP8 bitstream for the purposes of quickly
+// parsing the VP8 frame headers.  It is mostly the exact same implementation
+// found in third_party/libvpx/.../vp8/decoder/dboolhuff.h except that only the
+// portion of the implementation needed to parse the frame headers is present.
+// As of this writing, the implementation in libvpx could not be re-used
+// because of the way that the code is structured, and lack of the necessary
+// parts being exported.
+class Vp8BitReader {
+ public:
+  Vp8BitReader(const uint8* data, size_t size)
+      : encoded_data_(data), encoded_data_end_(data + size) {
+    Vp8DecoderReadBytes();
+  }
+  ~Vp8BitReader() {}
+
+  // Decode one bit. The output is 0 or 1.
+  unsigned int DecodeBit();
+  // Decode a value with |num_bits|. The decoding order is MSB first.
+  unsigned int DecodeValue(unsigned int num_bits);
+
+ private:
+  // Read new bytes frome the encoded data buffer until |bit_count_| > 0.
+  void Vp8DecoderReadBytes();
+
+  const uint8* encoded_data_;            // Current byte to decode.
+  const uint8* const encoded_data_end_;  // The end of the byte to decode.
+  // The following two variables are maintained by the decoder.
+  // General decoding rule:
+  // If |value_| is in the range of 0 to half of |range_|, output 0.
+  // Otherwise output 1.
+  // |range_| and |value_| need to be shifted when necessary to avoid underflow.
+  unsigned int range_ = 255;
+  unsigned int value_ = 0;
+  // Number of valid bits left to decode. Initializing it to -8 to let the
+  // decoder load two bytes at the beginning. The lower byte is used as
+  // a buffer byte. During the decoding, decoder needs to call
+  // Vp8DecoderReadBytes() to load new bytes when it becomes negative.
+  int bit_count_ = -8;
+
+  DISALLOW_COPY_AND_ASSIGN(Vp8BitReader);
+};
+
+// The number of bits to be left-shifted to make the variable range_ over 128.
+const uint8 vp8_shift[128] = {
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+// Mapping from the q_index(0-127) to the quantizer value(0-63).
+const uint8 vp8_quantizer_lookup[128] = {
+    0,  1,  2,  3,  4,  5,  6,  6,  7,  8,  9,  10, 10, 11, 12, 12, 13, 13, 14,
+    15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 28, 28, 29, 29,
+    30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39,
+    39, 40, 40, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46,
+    46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52,
+    53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59,
+    59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63};
+
+void Vp8BitReader::Vp8DecoderReadBytes() {
+  int shift = -bit_count_;
+  while ((shift >= 0) && (encoded_data_ < encoded_data_end_)) {
+    bit_count_ += 8;
+    value_ |= static_cast<unsigned int>(*encoded_data_) << shift;
+    ++encoded_data_;
+    shift -= 8;
+  }
+}
+
+unsigned int Vp8BitReader::DecodeBit() {
+  unsigned int decoded_bit = 0;
+  unsigned int split = 1 + (((range_ - 1) * 128) >> 8);
+  if (bit_count_ < 0) {
+    Vp8DecoderReadBytes();
+  }
+  DCHECK_GE(bit_count_, 0);
+  unsigned int shifted_split = split << 8;
+  if (value_ >= shifted_split) {
+    range_ -= split;
+    value_ -= shifted_split;
+    decoded_bit = 1;
+  } else {
+    range_ = split;
+  }
+  if (range_ < 128) {
+    int shift = vp8_shift[range_];
+    range_ <<= shift;
+    value_ <<= shift;
+    bit_count_ -= shift;
+  }
+  return decoded_bit;
+}
+
+unsigned int Vp8BitReader::DecodeValue(unsigned int num_bits) {
+  unsigned int decoded_value = 0;
+  for (int i = static_cast<int>(num_bits) - 1; i >= 0; i--) {
+    decoded_value |= (DecodeBit() << i);
+  }
+  return decoded_value;
+}
+
+// Parse the Segment Header part in the first partition.
+void ParseSegmentHeader(Vp8BitReader* bit_reader) {
+  const bool segmentation_enabled = (bit_reader->DecodeBit() != 0);
+  DVLOG(2) << "segmentation_enabled:" << segmentation_enabled;
+  if (segmentation_enabled) {
+    const bool update_mb_segmentation_map = (bit_reader->DecodeBit() != 0);
+    const bool update_mb_segmentation_data = (bit_reader->DecodeBit() != 0);
+    DVLOG(2) << "update_mb_segmentation_data:" << update_mb_segmentation_data;
+    if (update_mb_segmentation_data) {
+      bit_reader->DecodeBit();
+      for (int i = 0; i < 4; ++i) {
+        if (bit_reader->DecodeBit()) {
+          bit_reader->DecodeValue(7 + 1);  // Parse 7 bits value + 1 sign bit.
+        }
+      }
+      for (int i = 0; i < 4; ++i) {
+        if (bit_reader->DecodeBit()) {
+          bit_reader->DecodeValue(6 + 1);  // Parse 6 bits value + 1 sign bit.
+        }
+      }
+    }
+
+    if (update_mb_segmentation_map) {
+      for (int i = 0; i < 3; ++i) {
+        if (bit_reader->DecodeBit()) {
+          bit_reader->DecodeValue(8);
+        }
+      }
+    }
+  }
+}
+
+// Parse the Filter Header in the first partition.
+void ParseFilterHeader(Vp8BitReader* bit_reader) {
+  // Parse 1 bit filter_type + 6 bits loop_filter_level + 3 bits
+  // sharpness_level.
+  bit_reader->DecodeValue(1 + 6 + 3);
+  if (bit_reader->DecodeBit()) {
+    if (bit_reader->DecodeBit()) {
+      for (int i = 0; i < 4; ++i) {
+        if (bit_reader->DecodeBit()) {
+          bit_reader->DecodeValue(6 + 1);  // Parse 6 bits value + 1 sign bit.
+        }
+      }
+      for (int i = 0; i < 4; ++i) {
+        if (bit_reader->DecodeBit()) {
+          bit_reader->DecodeValue(6 + 1);  // Parse 6 bits value + 1 sign bit.
+        }
+      }
+    }
+  }
+}
+}  // unnamed namespace
+
+int ParseVp8HeaderQuantizer(const uint8* encoded_data, size_t size) {
+  DCHECK(encoded_data);
+  if (size <= 3) {
+    return -1;
+  }
+  const bool is_key = !(encoded_data[0] & 1);
+  const unsigned int header_3bytes =
+      encoded_data[0] | (encoded_data[1] << 8) | (encoded_data[2] << 16);
+  // Parse the size of the first partition.
+  unsigned int partition_size = (header_3bytes >> 5);
+  encoded_data += 3;  // Skip 3 bytes.
+  size -= 3;
+  if (is_key) {
+    if (size <= 7) {
+      return -1;
+    }
+    encoded_data += 7;  // Skip 7 bytes.
+    size -= 7;
+  }
+  if (size < partition_size) {
+    return -1;
+  }
+  Vp8BitReader bit_reader(encoded_data, partition_size);
+  if (is_key) {
+    bit_reader.DecodeValue(1 + 1);  // Parse two bits: color_space + clamp_type.
+  }
+  ParseSegmentHeader(&bit_reader);
+  ParseFilterHeader(&bit_reader);
+  // Parse the number of coefficient data partitions.
+  bit_reader.DecodeValue(2);
+  // Parse the base q_index.
+  uint8 q_index = static_cast<uint8>(bit_reader.DecodeValue(7));
+  if (q_index > 127) {
+    return 63;
+  }
+  return vp8_quantizer_lookup[q_index];
+}
+
+}  //  namespace cast
+}  //  namespace media
diff --git a/media/cast/sender/vp8_quantizer_parser.h b/media/cast/sender/vp8_quantizer_parser.h
new file mode 100644
index 0000000..abd0d5e
--- /dev/null
+++ b/media/cast/sender/vp8_quantizer_parser.h
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAST_SENDER_VP8_QUANTIZER_PARSER_H_
+#define MEDIA_CAST_SENDER_VP8_QUANTIZER_PARSER_H_
+
+#include "media/cast/cast_config.h"
+
+namespace media {
+namespace cast {
+
+// Partially parse / skip data in the header and the first partition,
+// and return the base quantizer in the range [0,63], or -1 on parse error.
+int ParseVp8HeaderQuantizer(const uint8* data, size_t size);
+
+}  // namespace cast
+}  // namespace media
+
+#endif  // MEDIA_CAST_SENDER_VP8_QUANTIZER_PARSER_H_
diff --git a/media/cast/sender/vp8_quantizer_parser_unittest.cc b/media/cast/sender/vp8_quantizer_parser_unittest.cc
new file mode 100644
index 0000000..9d96900
--- /dev/null
+++ b/media/cast/sender/vp8_quantizer_parser_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstdlib>
+
+#include "base/time/time.h"
+#include "media/cast/cast_config.h"
+#include "media/cast/receiver/video_decoder.h"
+#include "media/cast/sender/sender_encoded_frame.h"
+#include "media/cast/sender/vp8_encoder.h"
+#include "media/cast/sender/vp8_quantizer_parser.h"
+#include "media/cast/test/utility/default_config.h"
+#include "media/cast/test/utility/video_utility.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace cast {
+
+namespace {
+const int kWidth = 320;
+const int kHeight = 240;
+const int kFrameRate = 10;
+const int kQp = 20;
+
+VideoSenderConfig GetVideoConfigForTest() {
+  VideoSenderConfig config = GetDefaultVideoSenderConfig();
+  config.codec = CODEC_VIDEO_VP8;
+  config.use_external_encoder = false;
+  config.max_frame_rate = kFrameRate;
+  config.min_qp = kQp;
+  config.max_qp = kQp;
+  return config;
+}
+}  // unnamed namespace
+
+class Vp8QuantizerParserTest : public ::testing::Test {
+ public:
+  Vp8QuantizerParserTest() : video_config_(GetVideoConfigForTest()) {}
+
+  // Call vp8 software encoder to encode one randomly generated frame.
+  void EncodeOneFrame(SenderEncodedFrame* encoded_frame) {
+    const gfx::Size frame_size = gfx::Size(kWidth, kHeight);
+    const scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateFrame(
+        PIXEL_FORMAT_YV12, frame_size, gfx::Rect(frame_size), frame_size,
+        next_frame_timestamp_);
+    const base::TimeTicks reference_time =
+        base::TimeTicks::UnixEpoch() + next_frame_timestamp_;
+    next_frame_timestamp_ += base::TimeDelta::FromSeconds(1) / kFrameRate;
+    PopulateVideoFrameWithNoise(video_frame.get());
+    vp8_encoder_->Encode(video_frame, reference_time, encoded_frame);
+  }
+
+  // Update the vp8 encoder with the new quantizer.
+  void UpdateQuantizer(int qp) {
+    DCHECK((qp > 3) && (qp < 64));
+    video_config_.min_qp = qp;
+    video_config_.max_qp = qp;
+    RecreateVp8Encoder();
+  }
+
+ protected:
+  void SetUp() final {
+    next_frame_timestamp_ = base::TimeDelta();
+    RecreateVp8Encoder();
+  }
+
+ private:
+  // Reconstruct a vp8 encoder with new config since the Vp8Encoder
+  // class has no interface to update the config.
+  void RecreateVp8Encoder() {
+    vp8_encoder_.reset(new Vp8Encoder(video_config_));
+    vp8_encoder_->Initialize();
+  }
+
+  base::TimeDelta next_frame_timestamp_;
+  VideoSenderConfig video_config_;
+  scoped_ptr<Vp8Encoder> vp8_encoder_;
+
+  DISALLOW_COPY_AND_ASSIGN(Vp8QuantizerParserTest);
+};
+
+// Encode 5 frames to test the cases with insufficient data input.
+TEST_F(Vp8QuantizerParserTest, InsufficientData) {
+  for (int i = 0; i < 5; ++i) {
+    scoped_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame());
+    const uint8* encoded_data =
+        reinterpret_cast<const uint8*>(encoded_frame->data.data());
+    // Null input.
+    int decoded_quantizer =
+        ParseVp8HeaderQuantizer(encoded_data, encoded_frame->data.size());
+    EXPECT_EQ(-1, decoded_quantizer);
+    EncodeOneFrame(encoded_frame.get());
+    encoded_data = reinterpret_cast<const uint8*>(encoded_frame->data.data());
+    // Zero bytes should not be enough to decode the quantizer value.
+    decoded_quantizer = ParseVp8HeaderQuantizer(encoded_data, 0);
+    EXPECT_EQ(-1, decoded_quantizer);
+    // Three bytes should not be enough to decode the quantizer value..
+    decoded_quantizer = ParseVp8HeaderQuantizer(encoded_data, 3);
+    EXPECT_EQ(-1, decoded_quantizer);
+    unsigned int first_partition_size =
+        (encoded_data[0] | (encoded_data[1] << 8) | (encoded_data[2] << 16)) >>
+        5;
+    if (encoded_frame->dependency == EncodedFrame::KEY) {
+      // Ten bytes should not be enough to decode the quanitizer value
+      // for a Key frame.
+      decoded_quantizer = ParseVp8HeaderQuantizer(encoded_data, 10);
+      EXPECT_EQ(-1, decoded_quantizer);
+      // One byte less than needed to decode the quantizer value.
+      decoded_quantizer =
+          ParseVp8HeaderQuantizer(encoded_data, 10 + first_partition_size - 1);
+      EXPECT_EQ(-1, decoded_quantizer);
+      // Minimum number of bytes to decode the quantizer value.
+      decoded_quantizer =
+          ParseVp8HeaderQuantizer(encoded_data, 10 + first_partition_size);
+      EXPECT_EQ(kQp, decoded_quantizer);
+    } else {
+      // One byte less than needed to decode the quantizer value.
+      decoded_quantizer =
+          ParseVp8HeaderQuantizer(encoded_data, 3 + first_partition_size - 1);
+      EXPECT_EQ(-1, decoded_quantizer);
+      // Minimum number of bytes to decode the quantizer value.
+      decoded_quantizer =
+          ParseVp8HeaderQuantizer(encoded_data, 3 + first_partition_size);
+      EXPECT_EQ(kQp, decoded_quantizer);
+    }
+  }
+}
+
+// Encode 5 fames for every quantizer value in the range of [4,63].
+// crbug.com/537635: disable VariedQuantizer on Thread Sanitizer
+#if defined(THREAD_SANITIZER)
+# define MAYBE_VariedQuantizer DISABLED_VariedQuantizer
+#else
+# define MAYBE_VariedQuantizer VariedQuantizer
+#endif
+TEST_F(Vp8QuantizerParserTest, MAYBE_VariedQuantizer) {
+  int decoded_quantizer = -1;
+  for (int qp = 4; qp <= 63; ++qp) {
+    UpdateQuantizer(qp);
+    for (int i = 0; i < 5; ++i) {
+      scoped_ptr<SenderEncodedFrame> encoded_frame(new SenderEncodedFrame());
+      EncodeOneFrame(encoded_frame.get());
+      decoded_quantizer = ParseVp8HeaderQuantizer(
+          reinterpret_cast<const uint8*>(encoded_frame->data.data()),
+          encoded_frame->data.size());
+      EXPECT_EQ(qp, decoded_quantizer);
+    }
+  }
+}
+
+}  // namespace cast
+}  // namespace media
diff --git a/media/cdm/player_tracker_impl.cc b/media/cdm/player_tracker_impl.cc
index 8f102bd..e4abd61f 100644
--- a/media/cdm/player_tracker_impl.cc
+++ b/media/cdm/player_tracker_impl.cc
@@ -19,7 +19,11 @@
 PlayerTrackerImpl::PlayerCallbacks::~PlayerCallbacks() {
 }
 
-PlayerTrackerImpl::PlayerTrackerImpl() : next_registration_id_(1) {}
+PlayerTrackerImpl::PlayerTrackerImpl() : next_registration_id_(1) {
+  // Enable PlayerTrackerImpl to be created on another thread than it will be
+  // later exclusively used.
+  thread_checker_.DetachFromThread();
+}
 
 PlayerTrackerImpl::~PlayerTrackerImpl() {}
 
diff --git a/media/media.gyp b/media/media.gyp
index 804024c..a136093 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -324,6 +324,8 @@
         'base/media_log_event.h',
         'base/media_permission.cc',
         'base/media_permission.h',
+        'base/media_resources.cc',
+        'base/media_resources.h',
         'base/media_switches.cc',
         'base/media_switches.h',
         'base/mime_util.cc',
@@ -1510,10 +1512,6 @@
             'sources': [
               'audio/android/audio_android_unittest.cc',
             ],
-          }, {
-            'sources': [
-              'audio/audio_input_volume_unittest.cc',
-            ],
           }],
           ['OS=="mac"', {
             'sources': [
@@ -1613,6 +1611,8 @@
         'base/fake_audio_renderer_sink.h',
         'base/fake_demuxer_stream.cc',
         'base/fake_demuxer_stream.h',
+        'base/fake_media_resources.cc',
+        'base/fake_media_resources.h',
         'base/fake_output_device.cc',
         'base/fake_output_device.h',
         'base/fake_text_track_stream.cc',
@@ -1865,6 +1865,8 @@
             'base/android/media_resource_getter.h',
             'base/android/media_source_player.cc',
             'base/android/media_source_player.h',
+            'base/android/media_task_runner.cc',
+            'base/android/media_task_runner.h',
             'base/android/media_url_interceptor.h',
             'base/android/video_decoder_job.cc',
             'base/android/video_decoder_job.h',
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java b/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java
index b6ccac3..92657e5 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java
+++ b/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java
@@ -4,8 +4,10 @@
 
 package org.chromium.media.midi;
 
+import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
 import android.media.midi.MidiDeviceInfo;
+import android.os.Build;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -14,6 +16,7 @@
 /**
  * A class implementing media::midi::MidiDeviceAndroid functionality.
  */
+@TargetApi(Build.VERSION_CODES.M)
 class MidiDeviceAndroid {
     /**
      * The underlying device.
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java b/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java
index aab30e4..60d9abb 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java
+++ b/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java
@@ -4,9 +4,11 @@
 
 package org.chromium.media.midi;
 
+import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
 import android.media.midi.MidiOutputPort;
 import android.media.midi.MidiReceiver;
+import android.os.Build;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -19,6 +21,7 @@
  * A MidiInputPortAndroid provides data to the associated media::midi::MidiInputPortAndroid object.
  */
 @JNINamespace("media::midi")
+@TargetApi(Build.VERSION_CODES.M)
 class MidiInputPortAndroid {
     /**
      * The underlying port.
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java b/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java
index c17974d..c6048e8 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java
+++ b/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java
@@ -4,10 +4,12 @@
 
 package org.chromium.media.midi;
 
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.media.midi.MidiDevice;
 import android.media.midi.MidiDeviceInfo;
 import android.media.midi.MidiManager;
+import android.os.Build;
 import android.os.Handler;
 
 import org.chromium.base.ThreadUtils;
@@ -23,6 +25,7 @@
  * A Java class implementing media::midi::MidiManagerAndroid functionality.
  */
 @JNINamespace("media::midi")
+@TargetApi(Build.VERSION_CODES.M)
 class MidiManagerAndroid {
     /**
      * Set true while this instance is being initialized.
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java b/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java
index 6a0ec30..8de149b 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java
+++ b/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java
@@ -4,8 +4,10 @@
 
 package org.chromium.media.midi;
 
+import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
 import android.media.midi.MidiInputPort;
+import android.os.Build;
 
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
@@ -19,6 +21,7 @@
 // Note "OutputPort" is named in the Web MIDI manner. It corresponds to MidiInputPort class in the
 // Android API.
 @JNINamespace("media::midi")
+@TargetApi(Build.VERSION_CODES.M)
 class MidiOutputPortAndroid {
     /**
      * The underlying port.
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 8f1ecd0..f1965d10 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -16,19 +16,23 @@
 #include "base/containers/stack_container.h"
 #include "base/location.h"
 #include "base/memory/linked_ptr.h"
+#include "base/strings/stringprintf.h"
+#include "base/trace_event/memory_dump_provider.h"
 #include "base/trace_event/trace_event.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "media/renderers/gpu_video_accelerator_factories.h"
 #include "third_party/libyuv/include/libyuv.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gl/trace_util.h"
 
 namespace media {
 
 // Implementation of a pool of GpuMemoryBuffers used to back VideoFrames.
 class GpuMemoryBufferVideoFramePool::PoolImpl
     : public base::RefCountedThreadSafe<
-          GpuMemoryBufferVideoFramePool::PoolImpl> {
+          GpuMemoryBufferVideoFramePool::PoolImpl>,
+      public base::trace_event::MemoryDumpProvider {
  public:
   // |media_task_runner| is the media task runner associated with the
   // GL context provided by |gpu_factories|
@@ -58,10 +62,13 @@
   void CreateHardwareFrame(const scoped_refptr<VideoFrame>& video_frame,
                            const FrameReadyCB& cb);
 
+  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+                    base::trace_event::ProcessMemoryDump* pmd) override;
+
  private:
   friend class base::RefCountedThreadSafe<
       GpuMemoryBufferVideoFramePool::PoolImpl>;
-  ~PoolImpl();
+  ~PoolImpl() override;
 
   // Resource to represent a plane.
   struct PlaneResource {
@@ -257,13 +264,13 @@
     DCHECK_EQ(0, first_row % 2);
 
     libyuv::I420ToNV12(
-        source_frame->data(VideoFrame::kYPlane) +
+        source_frame->visible_data(VideoFrame::kYPlane) +
             first_row * source_frame->stride(VideoFrame::kYPlane),
         source_frame->stride(VideoFrame::kYPlane),
-        source_frame->data(VideoFrame::kUPlane) +
+        source_frame->visible_data(VideoFrame::kUPlane) +
             first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
         source_frame->stride(VideoFrame::kUPlane),
-        source_frame->data(VideoFrame::kVPlane) +
+        source_frame->visible_data(VideoFrame::kVPlane) +
             first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
         source_frame->stride(VideoFrame::kVPlane),
         dest_y + first_row * dest_stride_y, dest_stride_y,
@@ -287,13 +294,13 @@
     DCHECK_LE(width, std::abs(dest_stride / 2));
     DCHECK_EQ(0, first_row % 2);
     libyuv::I420ToUYVY(
-        source_frame->data(VideoFrame::kYPlane) +
+        source_frame->visible_data(VideoFrame::kYPlane) +
             first_row * source_frame->stride(VideoFrame::kYPlane),
         source_frame->stride(VideoFrame::kYPlane),
-        source_frame->data(VideoFrame::kUPlane) +
+        source_frame->visible_data(VideoFrame::kUPlane) +
             first_row / 2 * source_frame->stride(VideoFrame::kUPlane),
         source_frame->stride(VideoFrame::kUPlane),
-        source_frame->data(VideoFrame::kVPlane) +
+        source_frame->visible_data(VideoFrame::kVPlane) +
             first_row / 2 * source_frame->stride(VideoFrame::kVPlane),
         source_frame->stride(VideoFrame::kVPlane),
         output + first_row * dest_stride, dest_stride, width, rows);
@@ -350,7 +357,6 @@
       return;
   }
 
-  DCHECK(video_frame->visible_rect().origin().IsOrigin());
   const gfx::Size size = video_frame->visible_rect().size();
 
   // Acquire resources. Incompatible ones will be dropped from the pool.
@@ -366,6 +372,42 @@
                             video_frame, frame_resources, frame_ready_cb));
 }
 
+bool GpuMemoryBufferVideoFramePool::PoolImpl::OnMemoryDump(
+    const base::trace_event::MemoryDumpArgs& args,
+    base::trace_event::ProcessMemoryDump* pmd) {
+  const uint64 tracing_process_id =
+      base::trace_event::MemoryDumpManager::GetInstance()
+          ->GetTracingProcessId();
+  const int kImportance = 2;
+  for (const FrameResources* frame_resources : resources_pool_) {
+    for (const PlaneResource& plane_resource :
+         frame_resources->plane_resources) {
+      if (plane_resource.gpu_memory_buffer) {
+        gfx::GpuMemoryBufferId buffer_id =
+            plane_resource.gpu_memory_buffer->GetId();
+        std::string dump_name = base::StringPrintf(
+            "media/video_frame_memory/buffer_%d", buffer_id.id);
+        base::trace_event::MemoryAllocatorDump* dump =
+            pmd->CreateAllocatorDump(dump_name);
+        size_t buffer_size_in_bytes = gfx::BufferSizeForBufferFormat(
+            plane_resource.size, plane_resource.gpu_memory_buffer->GetFormat());
+        dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+                        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                        buffer_size_in_bytes);
+        dump->AddScalar("free_size",
+                        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                        frame_resources->in_use ? 0 : buffer_size_in_bytes);
+        base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid =
+            gfx::GetGpuMemoryBufferGUIDForTracing(tracing_process_id,
+                                                  buffer_id);
+        pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid);
+        pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid, kImportance);
+      }
+    }
+  }
+  return true;
+}
+
 void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
     const scoped_refptr<VideoFrame>& video_frame,
     FrameResources* frame_resources,
@@ -391,7 +433,7 @@
   // Compute the number of tasks to post and create the barrier.
   const size_t num_planes = VideoFrame::NumPlanes(output_format_);
   const size_t planes_per_copy = PlanesPerCopy(output_format_);
-  gfx::Size size = video_frame->visible_rect().size();
+  const gfx::Size size = video_frame->visible_rect().size();
   size_t copies = 0;
   for (size_t i = 0; i < num_planes; i += planes_per_copy) {
     const int rows = VideoFrame::Rows(i, output_format_, size.height());
@@ -429,11 +471,10 @@
           const int bytes_per_row =
               VideoFrame::RowBytes(i, output_format_, size.width());
           worker_task_runner_->PostTask(
-              FROM_HERE,
-              base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy,
-                         bytes_per_row, video_frame->data(i),
-                         video_frame->stride(i), dest_buffers[0],
-                         dest_strides[0], barrier));
+              FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy,
+                                    bytes_per_row, video_frame->visible_data(i),
+                                    video_frame->stride(i), dest_buffers[0],
+                                    dest_strides[0], barrier));
           break;
         }
         case PIXEL_FORMAT_NV12:
@@ -511,8 +552,7 @@
           mailbox_holders[VideoFrame::kUPlane],
           mailbox_holders[VideoFrame::kVPlane],
           base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
-          size, video_frame->visible_rect(), video_frame->natural_size(),
-          video_frame->timestamp());
+          size, gfx::Rect(size), size, video_frame->timestamp());
       if (video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY))
         frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
       break;
@@ -521,8 +561,7 @@
       frame = VideoFrame::WrapNativeTexture(
           output_format_, mailbox_holders[VideoFrame::kYPlane],
           base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources),
-          size, video_frame->visible_rect(), video_frame->natural_size(),
-          video_frame->timestamp());
+          size, gfx::Rect(size), size, video_frame->timestamp());
       frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true);
       break;
     default:
@@ -579,11 +618,11 @@
     PlaneResource& plane_resource = frame_resources->plane_resources[i];
     const size_t width = VideoFrame::Columns(i, format, size.width());
     const size_t height = VideoFrame::Rows(i, format, size.height());
-    const gfx::Size plane_size(width, height);
+    plane_resource.size = gfx::Size(width, height);
 
     const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(format, i);
     plane_resource.gpu_memory_buffer = gpu_factories_->AllocateGpuMemoryBuffer(
-        plane_size, buffer_format, gfx::BufferUsage::MAP);
+        plane_resource.size, buffer_format, gfx::BufferUsage::MAP);
 
     gles2->GenTextures(1, &plane_resource.texture_id);
     gles2->BindTexture(texture_target_, plane_resource.texture_id);
@@ -647,9 +686,14 @@
     const scoped_refptr<base::TaskRunner>& worker_task_runner,
     const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
     : pool_impl_(
-          new PoolImpl(media_task_runner, worker_task_runner, gpu_factories)) {}
+          new PoolImpl(media_task_runner, worker_task_runner, gpu_factories)) {
+  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+      pool_impl_.get(), media_task_runner);
+}
 
 GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() {
+  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+      pool_impl_.get());
 }
 
 void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
diff --git a/mojo/cc/BUILD.gn b/mojo/cc/BUILD.gn
deleted file mode 100644
index c903ce0..0000000
--- a/mojo/cc/BUILD.gn
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# GYP version: mojo/mojo.gyp:mojo_cc_support
-source_set("cc") {
-  deps = [
-    "//base",
-    "//cc",
-    "//cc/surfaces",
-    "//cc/surfaces:surface_id",
-    "//components/mus/public/interfaces",
-    "//components/mus/public/cpp",
-    "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/client:gles2_interface",
-    "//mojo/converters/surfaces",
-    "//mojo/gles2:headers",
-    "//mojo/gpu:mojo_gles2_implementation",
-    "//skia",
-    "//third_party/mojo/src/mojo/public/c/gles2",
-    "//third_party/mojo/src/mojo/public/cpp/environment",
-    "//third_party/mojo/src/mojo/public/cpp/system",
-  ]
-
-  sources = [
-    "context_provider_mojo.cc",
-    "context_provider_mojo.h",
-    "direct_output_surface.cc",
-    "direct_output_surface.h",
-    "output_surface_mojo.cc",
-    "output_surface_mojo.h",
-  ]
-}
diff --git a/mojo/cc/DEPS b/mojo/cc/DEPS
deleted file mode 100644
index 9218a8b..0000000
--- a/mojo/cc/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
-  "+cc",
-  "-cc/blink",
-  "+components/mus/public/cpp",
-  "+gpu/command_buffer/client",
-  "+mojo/gpu",
-]
diff --git a/mojo/cc/OWNERS b/mojo/cc/OWNERS
deleted file mode 100644
index c92691f..0000000
--- a/mojo/cc/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-fsamuel@chromium.org
diff --git a/mojo/cc/context_provider_mojo.cc b/mojo/cc/context_provider_mojo.cc
deleted file mode 100644
index ed8643d..0000000
--- a/mojo/cc/context_provider_mojo.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/cc/context_provider_mojo.h"
-
-#include "base/logging.h"
-#include "mojo/gles2/gles2_context.h"
-#include "mojo/gpu/mojo_gles2_impl_autogen.h"
-#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h"
-
-namespace mojo {
-
-ContextProviderMojo::ContextProviderMojo(
-    ScopedMessagePipeHandle command_buffer_handle)
-    : command_buffer_handle_(command_buffer_handle.Pass()),
-      context_(nullptr) {
-  // Enabled the CHROMIUM_image extension to use GpuMemoryBuffers. The
-  // implementation of which is used in CommandBufferDriver.
-  capabilities_.gpu.image = true;
-}
-
-bool ContextProviderMojo::BindToCurrentThread() {
-  DCHECK(command_buffer_handle_.is_valid());
-  context_ = MojoGLES2CreateContext(command_buffer_handle_.release().value(),
-                                    nullptr,
-                                    &ContextLostThunk,
-                                    this,
-                                    Environment::GetDefaultAsyncWaiter());
-  context_gl_.reset(new MojoGLES2Impl(context_));
-  return !!context_;
-}
-
-gpu::gles2::GLES2Interface* ContextProviderMojo::ContextGL() {
-  return context_gl_.get();
-}
-
-gpu::ContextSupport* ContextProviderMojo::ContextSupport() {
-  if (!context_)
-    return NULL;
-  // TODO(rjkroege): Ensure that UIP does not take this code path.
-  return static_cast<gles2::GLES2Context*>(context_)->context_support();
-}
-
-class GrContext* ContextProviderMojo::GrContext() { return NULL; }
-
-void ContextProviderMojo::InvalidateGrContext(uint32_t state) {
-}
-
-cc::ContextProvider::Capabilities ContextProviderMojo::ContextCapabilities() {
-  return capabilities_;
-}
-
-void ContextProviderMojo::SetupLock() {
-}
-
-base::Lock* ContextProviderMojo::GetLock() {
-  return &context_lock_;
-}
-
-bool ContextProviderMojo::DestroyedOnMainThread() { return !context_; }
-
-ContextProviderMojo::~ContextProviderMojo() {
-  context_gl_.reset();
-  if (context_)
-    MojoGLES2DestroyContext(context_);
-}
-
-void ContextProviderMojo::ContextLost() {
-}
-
-}  // namespace mojo
diff --git a/mojo/cc/direct_output_surface.cc b/mojo/cc/direct_output_surface.cc
deleted file mode 100644
index 0899c4e..0000000
--- a/mojo/cc/direct_output_surface.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/cc/direct_output_surface.h"
-
-#include "base/bind.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/context_provider.h"
-#include "cc/output/output_surface_client.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-
-namespace mojo {
-
-DirectOutputSurface::DirectOutputSurface(
-    const scoped_refptr<cc::ContextProvider>& context_provider)
-    : cc::OutputSurface(context_provider), weak_ptr_factory_(this) {
-}
-
-DirectOutputSurface::~DirectOutputSurface() {}
-
-void DirectOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
-  DCHECK(context_provider_.get());
-  DCHECK(frame->gl_frame_data);
-  if (frame->gl_frame_data->sub_buffer_rect ==
-      gfx::Rect(frame->gl_frame_data->size)) {
-    context_provider_->ContextSupport()->Swap();
-  } else {
-    context_provider_->ContextSupport()->PartialSwapBuffers(
-        frame->gl_frame_data->sub_buffer_rect);
-  }
-  uint32_t sync_point =
-      context_provider_->ContextGL()->InsertSyncPointCHROMIUM();
-  context_provider_->ContextSupport()->SignalSyncPoint(
-      sync_point,
-      base::Bind(&OutputSurface::OnSwapBuffersComplete,
-                 weak_ptr_factory_.GetWeakPtr()));
-  client_->DidSwapBuffers();
-}
-
-}  // namespace mojo
diff --git a/mojo/cc/direct_output_surface.h b/mojo/cc/direct_output_surface.h
deleted file mode 100644
index fa997b0..0000000
--- a/mojo/cc/direct_output_surface.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_CC_DIRECT_OUTPUT_SURFACE_H_
-#define MOJO_CC_DIRECT_OUTPUT_SURFACE_H_
-
-#include "cc/output/output_surface.h"
-
-namespace mojo {
-
-// An OutputSurface implementation that directly draws and
-// swaps to an actual GL surface.
-class DirectOutputSurface : public cc::OutputSurface {
- public:
-  explicit DirectOutputSurface(
-      const scoped_refptr<cc::ContextProvider>& context_provider);
-  ~DirectOutputSurface() override;
-
-  // cc::OutputSurface implementation
-  void SwapBuffers(cc::CompositorFrame* frame) override;
-
-private:
-  base::WeakPtrFactory<DirectOutputSurface> weak_ptr_factory_;
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_CC_DIRECT_OUTPUT_SURFACE_H_
diff --git a/mojo/cc/output_surface_mojo.h b/mojo/cc/output_surface_mojo.h
deleted file mode 100644
index 3e37455..0000000
--- a/mojo/cc/output_surface_mojo.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_CC_OUTPUT_SURFACE_MOJO_H_
-#define MOJO_CC_OUTPUT_SURFACE_MOJO_H_
-
-#include "base/macros.h"
-#include "cc/output/output_surface.h"
-#include "cc/surfaces/surface_id.h"
-#include "components/mus/public/cpp/view_surface.h"
-#include "components/mus/public/cpp/view_surface_client.h"
-#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
-
-namespace mojo {
-
-class OutputSurfaceMojo : public cc::OutputSurface,
-                          public mus::ViewSurfaceClient {
- public:
-  OutputSurfaceMojo(const scoped_refptr<cc::ContextProvider>& context_provider,
-                    scoped_ptr<mus::ViewSurface> surface);
-  ~OutputSurfaceMojo() override;
-
-  // cc::OutputSurface implementation.
-  void SwapBuffers(cc::CompositorFrame* frame) override;
-  bool BindToClient(cc::OutputSurfaceClient* client) override;
-  void DetachFromClient() override;
-
- private:
-  // ViewSurfaceClient implementation:
-  void OnResourcesReturned(
-      mus::ViewSurface* surface,
-      mojo::Array<mojo::ReturnedResourcePtr> resources) override;
-
-  void SwapBuffersComplete();
-
-  scoped_ptr<mus::ViewSurface> surface_;
-
-  DISALLOW_COPY_AND_ASSIGN(OutputSurfaceMojo);
-};
-}
-
-#endif  // MOJO_CC_OUTPUT_SURFACE_MOJO_H_
diff --git a/mojo/converters/surfaces/tests/surface_unittest.cc b/mojo/converters/surfaces/tests/surface_unittest.cc
index 0dcfeea..90aab3c58 100644
--- a/mojo/converters/surfaces/tests/surface_unittest.cc
+++ b/mojo/converters/surfaces/tests/surface_unittest.cc
@@ -75,13 +75,13 @@
   QuadPtr mojo_quad = Quad::From<cc::DrawQuad>(*color_quad);
   ASSERT_FALSE(mojo_quad.is_null());
   EXPECT_EQ(MATERIAL_SOLID_COLOR, mojo_quad->material);
-  EXPECT_EQ(Rect::From(rect), mojo_quad->rect);
-  EXPECT_EQ(Rect::From(opaque_rect), mojo_quad->opaque_rect);
-  EXPECT_EQ(Rect::From(visible_rect), mojo_quad->visible_rect);
+  EXPECT_TRUE(Rect::From(rect).Equals(mojo_quad->rect));
+  EXPECT_TRUE(Rect::From(opaque_rect).Equals(mojo_quad->opaque_rect));
+  EXPECT_TRUE(Rect::From(visible_rect).Equals(mojo_quad->visible_rect));
   EXPECT_EQ(needs_blending, mojo_quad->needs_blending);
   ASSERT_TRUE(mojo_quad->solid_color_quad_state);
   SolidColorQuadStatePtr& mojo_color_state = mojo_quad->solid_color_quad_state;
-  EXPECT_EQ(Color::From(arbitrary_color), mojo_color_state->color);
+  EXPECT_TRUE(Color::From(arbitrary_color).Equals(mojo_color_state->color));
   EXPECT_EQ(force_anti_aliasing_off, mojo_color_state->force_anti_aliasing_off);
 }
 
@@ -97,8 +97,8 @@
   EXPECT_EQ(MATERIAL_SURFACE_CONTENT, mojo_quad->material);
   ASSERT_TRUE(mojo_quad->surface_quad_state);
   SurfaceQuadStatePtr& mojo_surface_state = mojo_quad->surface_quad_state;
-  EXPECT_EQ(SurfaceId::From(arbitrary_id),
-            mojo_surface_state->surface);
+  EXPECT_TRUE(
+      SurfaceId::From(arbitrary_id).Equals(mojo_surface_state->surface));
 }
 
 TEST_F(SurfaceLibQuadTest, TextureQuad) {
@@ -126,10 +126,12 @@
   TextureQuadStatePtr& mojo_texture_state = mojo_quad->texture_quad_state;
   EXPECT_EQ(resource_id, mojo_texture_state->resource_id);
   EXPECT_EQ(premultiplied_alpha, mojo_texture_state->premultiplied_alpha);
-  EXPECT_EQ(PointF::From(uv_top_left), mojo_texture_state->uv_top_left);
-  EXPECT_EQ(PointF::From(uv_bottom_right), mojo_texture_state->uv_bottom_right);
-  EXPECT_EQ(Color::From(background_color),
-            mojo_texture_state->background_color);
+  EXPECT_TRUE(
+      PointF::From(uv_top_left).Equals(mojo_texture_state->uv_top_left));
+  EXPECT_TRUE(PointF::From(uv_bottom_right)
+                  .Equals(mojo_texture_state->uv_bottom_right));
+  EXPECT_TRUE(Color::From(background_color)
+                  .Equals(mojo_texture_state->background_color));
   for (size_t i = 0; i < 4; ++i) {
     EXPECT_EQ(vertex_opacity[i], mojo_texture_state->vertex_opacity[i]) << i;
   }
@@ -191,12 +193,13 @@
 
   SharedQuadStatePtr mojo_sqs = SharedQuadState::From(*sqs);
   ASSERT_FALSE(mojo_sqs.is_null());
-  EXPECT_EQ(Transform::From(quad_to_target_transform),
-            mojo_sqs->quad_to_target_transform);
-  EXPECT_EQ(Size::From(quad_layer_bounds), mojo_sqs->quad_layer_bounds);
-  EXPECT_EQ(Rect::From(visible_quad_layer_rect),
-            mojo_sqs->visible_quad_layer_rect);
-  EXPECT_EQ(Rect::From(clip_rect), mojo_sqs->clip_rect);
+  EXPECT_TRUE(Transform::From(quad_to_target_transform)
+                  .Equals(mojo_sqs->quad_to_target_transform));
+  EXPECT_TRUE(
+      Size::From(quad_layer_bounds).Equals(mojo_sqs->quad_layer_bounds));
+  EXPECT_TRUE(Rect::From(visible_quad_layer_rect)
+                  .Equals(mojo_sqs->visible_quad_layer_rect));
+  EXPECT_TRUE(Rect::From(clip_rect).Equals(mojo_sqs->clip_rect));
   EXPECT_EQ(is_clipped, mojo_sqs->is_clipped);
   EXPECT_EQ(opacity, mojo_sqs->opacity);
   EXPECT_EQ(sorting_context_id, mojo_sqs->sorting_context_id);
@@ -273,10 +276,10 @@
   PassPtr mojo_pass = Pass::From(*pass);
   ASSERT_FALSE(mojo_pass.is_null());
   EXPECT_EQ(6u, mojo_pass->id->index);
-  EXPECT_EQ(Rect::From(output_rect), mojo_pass->output_rect);
-  EXPECT_EQ(Rect::From(damage_rect), mojo_pass->damage_rect);
-  EXPECT_EQ(Transform::From(transform_to_root_target),
-            mojo_pass->transform_to_root_target);
+  EXPECT_TRUE(Rect::From(output_rect).Equals(mojo_pass->output_rect));
+  EXPECT_TRUE(Rect::From(damage_rect).Equals(mojo_pass->damage_rect));
+  EXPECT_TRUE(Transform::From(transform_to_root_target)
+                  .Equals(mojo_pass->transform_to_root_target));
   EXPECT_EQ(has_transparent_background, mojo_pass->has_transparent_background);
   ASSERT_EQ(1u, mojo_pass->shared_quad_states.size());
   ASSERT_EQ(3u, mojo_pass->quads.size());
@@ -401,7 +404,7 @@
   EXPECT_EQ(static_cast<ResourceFormat>(format),
             mojo_resource->format);
   EXPECT_EQ(filter, mojo_resource->filter);
-  EXPECT_EQ(Size::From(size), mojo_resource->size);
+  EXPECT_TRUE(Size::From(size).Equals(mojo_resource->size));
   EXPECT_EQ(is_repeated, mojo_resource->is_repeated);
   EXPECT_EQ(is_software, mojo_resource->is_software);
 
@@ -461,14 +464,15 @@
   QuadPtr mojo_quad = Quad::From<cc::DrawQuad>(*debug_border_quad);
   ASSERT_FALSE(mojo_quad.is_null());
   EXPECT_EQ(MATERIAL_DEBUG_BORDER, mojo_quad->material);
-  EXPECT_EQ(Rect::From(rect), mojo_quad->rect);
-  EXPECT_EQ(Rect::From(opaque_rect), mojo_quad->opaque_rect);
-  EXPECT_EQ(Rect::From(visible_rect), mojo_quad->visible_rect);
+  EXPECT_TRUE(Rect::From(rect).Equals(mojo_quad->rect));
+  EXPECT_TRUE(Rect::From(opaque_rect).Equals(mojo_quad->opaque_rect));
+  EXPECT_TRUE(Rect::From(visible_rect).Equals(mojo_quad->visible_rect));
   EXPECT_EQ(needs_blending, mojo_quad->needs_blending);
   ASSERT_TRUE(mojo_quad->debug_border_quad_state);
   DebugBorderQuadStatePtr& mojo_debug_border_state =
       mojo_quad->debug_border_quad_state;
-  EXPECT_EQ(Color::From(arbitrary_color), mojo_debug_border_state->color);
+  EXPECT_TRUE(
+      Color::From(arbitrary_color).Equals(mojo_debug_border_state->color));
   EXPECT_EQ(width, mojo_debug_border_state->width);
 }
 
diff --git a/mojo/runner/BUILD.gn b/mojo/runner/BUILD.gn
index 558b327..016f383 100644
--- a/mojo/runner/BUILD.gn
+++ b/mojo/runner/BUILD.gn
@@ -54,6 +54,7 @@
     deps += [
       ":jni_headers",
       "//components/mus",
+      "//components/mus/vm:lib",
       "//mojo/shell",
       "//ui/gl",
       "//ui/platform_window/android",
@@ -301,7 +302,7 @@
       ":bootstrap",
       ":bootstrap_java",
       "//components/clipboard:apptests",
-      "//components/mus:apptests",
+      "//components/mus/vm:apptests",
       "//components/resource_provider:apptests",
       "//mojo/services/network:apptests",
     ]
diff --git a/mojo/runner/DEPS b/mojo/runner/DEPS
index 8f8de76..d8b1afb 100644
--- a/mojo/runner/DEPS
+++ b/mojo/runner/DEPS
@@ -3,7 +3,7 @@
   "+components/mus",
   "+components/mus/gles2",
   "+components/mus/native_viewport",
-  "+components/mus/public",
+  "+components/mus/vm/public",
   "+components/tracing",
   "+crypto",
   "+jni",
diff --git a/mojo/runner/context.cc b/mojo/runner/context.cc
index 0f59f7d..c7bda8c9 100644
--- a/mojo/runner/context.cc
+++ b/mojo/runner/context.cc
@@ -62,8 +62,13 @@
 void InitContentHandlers(package_manager::PackageManagerImpl* manager,
                          const base::CommandLine& command_line) {
   // Default content handlers.
+  manager->RegisterContentHandler("application/javascript",
+                                  GURL("mojo:html_viewer"));
   manager->RegisterContentHandler("application/pdf", GURL("mojo:pdf_viewer"));
+  manager->RegisterContentHandler("image/gif", GURL("mojo:html_viewer"));
+  manager->RegisterContentHandler("image/jpeg", GURL("mojo:html_viewer"));
   manager->RegisterContentHandler("image/png", GURL("mojo:png_viewer"));
+  manager->RegisterContentHandler("text/css", GURL("mojo:html_viewer"));
   manager->RegisterContentHandler("text/html", GURL("mojo:html_viewer"));
   manager->RegisterContentHandler("text/plain", GURL("mojo:html_viewer"));
 
diff --git a/mojo/tools/data/apptests b/mojo/tools/data/apptests
index 24c18b59..3f45a89 100644
--- a/mojo/tools/data/apptests
+++ b/mojo/tools/data/apptests
@@ -77,7 +77,6 @@
     #{
     #  'test': 'mojo:mandoline_browser_apptests',
     #  'type': 'gtest_isolated',
-    #  'args': ['--use-headless-config']
     #},
     # TODO(xhwang): Fix and enable mojo:media_pipeline_integration_apptests.
     # http://crbug.com/501417
diff --git a/native_client_sdk/src/examples/api/media_stream_audio/example.dsc b/native_client_sdk/src/examples/api/media_stream_audio/example.dsc
index 829f0c3e..9d18729 100644
--- a/native_client_sdk/src/examples/api/media_stream_audio/example.dsc
+++ b/native_client_sdk/src/examples/api/media_stream_audio/example.dsc
@@ -16,5 +16,6 @@
   'NAME': 'media_stream_audio',
   'TITLE': 'MediaStream Audio',
   'GROUP': 'API',
-  'MIN_CHROME_VERSION': '35.0.0.0'
+  'MIN_CHROME_VERSION': '35.0.0.0',
+  'PERMISSIONS': ['audioCapture']
 }
diff --git a/native_client_sdk/src/examples/api/media_stream_video/example.dsc b/native_client_sdk/src/examples/api/media_stream_video/example.dsc
index 75d179a0..ab9dfeb 100644
--- a/native_client_sdk/src/examples/api/media_stream_video/example.dsc
+++ b/native_client_sdk/src/examples/api/media_stream_video/example.dsc
@@ -16,8 +16,6 @@
   'NAME': 'media_stream_video',
   'TITLE': 'MediaStream Video',
   'GROUP': 'API',
-  'MIN_CHROME_VERSION': '35.0.0.0'
+  'MIN_CHROME_VERSION': '35.0.0.0',
+  'PERMISSIONS': ['videoCapture']
 }
-
-
-
diff --git a/net/android/java/src/org/chromium/net/AndroidTrafficStats.java b/net/android/java/src/org/chromium/net/AndroidTrafficStats.java
index 059e3993..a217f4c 100644
--- a/net/android/java/src/org/chromium/net/AndroidTrafficStats.java
+++ b/net/android/java/src/org/chromium/net/AndroidTrafficStats.java
@@ -5,6 +5,7 @@
 package org.chromium.net;
 
 import android.net.TrafficStats;
+import android.os.Process;
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -26,4 +27,39 @@
         long bytes = TrafficStats.getTotalTxBytes();
         return bytes != TrafficStats.UNSUPPORTED ? bytes : TrafficStatsError.ERROR_NOT_SUPPORTED;
     }
+
+    /**
+     * @return Number of bytes received since device boot. Counts packets across all network
+     *         interfaces, and always increases monotonically since device boot. Statistics are
+     *         measured at the network layer, so they include both TCP and UDP usage.
+     */
+    @CalledByNative
+    private static long getTotalRxBytes() {
+        long bytes = TrafficStats.getTotalRxBytes();
+        return bytes != TrafficStats.UNSUPPORTED ? bytes : TrafficStatsError.ERROR_NOT_SUPPORTED;
+    }
+
+    /**
+     * @return Number of bytes transmitted since device boot that were attributed to caller's UID.
+     *         Counts packets across all network interfaces, and always increases monotonically
+     *         since device boot. Statistics are measured at the network layer, so they include
+     *         both TCP and UDP usage.
+     */
+    @CalledByNative
+    private static long getCurrentUidTxBytes() {
+        long bytes = TrafficStats.getUidTxBytes(Process.myUid());
+        return bytes != TrafficStats.UNSUPPORTED ? bytes : TrafficStatsError.ERROR_NOT_SUPPORTED;
+    }
+
+    /**
+     * @return Number of bytes received since device boot that were attributed to caller's UID.
+     *         Counts packets across all network interfaces, and always increases monotonically
+     *         since device boot. Statistics are measured at the network layer, so they include
+     *         both TCP and UDP usage.
+     */
+    @CalledByNative
+    private static long getCurrentUidRxBytes() {
+        long bytes = TrafficStats.getUidRxBytes(Process.myUid());
+        return bytes != TrafficStats.UNSUPPORTED ? bytes : TrafficStatsError.ERROR_NOT_SUPPORTED;
+    }
 }
diff --git a/net/android/traffic_stats.cc b/net/android/traffic_stats.cc
index 6ae5953b..4a953a6 100644
--- a/net/android/traffic_stats.cc
+++ b/net/android/traffic_stats.cc
@@ -25,6 +25,24 @@
   return *bytes != ERROR_NOT_SUPPORTED;
 }
 
+bool GetTotalRxBytes(int64_t* bytes) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  *bytes = Java_AndroidTrafficStats_getTotalRxBytes(env);
+  return *bytes != ERROR_NOT_SUPPORTED;
+}
+
+bool GetCurrentUidTxBytes(int64_t* bytes) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  *bytes = Java_AndroidTrafficStats_getCurrentUidTxBytes(env);
+  return *bytes != ERROR_NOT_SUPPORTED;
+}
+
+bool GetCurrentUidRxBytes(int64_t* bytes) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  *bytes = Java_AndroidTrafficStats_getCurrentUidRxBytes(env);
+  return *bytes != ERROR_NOT_SUPPORTED;
+}
+
 bool Register(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
diff --git a/net/android/traffic_stats.h b/net/android/traffic_stats.h
index 3434d89..f6aadad 100644
--- a/net/android/traffic_stats.h
+++ b/net/android/traffic_stats.h
@@ -26,6 +26,27 @@
 // UDP usage. |bytes| must not be nullptr.
 NET_EXPORT bool GetTotalTxBytes(int64_t* bytes);
 
+// Returns true if the number of bytes received since device boot is
+// available and sets |*bytes| to that value. Counts packets across all network
+// interfaces, and always increases monotonically since device boot.
+// Statistics are measured at the network layer, so they include both TCP and
+// UDP usage. |bytes| must not be nullptr.
+NET_EXPORT bool GetTotalRxBytes(int64_t* bytes);
+
+// Returns true if the number of bytes attributed to caller's UID since device
+// boot are available and sets |*bytes| to that value. Counts packets across
+// all network interfaces, and always increases monotonically since device
+// boot. Statistics are measured at the network layer, so they include both TCP
+// and UDP usage. |bytes| must not be nullptr.
+NET_EXPORT bool GetCurrentUidTxBytes(int64_t* bytes);
+
+// Returns true if the number of bytes attributed to caller's UID since device
+// boot are available and sets |*bytes| to that value. Counts packets across
+// all network interfaces, and always increases monotonically since device
+// boot. Statistics are measured at the network layer, so they include both TCP
+// and UDP usage. |bytes| must not be nullptr.
+NET_EXPORT bool GetCurrentUidRxBytes(int64_t* bytes);
+
 bool Register(JNIEnv* env);
 
 }  // namespace traffic_stats
diff --git a/net/android/traffic_stats_unittest.cc b/net/android/traffic_stats_unittest.cc
index ad5198f..0d53c246 100644
--- a/net/android/traffic_stats_unittest.cc
+++ b/net/android/traffic_stats_unittest.cc
@@ -20,9 +20,14 @@
       base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
   ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady());
 
-  int64_t bytes_before_request = -1;
-  EXPECT_TRUE(android::traffic_stats::GetTotalTxBytes(&bytes_before_request));
-  EXPECT_GE(bytes_before_request, 0);
+  int64_t tx_bytes_before_request = -1;
+  int64_t rx_bytes_before_request = -1;
+  EXPECT_TRUE(
+      android::traffic_stats::GetTotalTxBytes(&tx_bytes_before_request));
+  EXPECT_GE(tx_bytes_before_request, 0);
+  EXPECT_TRUE(
+      android::traffic_stats::GetTotalRxBytes(&rx_bytes_before_request));
+  EXPECT_GE(rx_bytes_before_request, 0);
 
   TestDelegate test_delegate;
   TestURLRequestContext context(false);
@@ -34,9 +39,47 @@
   base::RunLoop().Run();
 
   // Bytes should increase because of the network traffic.
-  int64_t bytes_after_request;
-  EXPECT_TRUE(android::traffic_stats::GetTotalTxBytes(&bytes_after_request));
-  DCHECK_GT(bytes_after_request, bytes_before_request);
+  int64_t tx_bytes_after_request = -1;
+  int64_t rx_bytes_after_request = -1;
+  EXPECT_TRUE(android::traffic_stats::GetTotalTxBytes(&tx_bytes_after_request));
+  DCHECK_GT(tx_bytes_after_request, tx_bytes_before_request);
+  EXPECT_TRUE(android::traffic_stats::GetTotalRxBytes(&rx_bytes_after_request));
+  DCHECK_GT(rx_bytes_after_request, rx_bytes_before_request);
+}
+
+TEST(TrafficStatsAndroidTest, UIDBasicsTest) {
+  test_server::EmbeddedTestServer embedded_test_server;
+  embedded_test_server.ServeFilesFromDirectory(
+      base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
+  ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady());
+
+  int64_t tx_bytes_before_request = -1;
+  int64_t rx_bytes_before_request = -1;
+  EXPECT_TRUE(
+      android::traffic_stats::GetCurrentUidTxBytes(&tx_bytes_before_request));
+  EXPECT_GE(tx_bytes_before_request, 0);
+  EXPECT_TRUE(
+      android::traffic_stats::GetCurrentUidRxBytes(&rx_bytes_before_request));
+  EXPECT_GE(rx_bytes_before_request, 0);
+
+  TestDelegate test_delegate;
+  TestURLRequestContext context(false);
+
+  scoped_ptr<URLRequest> request(
+      context.CreateRequest(embedded_test_server.GetURL("/echo.html"),
+                            DEFAULT_PRIORITY, &test_delegate));
+  request->Start();
+  base::RunLoop().Run();
+
+  // Bytes should increase because of the network traffic.
+  int64_t tx_bytes_after_request = -1;
+  int64_t rx_bytes_after_request = -1;
+  EXPECT_TRUE(
+      android::traffic_stats::GetCurrentUidTxBytes(&tx_bytes_after_request));
+  DCHECK_GT(tx_bytes_after_request, tx_bytes_before_request);
+  EXPECT_TRUE(
+      android::traffic_stats::GetCurrentUidRxBytes(&rx_bytes_after_request));
+  DCHECK_GT(rx_bytes_after_request, rx_bytes_before_request);
 }
 
 }  // namespace
diff --git a/net/base/layered_network_delegate.cc b/net/base/layered_network_delegate.cc
index f84b4687..d384d5ea 100644
--- a/net/base/layered_network_delegate.cc
+++ b/net/base/layered_network_delegate.cc
@@ -148,6 +148,16 @@
     const URLRequest& request,
     int64_t bytes_received) {}
 
+void LayeredNetworkDelegate::OnNetworkBytesSent(const URLRequest& request,
+                                                int64_t bytes_sent) {
+  OnNetworkBytesSentInternal(request, bytes_sent);
+  nested_network_delegate_->NotifyNetworkBytesSent(request, bytes_sent);
+}
+
+void LayeredNetworkDelegate::OnNetworkBytesSentInternal(
+    const URLRequest& request,
+    int64_t bytes_sent) {}
+
 void LayeredNetworkDelegate::OnCompleted(URLRequest* request, bool started) {
   OnCompletedInternal(request, started);
   nested_network_delegate_->NotifyCompleted(request, started);
diff --git a/net/base/layered_network_delegate.h b/net/base/layered_network_delegate.h
index f5899e9..dabe681 100644
--- a/net/base/layered_network_delegate.h
+++ b/net/base/layered_network_delegate.h
@@ -66,6 +66,7 @@
   void OnResponseStarted(URLRequest* request) final;
   void OnNetworkBytesReceived(const URLRequest& request,
                               int64_t bytes_received) final;
+  void OnNetworkBytesSent(const URLRequest& request, int64_t bytes_sent) final;
   void OnCompleted(URLRequest* request, bool started) final;
   void OnURLRequestDestroyed(URLRequest* request) final;
   void OnURLRequestJobOrphaned(URLRequest* request) final;
@@ -128,6 +129,9 @@
   virtual void OnNetworkBytesReceivedInternal(const URLRequest& request,
                                               int64_t bytes_received);
 
+  virtual void OnNetworkBytesSentInternal(const URLRequest& request,
+                                          int64_t bytes_sent);
+
   virtual void OnCompletedInternal(URLRequest* request, bool started);
 
   virtual void OnURLRequestDestroyedInternal(URLRequest* request);
diff --git a/net/base/layered_network_delegate_unittest.cc b/net/base/layered_network_delegate_unittest.cc
index a74a2b6..bfdbe7b8 100644
--- a/net/base/layered_network_delegate_unittest.cc
+++ b/net/base/layered_network_delegate_unittest.cc
@@ -98,6 +98,11 @@
     IncrementAndCompareCounter("on_network_bytes_received_count");
   }
 
+  void OnNetworkBytesSent(const URLRequest& request,
+                          int64_t bytes_sent) override {
+    IncrementAndCompareCounter("on_network_bytes_sent_count");
+  }
+
   void OnCompleted(URLRequest* request, bool started) override {
     IncrementAndCompareCounter("on_completed_count");
   }
@@ -197,6 +202,7 @@
                                       request_headers.get()));
     OnBeforeSendProxyHeaders(NULL, ProxyInfo(), request_headers.get());
     OnSendHeaders(NULL, *request_headers);
+    OnNetworkBytesSent(*request, 42);
     EXPECT_EQ(OK, OnHeadersReceived(NULL, completion_callback.callback(),
                                     response_headers.get(), NULL, NULL));
     OnResponseStarted(request.get());
@@ -284,6 +290,12 @@
     EXPECT_EQ(1, (*counters_)["on_network_bytes_received_count"]);
   }
 
+  void OnNetworkBytesSentInternal(const URLRequest& request,
+                                  int64_t bytes_sent) override {
+    ++(*counters_)["on_network_bytes_sent_count"];
+    EXPECT_EQ(1, (*counters_)["on_network_bytes_sent_count"]);
+  }
+
   void OnCompletedInternal(URLRequest* request, bool started) override {
     ++(*counters_)["on_completed_count"];
     EXPECT_EQ(1, (*counters_)["on_completed_count"]);
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index 27f230f..e768352 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -296,7 +296,7 @@
   if (ret != ERROR_IO_PENDING)
     return false;
 
-  addr_watcher_.StartWatching(addr_overlapped_.hEvent, this);
+  addr_watcher_.StartWatchingOnce(addr_overlapped_.hEvent, this);
   return true;
 }
 
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index 745336f1..1538028 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -96,6 +96,13 @@
   OnNetworkBytesReceived(request, bytes_received);
 }
 
+void NetworkDelegate::NotifyNetworkBytesSent(const URLRequest& request,
+                                             int64_t bytes_sent) {
+  DCHECK(CalledOnValidThread());
+  DCHECK_GT(bytes_sent, 0);
+  OnNetworkBytesSent(request, bytes_sent);
+}
+
 void NetworkDelegate::NotifyBeforeRedirect(URLRequest* request,
                                            const GURL& new_location) {
   DCHECK(CalledOnValidThread());
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index 3a29e26..cad221e 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -89,6 +89,7 @@
   void NotifyResponseStarted(URLRequest* request);
   void NotifyNetworkBytesReceived(const URLRequest& request,
                                   int64_t bytes_received);
+  void NotifyNetworkBytesSent(const URLRequest& request, int64_t bytes_sent);
   void NotifyCompleted(URLRequest* request, bool started);
   void NotifyURLRequestDestroyed(URLRequest* request);
   void NotifyURLRequestJobOrphaned(URLRequest* request);
@@ -213,6 +214,16 @@
   virtual void OnNetworkBytesReceived(const URLRequest& request,
                                       int64_t bytes_received) = 0;
 
+  // Called when bytes are sent over the network, such as when sending request
+  // headers or uploading request body bytes. This includes localhost requests.
+  // |bytes_sent| is the number of bytes measured at the application layer that
+  // have been sent over the network for this request since the last time
+  // OnNetworkBytesSent was called. |bytes_sent| will always be greater than 0.
+  // Currently, this is only implemented for HTTP transactions, and |bytes_sent|
+  // does not include TLS overhead or TCP retransmits.
+  virtual void OnNetworkBytesSent(const URLRequest& request,
+                                  int64_t bytes_sent) = 0;
+
   // Indicates that the URL request has been completed or failed.
   // |started| indicates whether the request has been started. If false,
   // some information like the socket address is not available.
diff --git a/net/base/network_delegate_impl.cc b/net/base/network_delegate_impl.cc
index 3cc8c21..af4d7086 100644
--- a/net/base/network_delegate_impl.cc
+++ b/net/base/network_delegate_impl.cc
@@ -59,6 +59,9 @@
 void NetworkDelegateImpl::OnNetworkBytesReceived(const URLRequest& request,
                                                  int64_t bytes_received) {}
 
+void NetworkDelegateImpl::OnNetworkBytesSent(const URLRequest& request,
+                                             int64_t bytes_sent) {}
+
 void NetworkDelegateImpl::OnCompleted(URLRequest* request, bool started) {
 }
 
diff --git a/net/base/network_delegate_impl.h b/net/base/network_delegate_impl.h
index 84e898d2..b0345dd 100644
--- a/net/base/network_delegate_impl.h
+++ b/net/base/network_delegate_impl.h
@@ -128,6 +128,16 @@
   void OnNetworkBytesReceived(const URLRequest& request,
                               int64_t bytes_received) override;
 
+  // Called when bytes are sent over the network, such as when sending request
+  // headers or uploading request body bytes. This includes localhost requests.
+  // |bytes_sent| is the number of bytes measured at the application layer that
+  // have been sent over the network for this request since the last time
+  // OnNetworkBytesSent was called. |bytes_sent| will always be greater than 0.
+  // Currently, this is only implemented for HTTP transactions, and |bytes_sent|
+  // does not include TLS overhead or TCP retransmits.
+  void OnNetworkBytesSent(const URLRequest& request,
+                          int64_t bytes_sent) override;
+
   // Indicates that the URL request has been completed or failed.
   // |started| indicates whether the request has been started. If false,
   // some information like the socket address is not available.
diff --git a/net/base/upload_disk_cache_entry_element_reader.cc b/net/base/upload_disk_cache_entry_element_reader.cc
deleted file mode 100644
index 0635aeb..0000000
--- a/net/base/upload_disk_cache_entry_element_reader.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/upload_disk_cache_entry_element_reader.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
-
-namespace net {
-
-UploadDiskCacheEntryElementReader::UploadDiskCacheEntryElementReader(
-    disk_cache::Entry* disk_cache_entry,
-    int disk_cache_stream_index,
-    int range_offset,
-    int range_length)
-    : disk_cache_entry_(disk_cache_entry),
-      disk_cache_stream_index_(disk_cache_stream_index),
-      range_begin_offset_(range_offset),
-      range_end_offset_(range_offset + range_length),
-      current_read_offset_(range_offset),
-      weak_factory_(this) {
-  DCHECK_LE(0, range_offset);
-  DCHECK_LT(0, range_length);
-  DCHECK_LE(range_offset + range_length,
-            disk_cache_entry_->GetDataSize(disk_cache_stream_index_));
-}
-
-UploadDiskCacheEntryElementReader::~UploadDiskCacheEntryElementReader() {
-}
-
-const UploadDiskCacheEntryElementReader*
-UploadDiskCacheEntryElementReader::AsDiskCacheEntryReaderForTests() const {
-  return this;
-}
-
-int UploadDiskCacheEntryElementReader::Init(
-    const CompletionCallback& callback) {
-  weak_factory_.InvalidateWeakPtrs();
-  current_read_offset_ = range_begin_offset_;
-  return OK;
-}
-
-uint64_t UploadDiskCacheEntryElementReader::GetContentLength() const {
-  return range_end_offset_ - range_begin_offset_;
-}
-
-uint64_t UploadDiskCacheEntryElementReader::BytesRemaining() const {
-  return range_end_offset_ - current_read_offset_;
-}
-
-bool UploadDiskCacheEntryElementReader::IsInMemory() const {
-  return false;
-}
-
-int UploadDiskCacheEntryElementReader::Read(
-    IOBuffer* buf,
-    int buf_length,
-    const CompletionCallback& callback) {
-  DCHECK(!callback.is_null());
-  int bytes_to_read = std::min(buf_length, static_cast<int>(BytesRemaining()));
-
-  CompletionCallback new_callback =
-      base::Bind(&UploadDiskCacheEntryElementReader::OnReadCompleted,
-                 weak_factory_.GetWeakPtr(), callback);
-
-  int result = disk_cache_entry_->ReadData(disk_cache_stream_index_,
-                                           current_read_offset_, buf,
-                                           bytes_to_read, new_callback);
-  if (result == ERR_IO_PENDING)
-    return ERR_IO_PENDING;
-  if (result > 0)
-    current_read_offset_ += result;
-  return result;
-}
-
-void UploadDiskCacheEntryElementReader::OnReadCompleted(
-    const CompletionCallback& callback,
-    int result) {
-  if (result > 0)
-    current_read_offset_ += result;
-  callback.Run(result);
-}
-
-}  // namespace net
diff --git a/net/base/upload_disk_cache_entry_element_reader.h b/net/base/upload_disk_cache_entry_element_reader.h
deleted file mode 100644
index 1885b2e9..0000000
--- a/net/base/upload_disk_cache_entry_element_reader.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_UPLOAD_DISK_CACHE_ENTRY_ELEMENT_READER_H_
-#define NET_BASE_UPLOAD_DISK_CACHE_ENTRY_ELEMENT_READER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
-#include "net/base/net_export.h"
-#include "net/base/upload_element_reader.h"
-
-namespace disk_cache {
-class Entry;
-}
-
-namespace net {
-
-// An UploadElementReader implementation for disk_cache::Entry objects. The
-// caller keeps ownership of |disk_cache_entry|, and is responsible for ensuring
-// it outlives the UploadDiskCacheEntryElementReader.
-class NET_EXPORT UploadDiskCacheEntryElementReader
-    : public UploadElementReader {
- public:
-  // Construct a new UploadDiskCacheEntryElementReader which reads from the disk
-  // cache entry |disk_cache_entry| with stream index |disk_cache_stream_index|.
-  // The new upload reader object will read |range_length| bytes, starting from
-  // |range_offset|. To read an whole cache entry give a 0 as |range_offset| and
-  // provide the length of the entry's stream as |range_length|.
-  UploadDiskCacheEntryElementReader(disk_cache::Entry* disk_cache_entry,
-                                    int disk_cache_stream_index,
-                                    int range_offset,
-                                    int range_length);
-  ~UploadDiskCacheEntryElementReader() override;
-
-  int range_offset_for_tests() const { return range_begin_offset_; }
-  int range_length_for_tests() const {
-    return range_end_offset_ - range_begin_offset_;
-  }
-
-  // UploadElementReader overrides:
-  const UploadDiskCacheEntryElementReader* AsDiskCacheEntryReaderForTests()
-      const override;
-  int Init(const CompletionCallback& callback) override;
-  uint64_t GetContentLength() const override;
-  uint64_t BytesRemaining() const override;
-  bool IsInMemory() const override;
-  int Read(IOBuffer* buf,
-           int buf_length,
-           const CompletionCallback& callback) override;
-
- private:
-  void OnReadCompleted(const CompletionCallback& callback, int result);
-
-  disk_cache::Entry* const disk_cache_entry_;
-  const int disk_cache_stream_index_;
-
-  const int range_begin_offset_;
-  const int range_end_offset_;
-
-  int current_read_offset_;
-
-  base::WeakPtrFactory<UploadDiskCacheEntryElementReader> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(UploadDiskCacheEntryElementReader);
-};
-
-}  // namespace net
-
-#endif  // NET_BASE_UPLOAD_DISK_CACHE_ENTRY_ELEMENT_READER_H_
diff --git a/net/base/upload_disk_cache_entry_element_reader_unittest.cc b/net/base/upload_disk_cache_entry_element_reader_unittest.cc
deleted file mode 100644
index 7321acc..0000000
--- a/net/base/upload_disk_cache_entry_element_reader_unittest.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/upload_disk_cache_entry_element_reader.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/disk_cache/disk_cache.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace net {
-namespace {
-
-const int kTestDiskCacheStreamIndex = 0;
-
-const char kDataKey[] = "a key";
-
-const char kData[] = "this is data in a disk cache entry";
-const size_t kDataSize = arraysize(kData) - 1;
-
-// A disk_cache::Entry that arbitrarily delays the completion of a read
-// operation to allow testing some races without flake. This is particularly
-// relevant in this unit test, which uses the always-synchronous MEMORY_CACHE.
-class DelayedReadEntry : public disk_cache::Entry {
- public:
-  explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry)
-      : entry_(entry.Pass()) {}
-  ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); }
-
-  bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); }
-
-  void RunPendingReadCallbacks() {
-    std::vector<base::Callback<void(void)>> callbacks;
-    pending_read_callbacks_.swap(callbacks);
-    for (const auto& callback : callbacks)
-      callback.Run();
-  }
-
-  // From disk_cache::Entry:
-  void Doom() override { entry_->Doom(); }
-
-  void Close() override { delete this; }  // Note this is required by the API.
-
-  std::string GetKey() const override { return entry_->GetKey(); }
-
-  base::Time GetLastUsed() const override { return entry_->GetLastUsed(); }
-
-  base::Time GetLastModified() const override {
-    return entry_->GetLastModified();
-  }
-
-  int32 GetDataSize(int index) const override {
-    return entry_->GetDataSize(index);
-  }
-
-  int ReadData(int index,
-               int offset,
-               IOBuffer* buf,
-               int buf_len,
-               const CompletionCallback& original_callback) override {
-    TestCompletionCallback callback;
-    int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback());
-    DCHECK_NE(rv, ERR_IO_PENDING)
-        << "Test expects to use a MEMORY_CACHE instance, which is synchronous.";
-    pending_read_callbacks_.push_back(base::Bind(original_callback, rv));
-    return ERR_IO_PENDING;
-  }
-
-  int WriteData(int index,
-                int offset,
-                IOBuffer* buf,
-                int buf_len,
-                const CompletionCallback& callback,
-                bool truncate) override {
-    return entry_->WriteData(index, offset, buf, buf_len, callback, truncate);
-  }
-
-  int ReadSparseData(int64 offset,
-                     IOBuffer* buf,
-                     int buf_len,
-                     const CompletionCallback& callback) override {
-    return entry_->ReadSparseData(offset, buf, buf_len, callback);
-  }
-
-  int WriteSparseData(int64 offset,
-                      IOBuffer* buf,
-                      int buf_len,
-                      const CompletionCallback& callback) override {
-    return entry_->WriteSparseData(offset, buf, buf_len, callback);
-  }
-
-  int GetAvailableRange(int64 offset,
-                        int len,
-                        int64* start,
-                        const CompletionCallback& callback) override {
-    return entry_->GetAvailableRange(offset, len, start, callback);
-  }
-
-  bool CouldBeSparse() const override { return entry_->CouldBeSparse(); }
-
-  void CancelSparseIO() override { entry_->CancelSparseIO(); }
-
-  int ReadyForSparseIO(const CompletionCallback& callback) override {
-    return entry_->ReadyForSparseIO(callback);
-  }
-
- private:
-  disk_cache::ScopedEntryPtr entry_;
-  std::vector<base::Callback<void(void)>> pending_read_callbacks_;
-};
-
-class UploadDiskCacheEntryElementReaderTest : public PlatformTest {
- public:
-  UploadDiskCacheEntryElementReaderTest() {}
-
-  ~UploadDiskCacheEntryElementReaderTest() override {}
-
-  void SetUp() override {
-    TestCompletionCallback callback;
-    int rv = disk_cache::CreateCacheBackend(
-        MEMORY_CACHE, CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false,
-        nullptr, nullptr, &cache_, callback.callback());
-    ASSERT_EQ(OK, callback.GetResult(rv));
-
-    disk_cache::Entry* tmp_entry = nullptr;
-    rv = cache_->CreateEntry(kDataKey, &tmp_entry, callback.callback());
-    ASSERT_EQ(OK, callback.GetResult(rv));
-    entry_.reset(tmp_entry);
-
-    scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(kData);
-    rv = entry_->WriteData(kTestDiskCacheStreamIndex, 0, io_buffer.get(),
-                           kDataSize, callback.callback(), false);
-    EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  }
-
-  void set_entry(disk_cache::ScopedEntryPtr entry) { entry_.swap(entry); }
-  disk_cache::Entry* entry() { return entry_.get(); }
-  disk_cache::ScopedEntryPtr release_entry() { return entry_.Pass(); }
-
- private:
-  scoped_ptr<disk_cache::Backend> cache_;
-  disk_cache::ScopedEntryPtr entry_;
-};
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, ReadAll) {
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  char read_buffer[kDataSize];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer.get(), kDataSize, callback.callback());
-  EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  EXPECT_EQ(0U, reader.BytesRemaining())
-      << "Expected a single read of |kDataSize| to retrieve entire entry.";
-  EXPECT_EQ(std::string(kData, kDataSize), std::string(read_buffer, kDataSize));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, ReadPartially) {
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  const size_t kReadBuffer1Size = kDataSize / 3;
-  char read_buffer1[kReadBuffer1Size];
-  std::fill(read_buffer1, read_buffer1 + arraysize(read_buffer1), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer1 = new WrappedIOBuffer(read_buffer1);
-
-  const size_t kReadBuffer2Size = kDataSize - kReadBuffer1Size;
-  char read_buffer2[kReadBuffer2Size];
-  scoped_refptr<IOBuffer> io_buffer2 = new WrappedIOBuffer(read_buffer2);
-
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer1.get(), kReadBuffer1Size, callback.callback());
-  EXPECT_EQ(static_cast<int>(kReadBuffer1Size), callback.GetResult(rv));
-  EXPECT_EQ(static_cast<uint64_t>(kReadBuffer2Size), reader.BytesRemaining());
-
-  rv = reader.Read(io_buffer2.get(), kReadBuffer2Size, callback.callback());
-  EXPECT_EQ(static_cast<int>(kReadBuffer2Size), callback.GetResult(rv));
-  EXPECT_EQ(0U, reader.BytesRemaining());
-
-  EXPECT_EQ(std::string(kData, kDataSize),
-            std::string(read_buffer1, kReadBuffer1Size) +
-                std::string(read_buffer2, kReadBuffer2Size));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, ReadTooMuch) {
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  const size_t kTooLargeSize = kDataSize + kDataSize / 2;
-
-  char read_buffer[kTooLargeSize];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer.get(), kTooLargeSize, callback.callback());
-  EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  EXPECT_EQ(0U, reader.BytesRemaining());
-  EXPECT_EQ(std::string(kData, kDataSize), std::string(read_buffer, kDataSize));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, ReadAsync) {
-  DelayedReadEntry* delayed_read_entry = new DelayedReadEntry(release_entry());
-  set_entry(disk_cache::ScopedEntryPtr(delayed_read_entry));
-
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-
-  char read_buffer[kDataSize];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer.get(), kDataSize, callback.callback());
-  EXPECT_EQ(ERR_IO_PENDING, rv);
-  EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  delayed_read_entry->RunPendingReadCallbacks();
-  EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  EXPECT_EQ(0U, reader.BytesRemaining())
-      << "Expected a single read of |kDataSize| to retrieve entire entry.";
-  EXPECT_EQ(std::string(kData, kDataSize), std::string(read_buffer, kDataSize));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, MultipleInit) {
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-  char read_buffer[kDataSize];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer.get(), kDataSize, callback.callback());
-  EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  EXPECT_EQ(std::string(kData, kDataSize), std::string(read_buffer, kDataSize));
-
-  rv = reader.Init(callback.callback());
-  EXPECT_EQ(OK, callback.GetResult(rv));
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-  rv = reader.Read(io_buffer.get(), kDataSize, callback.callback());
-  EXPECT_EQ(static_cast<int>(kDataSize), callback.GetResult(rv));
-  EXPECT_EQ(std::string(kData, kDataSize), std::string(read_buffer, kDataSize));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, InitDuringAsyncOperation) {
-  DelayedReadEntry* delayed_read_entry = new DelayedReadEntry(release_entry());
-  set_entry(disk_cache::ScopedEntryPtr(delayed_read_entry));
-
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           0, kDataSize);
-  char read_buffer[kDataSize];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback read_callback;
-  int rv = reader.Read(io_buffer.get(), kDataSize, read_callback.callback());
-  EXPECT_EQ(ERR_IO_PENDING, rv);
-  EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  TestCompletionCallback init_callback;
-  rv = reader.Init(init_callback.callback());
-  EXPECT_EQ(OK, init_callback.GetResult(rv));
-
-  delayed_read_entry->RunPendingReadCallbacks();
-  EXPECT_FALSE(delayed_read_entry->HasPendingReadCallbacks());
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  char read_buffer2[kDataSize];
-  std::fill(read_buffer2, read_buffer2 + arraysize(read_buffer2), '\0');
-  scoped_refptr<IOBuffer> io_buffer2 = new WrappedIOBuffer(read_buffer2);
-  TestCompletionCallback read_callback2;
-  rv = reader.Read(io_buffer2.get(), kDataSize, read_callback2.callback());
-  EXPECT_EQ(ERR_IO_PENDING, rv);
-  EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
-  EXPECT_EQ(static_cast<uint64_t>(kDataSize), reader.BytesRemaining());
-
-  delayed_read_entry->RunPendingReadCallbacks();
-  EXPECT_FALSE(delayed_read_entry->HasPendingReadCallbacks());
-  read_callback2.WaitForResult();  // Succeeds if this does not deadlock.
-  EXPECT_EQ(std::string(kData, kDataSize),
-            std::string(read_buffer2, kDataSize));
-}
-
-TEST_F(UploadDiskCacheEntryElementReaderTest, Range) {
-  const size_t kOffset = kDataSize / 4;
-  const size_t kLength = kDataSize / 3;
-
-  UploadDiskCacheEntryElementReader reader(entry(), kTestDiskCacheStreamIndex,
-                                           kOffset, kLength);
-  EXPECT_EQ(static_cast<uint64_t>(kLength), reader.BytesRemaining());
-
-  char read_buffer[kLength];
-  std::fill(read_buffer, read_buffer + arraysize(read_buffer), '\0');
-
-  scoped_refptr<IOBuffer> io_buffer = new WrappedIOBuffer(read_buffer);
-  TestCompletionCallback callback;
-  int rv = reader.Read(io_buffer.get(), kLength, callback.callback());
-  EXPECT_EQ(static_cast<int>(kLength), callback.GetResult(rv));
-  EXPECT_EQ(0U, reader.BytesRemaining());
-  EXPECT_EQ(std::string(kData + kOffset, kLength),
-            std::string(read_buffer, kLength));
-}
-
-}  // namespace
-}  // namespace net
diff --git a/net/base/upload_element_reader.cc b/net/base/upload_element_reader.cc
index 70b657c..2a95eb8 100644
--- a/net/base/upload_element_reader.cc
+++ b/net/base/upload_element_reader.cc
@@ -6,11 +6,6 @@
 
 namespace net {
 
-const UploadDiskCacheEntryElementReader*
-UploadElementReader::AsDiskCacheEntryReaderForTests() const {
-  return nullptr;
-}
-
 const UploadBytesElementReader* UploadElementReader::AsBytesReader() const {
   return nullptr;
 }
diff --git a/net/base/upload_element_reader.h b/net/base/upload_element_reader.h
index 267df8c..2814efa 100644
--- a/net/base/upload_element_reader.h
+++ b/net/base/upload_element_reader.h
@@ -13,7 +13,6 @@
 
 class IOBuffer;
 class UploadBytesElementReader;
-class UploadDiskCacheEntryElementReader;
 class UploadFileElementReader;
 
 // An interface to read an upload data element.
@@ -22,11 +21,6 @@
   UploadElementReader() {}
   virtual ~UploadElementReader() {}
 
-  // Returns this instance's pointer as UploadDiskCacheEntryElementReader when
-  // possible, otherwise returns nullptr.
-  virtual const UploadDiskCacheEntryElementReader*
-  AsDiskCacheEntryReaderForTests() const;
-
   // Returns this instance's pointer as UploadBytesElementReader when possible,
   // otherwise returns NULL.
   virtual const UploadBytesElementReader* AsBytesReader() const;
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc
index 0c2ee356..16988557e 100644
--- a/net/cert_net/cert_net_fetcher_impl_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -34,7 +34,7 @@
   RequestContext() : storage_(this) {
     ProxyConfig no_proxy;
     storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
-    storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier).Pass());
+    storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier));
     storage_.set_transport_security_state(
         make_scoped_ptr(new TransportSecurityState));
     storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
@@ -55,8 +55,7 @@
         make_scoped_ptr(new HttpCache(network_session.get(),
                                       HttpCache::DefaultBackend::InMemory(0)))
             .Pass());
-    storage_.set_job_factory(
-        make_scoped_ptr(new URLRequestJobFactoryImpl()).Pass());
+    storage_.set_job_factory(make_scoped_ptr(new URLRequestJobFactoryImpl()));
   }
 
   ~RequestContext() override { AssertNoURLRequests(); }
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 0e17308..6eed2be 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -21,7 +21,7 @@
 
 - www_us_army_mil_cert.der
 - dod_ca_17_cert.der
-- dod_root_ca_2_cert.der : 
+- dod_root_ca_2_cert.der :
      A certificate chain used for testing certificate imports
 
 - unosoft_hu_cert : Certificate used by X509CertificateTest.UnoSoftCertParsing.
@@ -155,6 +155,9 @@
 - punycodetest.pem : A test self-signed server certificate with punycode name.
      The common name is "xn--wgv71a119e.com" (日本語.com)
 
+- sha1_2016.pem
+    Used to test the handling of SHA1 certificates expiring in 2016.
+
 - 10_year_validity.pem
 - 11_year_validity.pem
 - 39_months_after_2015_04.pem
diff --git a/net/data/ssl/certificates/sha1_2016.pem b/net/data/ssl/certificates/sha1_2016.pem
new file mode 100644
index 0000000..074a0db
--- /dev/null
+++ b/net/data/ssl/certificates/sha1_2016.pem
@@ -0,0 +1,82 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=Test Root CA
+        Validity
+            Not Before: Oct 30 00:00:00 2008 GMT
+            Not After : Dec 30 00:00:00 2016 GMT
+        Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c0:96:28:b8:79:2e:15:f8:33:2e:29:06:75:f8:
+                    99:8d:df:03:c3:6e:cf:ed:ff:ef:73:5c:9e:40:af:
+                    5b:3b:14:21:74:11:59:75:c7:35:00:12:f1:af:97:
+                    ca:2f:f6:5b:55:9e:38:5b:a3:e9:5a:23:39:aa:a5:
+                    fa:12:76:db:89:26:64:8a:ff:ec:f9:f1:a3:2e:3c:
+                    a2:f0:f4:95:a0:27:1a:18:04:4f:dd:32:39:c7:96:
+                    85:53:15:48:33:3a:c0:6b:6e:2a:91:12:01:fe:a1:
+                    79:4d:4d:6f:a1:ea:2d:ab:bb:06:ac:cb:8f:10:75:
+                    2f:75:cb:23:05:9b:73:b9:17:ba:4d:3d:b9:e4:54:
+                    12:a7:d2:b4:bd:df:00:c2:b6:3e:e0:60:3a:f3:9a:
+                    08:e4:72:8d:49:5a:b9:92:e9:ea:76:6c:8b:30:4f:
+                    7c:85:09:dd:4b:43:d8:3e:a0:6d:da:ad:2e:8b:af:
+                    e6:cc:a9:8c:b2:a0:81:fc:bb:da:05:45:0e:bc:ea:
+                    f1:b8:5d:a4:4f:ce:f7:78:7e:57:6e:54:f5:2b:40:
+                    be:ee:d6:05:dd:ea:c1:02:cb:cc:1e:5b:24:06:73:
+                    9d:41:8e:18:79:37:4f:f7:e8:dc:f3:b3:c0:db:e4:
+                    48:1e:d3:f4:dc:da:30:2c:2e:86:10:b1:a8:90:ec:
+                    af:c3
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Subject Key Identifier: 
+                A5:46:1F:A2:BE:47:ED:CD:33:DC:51:DF:70:2C:A5:E1:AB:4F:7D:41
+            X509v3 Authority Key Identifier: 
+                keyid:BC:F7:30:D1:3C:C0:F2:79:FA:EF:9F:C9:6C:5C:93:F3:8A:68:AB:83
+
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+            X509v3 Subject Alternative Name: 
+                IP Address:127.0.0.1
+    Signature Algorithm: sha256WithRSAEncryption
+         b5:a1:00:b0:53:8c:6e:61:f1:9e:1c:a4:5c:3b:f0:25:56:66:
+         e9:b1:b1:70:a0:d3:f2:c5:06:d1:99:08:82:bb:d9:b8:d5:c0:
+         57:89:11:90:d1:ad:36:08:d7:68:39:cf:d4:28:59:4b:09:92:
+         f6:65:65:b2:f0:7f:8b:01:0a:46:e4:1f:2b:d8:20:7d:73:2e:
+         2b:a9:8d:8c:d7:08:4e:1c:e2:fb:9e:68:34:b7:60:91:d1:a8:
+         70:0b:7a:50:e9:8c:98:fa:47:1e:e1:f6:f5:65:30:e7:07:be:
+         cb:c2:85:97:91:4d:8a:47:b7:d2:64:49:70:e7:ce:85:ed:f3:
+         f8:6a:72:70:f4:20:9d:c0:91:e9:ba:6b:26:a1:e6:e4:41:0f:
+         8b:f5:d9:7f:5c:2f:4e:46:37:a0:47:3d:de:21:d4:94:91:04:
+         21:ee:3b:b2:1d:64:4c:c6:7b:49:1c:b9:51:7a:99:ca:63:89:
+         7a:04:ca:31:7e:a7:c3:58:1f:96:d7:41:3f:88:e7:b5:cf:55:
+         e2:53:16:07:c2:ad:4a:76:64:b2:1c:07:9a:ae:c9:03:ac:3b:
+         1f:a9:09:45:7f:c0:8a:3f:47:83:41:c6:8a:48:04:32:cd:c5:
+         79:5e:59:4e:48:eb:ed:e4:0e:9d:f9:a2:40:2b:fc:02:59:c0:
+         26:8a:9a:72
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0
+IFJvb3QgQ0EwHhcNMDgxMDMwMDAwMDAwWhcNMTYxMjMwMDAwMDAwWjBgMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwJYouHkuFfgzLikGdfiZjd8Dw27P
+7f/vc1yeQK9bOxQhdBFZdcc1ABLxr5fKL/ZbVZ44W6PpWiM5qqX6EnbbiSZkiv/s
++fGjLjyi8PSVoCcaGARP3TI5x5aFUxVIMzrAa24qkRIB/qF5TU1voeotq7sGrMuP
+EHUvdcsjBZtzuRe6TT255FQSp9K0vd8AwrY+4GA685oI5HKNSVq5kunqdmyLME98
+hQndS0PYPqBt2q0ui6/mzKmMsqCB/LvaBUUOvOrxuF2kT873eH5XblT1K0C+7tYF
+3erBAsvMHlskBnOdQY4YeTdP9+jc87PA2+RIHtP03NowLC6GELGokOyvwwIDAQAB
+o4GAMH4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUpUYfor5H7c0z3FHfcCyl4atP
+fUEwHwYDVR0jBBgwFoAUvPcw0TzA8nn675/JbFyT84poq4MwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEL
+BQADggEBALWhALBTjG5h8Z4cpFw78CVWZumxsXCg0/LFBtGZCIK72bjVwFeJEZDR
+rTYI12g5z9QoWUsJkvZlZbLwf4sBCkbkHyvYIH1zLiupjYzXCE4c4vueaDS3YJHR
+qHALelDpjJj6Rx7h9vVlMOcHvsvChZeRTYpHt9JkSXDnzoXt8/hqcnD0IJ3Akem6
+ayah5uRBD4v12X9cL05GN6BHPd4h1JSRBCHuO7IdZEzGe0kcuVF6mcpjiXoEyjF+
+p8NYH5bXQT+I57XPVeJTFgfCrUp2ZLIcB5quyQOsOx+pCUV/wIo/R4NBxopIBDLN
+xXleWU5I6+3kDp35okAr/AJZwCaKmnI=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/generate-test-certs.sh b/net/data/ssl/scripts/generate-test-certs.sh
index feb2453..d777718c 100755
--- a/net/data/ssl/scripts/generate-test-certs.sh
+++ b/net/data/ssl/scripts/generate-test-certs.sh
@@ -170,6 +170,19 @@
     -sha256 \
     -out ../certificates/large_key.pem
 
+## SHA1 certificate expiring in 2016.
+try openssl req -config ../scripts/ee.cnf -sha1 \
+  -newkey rsa:2048 -text -out out/sha1_2016.req
+CA_COMMON_NAME="Test Root CA" \
+  try openssl ca \
+    -batch \
+    -extensions user_cert \
+    -startdate 081030000000Z \
+    -enddate   161230000000Z \
+    -in out/sha1_2016.req \
+    -out ../certificates/sha1_2016.pem \
+    -config ca.cnf
+
 ## Validity too long unit test support.
 try openssl req -config ../scripts/ee.cnf \
   -newkey rsa:2048 -text -out ../certificates/10_year_validity.req
diff --git a/net/ftp/ftp_network_layer.cc b/net/ftp/ftp_network_layer.cc
index f498299c..e8053dee 100644
--- a/net/ftp/ftp_network_layer.cc
+++ b/net/ftp/ftp_network_layer.cc
@@ -18,12 +18,6 @@
 FtpNetworkLayer::~FtpNetworkLayer() {
 }
 
-// static
-FtpTransactionFactory* FtpNetworkLayer::CreateFactory(
-    HostResolver* host_resolver) {
-  return new FtpNetworkLayer(host_resolver);
-}
-
 FtpTransaction* FtpNetworkLayer::CreateTransaction() {
   if (suspended_)
     return NULL;
diff --git a/net/ftp/ftp_network_layer.h b/net/ftp/ftp_network_layer.h
index 30ed960..e22ec49 100644
--- a/net/ftp/ftp_network_layer.h
+++ b/net/ftp/ftp_network_layer.h
@@ -21,8 +21,6 @@
   explicit FtpNetworkLayer(HostResolver* host_resolver);
   ~FtpNetworkLayer() override;
 
-  static FtpTransactionFactory* CreateFactory(HostResolver* host_resolver);
-
   // FtpTransactionFactory methods:
   FtpTransaction* CreateTransaction() override;
   void Suspend(bool suspend) override;
diff --git a/net/http/failing_http_transaction_factory.cc b/net/http/failing_http_transaction_factory.cc
index f63cd4d2..adb9691 100644
--- a/net/http/failing_http_transaction_factory.cc
+++ b/net/http/failing_http_transaction_factory.cc
@@ -58,6 +58,7 @@
   UploadProgress GetUploadProgress() const override;
   void SetQuicServerInfo(QuicServerInfo* quic_server_info) override;
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
   void SetPriority(RequestPriority priority) override;
   void SetWebSocketHandshakeStreamCreateHelper(
       WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
@@ -154,6 +155,10 @@
   return false;
 }
 
+bool FailingHttpTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  return false;
+}
+
 void FailingHttpTransaction::SetPriority(RequestPriority priority)  {}
 
 void FailingHttpTransaction::SetWebSocketHandshakeStreamCreateHelper(
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index 169e38c..436127f 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -104,6 +104,13 @@
   parser()->GetSSLCertRequestInfo(cert_request_info);
 }
 
+bool HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+  if (!state_.connection() || !state_.connection()->socket())
+    return false;
+
+  return state_.connection()->socket()->GetPeerAddress(endpoint) == OK;
+}
+
 void HttpBasicStream::Drain(HttpNetworkSession* session) {
   HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
   drainer->Start(session);
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index 5ece112..c9428d6f 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -74,6 +74,8 @@
 
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
 
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
+
   void Drain(HttpNetworkSession* session) override;
 
   void SetPriority(RequestPriority priority) override;
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 9dc77b0..9dd8458 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -599,6 +599,18 @@
   return true;
 }
 
+bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  if (network_trans_)
+    return network_trans_->GetRemoteEndpoint(endpoint);
+
+  if (!old_remote_endpoint_.address().empty()) {
+    *endpoint = old_remote_endpoint_;
+    return true;
+  }
+
+  return false;
+}
+
 void HttpCache::Transaction::SetPriority(RequestPriority priority) {
   priority_ = priority;
   if (network_trans_)
@@ -1403,6 +1415,7 @@
 
   // Old load timing information, if any, is now obsolete.
   old_network_trans_load_timing_.reset();
+  old_remote_endpoint_ = IPEndPoint();
 
   if (websocket_handshake_stream_base_create_helper_)
     network_trans_->SetWebSocketHandshakeStreamCreateHelper(
@@ -2814,6 +2827,8 @@
   network_trans_->GetConnectionAttempts(&attempts);
   for (const auto& attempt : attempts)
     old_connection_attempts_.push_back(attempt);
+  old_remote_endpoint_ = IPEndPoint();
+  network_trans_->GetRemoteEndpoint(&old_remote_endpoint_);
   network_trans_.reset();
 }
 
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 303e0e3..482bb64 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -20,6 +20,7 @@
 #include "base/time/time.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
 #include "net/base/load_states.h"
 #include "net/base/request_priority.h"
 #include "net/base/upload_progress.h"
@@ -150,6 +151,7 @@
   UploadProgress GetUploadProgress(void) const override;
   void SetQuicServerInfo(QuicServerInfo* quic_server_info) override;
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
   void SetPriority(RequestPriority priority) override;
   void SetWebSocketHandshakeStreamCreateHelper(
       WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
@@ -479,6 +481,7 @@
   scoped_ptr<LoadTimingInfo> old_network_trans_load_timing_;
 
   ConnectionAttempts old_connection_attempts_;
+  IPEndPoint old_remote_endpoint_;
 
   // The helper object to use to create WebSocketHandshakeStreamBase
   // objects. Only relevant when establishing a WebSocket connection.
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 5992b3ba..6eeef8f1 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -19,6 +19,7 @@
 #include "net/base/cache_type.h"
 #include "net/base/elements_upload_data_stream.h"
 #include "net/base/host_port_pair.h"
+#include "net/base/ip_endpoint.h"
 #include "net/base/load_flags.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/load_timing_info_test_util.h"
@@ -139,7 +140,8 @@
                             const BoundNetLog& net_log,
                             LoadTimingInfo* load_timing_info,
                             int64_t* sent_bytes,
-                            int64_t* received_bytes) {
+                            int64_t* received_bytes,
+                            IPEndPoint* remote_endpoint) {
   TestCompletionCallback callback;
 
   // write to the cache
@@ -171,6 +173,9 @@
     trans->GetLoadTimingInfo(load_timing_info);
   }
 
+  if (remote_endpoint)
+    ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint));
+
   ReadAndVerifyTransaction(trans.get(), trans_info);
 
   if (sent_bytes)
@@ -184,7 +189,7 @@
                                    const MockHttpRequest& request,
                                    HttpResponseInfo* response_info) {
   RunTransactionTestBase(cache, trans_info, request, response_info,
-                         BoundNetLog(), nullptr, nullptr, nullptr);
+                         BoundNetLog(), nullptr, nullptr, nullptr, nullptr);
 }
 
 void RunTransactionTestAndGetTiming(HttpCache* cache,
@@ -192,7 +197,19 @@
                                     const BoundNetLog& log,
                                     LoadTimingInfo* load_timing_info) {
   RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
-                         nullptr, log, load_timing_info, nullptr, nullptr);
+                         nullptr, log, load_timing_info, nullptr, nullptr,
+                         nullptr);
+}
+
+void RunTransactionTestAndGetTimingAndConnectedSocketAddress(
+    HttpCache* cache,
+    const MockTransaction& trans_info,
+    const BoundNetLog& log,
+    LoadTimingInfo* load_timing_info,
+    IPEndPoint* remote_endpoint) {
+  RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
+                         nullptr, log, load_timing_info, nullptr, nullptr,
+                         remote_endpoint);
 }
 
 void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) {
@@ -219,7 +236,8 @@
     const BoundNetLog& log,
     LoadTimingInfo* load_timing_info) {
   RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
-                         response, log, load_timing_info, nullptr, nullptr);
+                         response, log, load_timing_info, nullptr, nullptr,
+                         nullptr);
 }
 
 void RunTransactionTestWithResponse(HttpCache* cache,
@@ -238,7 +256,8 @@
     LoadTimingInfo* load_timing_info) {
   HttpResponseInfo response;
   RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info),
-                         &response, log, load_timing_info, nullptr, nullptr);
+                         &response, log, load_timing_info, nullptr, nullptr,
+                         nullptr);
   response.headers->GetNormalizedHeaders(response_headers);
 }
 
@@ -1991,13 +2010,17 @@
   transaction.handler = ETagGet_ConditionalRequest_Handler;
   BoundTestNetLog log;
   LoadTimingInfo load_timing_info;
-  RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(),
-                                 &load_timing_info);
+  IPEndPoint remote_endpoint;
+  RunTransactionTestAndGetTimingAndConnectedSocketAddress(
+      cache.http_cache(), transaction, log.bound(), &load_timing_info,
+      &remote_endpoint);
 
   EXPECT_EQ(2, cache.network_layer()->transaction_count());
   EXPECT_EQ(1, cache.disk_cache()->open_count());
   EXPECT_EQ(1, cache.disk_cache()->create_count());
   TestLoadTimingNetworkRequest(load_timing_info);
+
+  EXPECT_FALSE(remote_endpoint.address().empty());
 }
 
 class RevalidationServer {
@@ -7166,7 +7189,7 @@
                                       int64_t* received_bytes) {
   RunTransactionTestBase(cache.http_cache(), trans_info,
                          MockHttpRequest(trans_info), nullptr, BoundNetLog(),
-                         nullptr, sent_bytes, received_bytes);
+                         nullptr, sent_bytes, received_bytes, nullptr);
 }
 
 }  // namespace
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index f060cd7..c12f95d 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -451,6 +451,14 @@
   return true;
 }
 
+bool HttpNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  if (!remote_endpoint_.address().size())
+    return false;
+
+  *endpoint = remote_endpoint_;
+  return true;
+}
+
 void HttpNetworkTransaction::SetPriority(RequestPriority priority) {
   priority_ = priority;
   if (stream_request_)
@@ -813,6 +821,9 @@
 int HttpNetworkTransaction::DoInitStream() {
   DCHECK(stream_.get());
   next_state_ = STATE_INIT_STREAM_COMPLETE;
+
+  stream_->GetRemoteEndpoint(&remote_endpoint_);
+
   return stream_->InitializeStream(request_, priority_, net_log_, io_callback_);
 }
 
@@ -1443,6 +1454,7 @@
   request_headers_.Clear();
   response_ = HttpResponseInfo();
   establishing_tunnel_ = false;
+  remote_endpoint_ = IPEndPoint();
 }
 
 void HttpNetworkTransaction::RecordSSLFallbackMetrics(int result) {
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index bc6ce2c..a5e5b08 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -72,6 +72,7 @@
   UploadProgress GetUploadProgress() const override;
   void SetQuicServerInfo(QuicServerInfo* quic_server_info) override;
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
   void SetPriority(RequestPriority priority) override;
   void SetWebSocketHandshakeStreamCreateHelper(
       WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
@@ -351,6 +352,7 @@
   BeforeProxyHeadersSentCallback before_proxy_headers_sent_callback_;
 
   ConnectionAttempts connection_attempts_;
+  IPEndPoint remote_endpoint_;
 
   DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction);
 };
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 3b9bf30..fb658467 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -269,6 +269,7 @@
     int64_t total_sent_bytes;
     LoadTimingInfo load_timing_info;
     ConnectionAttempts connection_attempts;
+    IPEndPoint remote_endpoint_after_start;
   };
 
   void SetUp() override {
@@ -365,6 +366,11 @@
     EXPECT_EQ("127.0.0.1", response->socket_address.host());
     EXPECT_EQ(80, response->socket_address.port());
 
+    bool got_endpoint =
+        trans->GetRemoteEndpoint(&out.remote_endpoint_after_start);
+    EXPECT_EQ(got_endpoint,
+              out.remote_endpoint_after_start.address().size() > 0);
+
     rv = ReadTransaction(trans.get(), &out.response_data);
     EXPECT_EQ(OK, rv);
 
@@ -692,6 +698,8 @@
   int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads));
   EXPECT_EQ(reads_size, out.total_received_bytes);
   EXPECT_EQ(0u, out.connection_attempts.size());
+
+  EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
 }
 
 // Response with no status line.
@@ -1602,6 +1610,10 @@
 
   rv = callback.WaitForResult();
   EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+  IPEndPoint endpoint;
+  EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
+  EXPECT_LT(0u, endpoint.address().size());
 }
 
 // What do various browsers do when the server closes a non-keepalive
@@ -2003,6 +2015,122 @@
   EXPECT_EQ(100, response->headers->GetContentLength());
 }
 
+// Test the request-challenge-retry sequence for basic auth.
+// (basic auth is the easiest to mock, because it has no randomness).
+TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
+  HttpRequestInfo request;
+  request.method = "GET";
+  request.url = GURL("http://www.example.org/");
+  request.load_flags = 0;
+
+  TestNetLog log;
+  MockHostResolver* resolver = new MockHostResolver();
+  session_deps_.net_log = &log;
+  session_deps_.host_resolver.reset(resolver);
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+  scoped_ptr<HttpTransaction> trans(
+      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
+
+  resolver->rules()->ClearRules();
+  resolver->rules()->AddRule("www.example.org", "127.0.0.1");
+
+  MockWrite data_writes1[] = {
+      MockWrite("GET / HTTP/1.1\r\n"
+                "Host: www.example.org\r\n"
+                "Connection: keep-alive\r\n\r\n"),
+  };
+
+  MockRead data_reads1[] = {
+      MockRead("HTTP/1.0 401 Unauthorized\r\n"),
+      // Give a couple authenticate options (only the middle one is actually
+      // supported).
+      MockRead("WWW-Authenticate: Basic invalid\r\n"),  // Malformed.
+      MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
+      MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
+      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+      // Large content-length -- won't matter, as connection will be reset.
+      MockRead("Content-Length: 10000\r\n\r\n"),
+      MockRead(SYNCHRONOUS, ERR_FAILED),
+  };
+
+  // After calling trans->RestartWithAuth(), this is the request we should
+  // be issuing -- the final header line contains the credentials.
+  MockWrite data_writes2[] = {
+      MockWrite("GET / HTTP/1.1\r\n"
+                "Host: www.example.org\r\n"
+                "Connection: keep-alive\r\n"
+                "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+  };
+
+  // Lastly, the server responds with the actual content.
+  MockRead data_reads2[] = {
+      MockRead("HTTP/1.0 200 OK\r\n"),
+      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+      MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK),
+  };
+
+  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
+                                 data_writes1, arraysize(data_writes1));
+  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
+                                 data_writes2, arraysize(data_writes2));
+  session_deps_.socket_factory->AddSocketDataProvider(&data1);
+  session_deps_.socket_factory->AddSocketDataProvider(&data2);
+
+  TestCompletionCallback callback1;
+
+  EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(),
+                                                 BoundNetLog())));
+
+  LoadTimingInfo load_timing_info1;
+  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
+  TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
+
+  int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1));
+  EXPECT_EQ(writes_size1, trans->GetTotalSentBytes());
+  int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1));
+  EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes());
+
+  const HttpResponseInfo* response = trans->GetResponseInfo();
+  ASSERT_TRUE(response);
+  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
+
+  IPEndPoint endpoint;
+  EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
+  ASSERT_FALSE(endpoint.address().empty());
+  EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
+
+  resolver->rules()->ClearRules();
+  resolver->rules()->AddRule("www.example.org", "127.0.0.2");
+
+  TestCompletionCallback callback2;
+
+  EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth(
+                    AuthCredentials(kFoo, kBar), callback2.callback())));
+
+  LoadTimingInfo load_timing_info2;
+  EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
+  TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
+  // The load timing after restart should have a new socket ID, and times after
+  // those of the first load timing.
+  EXPECT_LE(load_timing_info1.receive_headers_end,
+            load_timing_info2.connect_timing.connect_start);
+  EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
+
+  int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2));
+  EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes());
+  int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2));
+  EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes());
+
+  response = trans->GetResponseInfo();
+  ASSERT_TRUE(response);
+  EXPECT_FALSE(response->auth_challenge.get());
+  EXPECT_EQ(100, response->headers->GetContentLength());
+
+  EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
+  ASSERT_FALSE(endpoint.address().empty());
+  EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
+}
+
 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
   HttpRequestInfo request;
   request.method = "GET";
@@ -2426,35 +2554,32 @@
 
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n\r\n"),
+      MockWrite(
+          "CONNECT www.example.org:443 HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Proxy-Connection: keep-alive\r\n\r\n"),
+
+      // After calling trans->RestartWithAuth(), this is the request we should
+      // be issuing -- the final header line contains the credentials.
+      MockWrite(
+          "CONNECT www.example.org:443 HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Proxy-Connection: keep-alive\r\n"
+          "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+
+      MockWrite(
+          "GET / HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Connection: keep-alive\r\n\r\n"),
   };
 
-  // The proxy responds to the connect with a 407, using a non-persistent
+  // The proxy responds to the connect with a 407, using a persistent
   // connection.
   MockRead data_reads1[] = {
       // No credentials.
       MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
       MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
-  };
 
-  // Since the first connection couldn't be reused, need to establish another
-  // once given credentials.
-  MockWrite data_writes2[] = {
-      // After calling trans->RestartWithAuth(), this is the request we should
-      // be issuing -- the final header line contains the credentials.
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n"
-                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
-
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n\r\n"),
-  };
-
-  MockRead data_reads2[] = {
       MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
 
       MockRead("HTTP/1.1 200 OK\r\n"),
@@ -2466,9 +2591,6 @@
   StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
                                  data_writes1, arraysize(data_writes1));
   session_deps_.socket_factory->AddSocketDataProvider(&data1);
-  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
-                                 data_writes2, arraysize(data_writes2));
-  session_deps_.socket_factory->AddSocketDataProvider(&data2);
   SSLSocketDataProvider ssl(ASYNC, OK);
   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
 
@@ -2550,48 +2672,44 @@
 
   // Since we have proxy, should try to establish tunnel.
   MockWrite data_writes1[] = {
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n\r\n"),
-  };
+      MockWrite(
+          "CONNECT www.example.org:443 HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Proxy-Connection: keep-alive\r\n\r\n"),
 
-  // The proxy responds to the connect with a 407, using a non-persistent
-  // connection.
-  MockRead data_reads1[] = {
-      // No credentials.
-      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
-      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
-      MockRead("Proxy-Connection: close\r\n\r\n"),
-  };
-
-  MockWrite data_writes2[] = {
       // After calling trans->RestartWithAuth(), this is the request we should
       // be issuing -- the final header line contains the credentials.
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n"
-                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
+      MockWrite(
+          "CONNECT www.example.org:443 HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Proxy-Connection: keep-alive\r\n"
+          "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
 
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n\r\n"),
+      MockWrite(
+          "GET / HTTP/1.1\r\n"
+          "Host: www.example.org\r\n"
+          "Connection: keep-alive\r\n\r\n"),
   };
 
-  MockRead data_reads2[] = {
-      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
+  // The proxy responds to the connect with a 407, using a persistent
+  // connection.
+  MockRead data_reads1[] = {
+    // No credentials.
+    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
+    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
+    MockRead("Proxy-Connection: close\r\n\r\n"),
 
-      MockRead("HTTP/1.1 200 OK\r\n"),
-      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
-      MockRead("Content-Length: 5\r\n\r\n"),
-      MockRead(SYNCHRONOUS, "hello"),
+    MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
+
+    MockRead("HTTP/1.1 200 OK\r\n"),
+    MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
+    MockRead("Content-Length: 5\r\n\r\n"),
+    MockRead(SYNCHRONOUS, "hello"),
   };
 
   StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
                                  data_writes1, arraysize(data_writes1));
   session_deps_.socket_factory->AddSocketDataProvider(&data1);
-  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
-                                 data_writes2, arraysize(data_writes2));
-  session_deps_.socket_factory->AddSocketDataProvider(&data2);
   SSLSocketDataProvider ssl(ASYNC, OK);
   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
 
@@ -2869,97 +2987,6 @@
   session->CloseAllConnections();
 }
 
-// Test the case a proxy closes a socket while the challenge body is being
-// drained.
-TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
-  HttpRequestInfo request;
-  request.method = "GET";
-  request.url = GURL("https://www.example.org/");
-  // Ensure that proxy authentication is attempted even
-  // when the no authentication data flag is set.
-  request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA;
-
-  // Configure against proxy server "myproxy:70".
-  session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70");
-  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-
-  scoped_ptr<HttpTransaction> trans(
-      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-
-  // Since we have proxy, should try to establish tunnel.
-  MockWrite data_writes1[] = {
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n\r\n"),
-  };
-
-  // The proxy responds to the connect with a 407, using a persistent
-  // connection.
-  MockRead data_reads1[] = {
-      // No credentials.
-      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
-      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
-      MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
-      // Server hands up in the middle of the body.
-      MockRead(ASYNC, ERR_CONNECTION_CLOSED),
-  };
-
-  MockWrite data_writes2[] = {
-      // After calling trans->RestartWithAuth(), this is the request we should
-      // be issuing -- the final header line contains the credentials.
-      MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Proxy-Connection: keep-alive\r\n"
-                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
-
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n\r\n"),
-  };
-
-  MockRead data_reads2[] = {
-      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
-
-      MockRead("HTTP/1.1 200 OK\r\n"),
-      MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
-      MockRead("Content-Length: 5\r\n\r\n"),
-      MockRead(SYNCHRONOUS, "hello"),
-  };
-
-  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
-                                 data_writes1, arraysize(data_writes1));
-  session_deps_.socket_factory->AddSocketDataProvider(&data1);
-  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
-                                 data_writes2, arraysize(data_writes2));
-  session_deps_.socket_factory->AddSocketDataProvider(&data2);
-  SSLSocketDataProvider ssl(ASYNC, OK);
-  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
-  TestCompletionCallback callback;
-
-  int rv = trans->Start(&request, callback.callback(), BoundNetLog());
-  EXPECT_EQ(OK, callback.GetResult(rv));
-
-  const HttpResponseInfo* response = trans->GetResponseInfo();
-  ASSERT_TRUE(response);
-  ASSERT_TRUE(response->headers);
-  EXPECT_TRUE(response->headers->IsKeepAlive());
-  EXPECT_EQ(407, response->headers->response_code());
-  EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
-
-  rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
-  EXPECT_EQ(OK, callback.GetResult(rv));
-
-  response = trans->GetResponseInfo();
-  ASSERT_TRUE(response);
-  ASSERT_TRUE(response->headers);
-  EXPECT_TRUE(response->headers->IsKeepAlive());
-  EXPECT_EQ(200, response->headers->response_code());
-  std::string body;
-  EXPECT_EQ(OK, ReadTransaction(trans.get(), &body));
-  EXPECT_EQ("hello", body);
-}
-
 // Test that we don't read the response body when we fail to establish a tunnel,
 // even if the user cancels the proxy's auth attempt.
 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
@@ -8326,6 +8353,10 @@
 
   rv = callback.WaitForResult();
   EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+
+  IPEndPoint endpoint;
+  EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
+  EXPECT_LT(0u, endpoint.address().size());
 }
 
 // Check that a connection closed after the start of the headers finishes ok.
@@ -8365,6 +8396,10 @@
   rv = ReadTransaction(trans.get(), &response_data);
   EXPECT_EQ(OK, rv);
   EXPECT_EQ("", response_data);
+
+  IPEndPoint endpoint;
+  EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint));
+  EXPECT_LT(0u, endpoint.address().size());
 }
 
 // Make sure that a dropped connection while draining the body for auth
@@ -10525,7 +10560,8 @@
 
       // kProxyChallenge uses Proxy-Connection: close which means that the
       // socket is closed and a new one will be created for the next request.
-      if (read_write_round.read.data == kProxyChallenge.data) {
+      if (read_write_round.read.data == kProxyChallenge.data &&
+          read_write_round.write.data != kConnect.data) {
         mock_reads.push_back(std::vector<MockRead>());
         mock_writes.push_back(std::vector<MockWrite>());
       }
@@ -10979,20 +11015,23 @@
       // SPDY request
       CreateMockWrite(*req, 4),
   };
+  const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
+                                         "Proxy-Authenticate: Mock\r\n"
+                                         "Proxy-Connection: close\r\n"
+                                         "\r\n");
+  const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
   MockRead data_reads_2[] = {
       // First connection attempt fails
-      MockRead(ASYNC, 1,
-               "HTTP/1.1 407 Unauthorized\r\n"
-               "Proxy-Authenticate: Mock\r\n"
-               "Content-Length: 0\r\n"
-               "Proxy-Connection: keep-alive\r\n"
-               "\r\n"),
+      MockRead(ASYNC, kRejectConnectResponse,
+               arraysize(kRejectConnectResponse) - 1, 1),
 
       // Second connection attempt passes
-      MockRead(ASYNC, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
+      MockRead(ASYNC, kAcceptConnectResponse,
+               arraysize(kAcceptConnectResponse) - 1, 3),
 
       // SPDY response
-      CreateMockRead(*resp.get(), 5), CreateMockRead(*data.get(), 6),
+      CreateMockRead(*resp.get(), 5),
+      CreateMockRead(*data.get(), 6),
       MockRead(ASYNC, 0, 0, 7),
   };
   SequencedSocketData data_2(data_reads_2, arraysize(data_reads_2),
@@ -13067,7 +13106,7 @@
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
 
-  MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
+  MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
   StaticSocketDataProvider data;
   data.set_connect_data(mock_connect);
   session_deps_.socket_factory->AddSocketDataProvider(&data);
@@ -13078,7 +13117,7 @@
   EXPECT_EQ(ERR_IO_PENDING, rv);
 
   rv = callback.WaitForResult();
-  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
 
   // We don't care whether this succeeds or fails, but it shouldn't crash.
   HttpRequestHeaders request_headers;
@@ -13087,7 +13126,11 @@
   ConnectionAttempts attempts;
   trans->GetConnectionAttempts(&attempts);
   ASSERT_EQ(1u, attempts.size());
-  EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
+
+  IPEndPoint endpoint;
+  EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
+  EXPECT_TRUE(endpoint.address().empty());
 }
 
 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
@@ -13100,7 +13143,7 @@
   scoped_ptr<HttpTransaction> trans(
       new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
 
-  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
+  MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
   StaticSocketDataProvider data;
   data.set_connect_data(mock_connect);
   session_deps_.socket_factory->AddSocketDataProvider(&data);
@@ -13111,7 +13154,7 @@
   EXPECT_EQ(ERR_IO_PENDING, rv);
 
   rv = callback.WaitForResult();
-  EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
 
   // We don't care whether this succeeds or fails, but it shouldn't crash.
   HttpRequestHeaders request_headers;
@@ -13120,7 +13163,11 @@
   ConnectionAttempts attempts;
   trans->GetConnectionAttempts(&attempts);
   ASSERT_EQ(1u, attempts.size());
-  EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result);
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result);
+
+  IPEndPoint endpoint;
+  EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint));
+  EXPECT_TRUE(endpoint.address().empty());
 }
 
 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
@@ -13383,6 +13430,8 @@
     ADD_FAILURE();
   }
 
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+
   void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); }
 
   void SetPriority(RequestPriority priority) override { priority_ = priority; }
@@ -13599,6 +13648,8 @@
     NOTREACHED();
   }
 
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+
   void Drain(HttpNetworkSession* session) override { NOTREACHED(); }
 
   void SetPriority(RequestPriority priority) override { NOTREACHED(); }
@@ -14446,8 +14497,7 @@
       // No credentials.
       MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
       MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
-      MockRead("Content-Length: 0\r\n"),
-      MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
+      MockRead("Proxy-Connection: close\r\n\r\n"),
 
       MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
 
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc
index 92a631e7..f5feb58 100644
--- a/net/http/http_proxy_client_socket.cc
+++ b/net/http/http_proxy_client_socket.cc
@@ -267,32 +267,36 @@
   if (!response_.headers.get())
     return ERR_CONNECTION_RESET;
 
-  // If the connection can't be reused, just return ERR_CONNECTION_CLOSED.
-  // The request should be retried at a higher layer.
-  if (!response_.headers->IsKeepAlive() ||
-      !http_stream_parser_->CanFindEndOfResponse() ||
-      !transport_->socket()->IsConnectedAndIdle()) {
-    transport_->socket()->Disconnect();
-    return ERR_CONNECTION_CLOSED;
+  bool keep_alive = false;
+  if (response_.headers->IsKeepAlive() &&
+      http_stream_parser_->CanFindEndOfResponse()) {
+    if (!http_stream_parser_->IsResponseBodyComplete()) {
+      next_state_ = STATE_DRAIN_BODY;
+      drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
+      return OK;
+    }
+    keep_alive = true;
   }
 
-  // If the auth request had a body, need to drain it before reusing the socket.
-  if (!http_stream_parser_->IsResponseBodyComplete()) {
-    next_state_ = STATE_DRAIN_BODY;
-    drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
-    return OK;
-  }
-
-  return DidDrainBodyForAuthRestart();
+  // We don't need to drain the response body, so we act as if we had drained
+  // the response body.
+  return DidDrainBodyForAuthRestart(keep_alive);
 }
 
-int HttpProxyClientSocket::DidDrainBodyForAuthRestart() {
-  next_state_ = STATE_GENERATE_AUTH_TOKEN;
-  transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
+int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
+  if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
+    next_state_ = STATE_GENERATE_AUTH_TOKEN;
+    transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
+  } else {
+    // This assumes that the underlying transport socket is a TCP socket,
+    // since only TCP sockets are restartable.
+    next_state_ = STATE_TCP_RESTART;
+    transport_->socket()->Disconnect();
+  }
 
   // Reset the other member variables.
-  drain_buf_ = nullptr;
-  parser_buf_ = nullptr;
+  drain_buf_ = NULL;
+  parser_buf_ = NULL;
   http_stream_parser_.reset();
   request_line_.clear();
   request_headers_.Clear();
@@ -369,6 +373,13 @@
       case STATE_DRAIN_BODY_COMPLETE:
         rv = DoDrainBodyComplete(rv);
         break;
+      case STATE_TCP_RESTART:
+        DCHECK_EQ(OK, rv);
+        rv = DoTCPRestart();
+        break;
+      case STATE_TCP_RESTART_COMPLETE:
+        rv = DoTCPRestartComplete(rv);
+        break;
       case STATE_DONE:
         break;
       default:
@@ -529,13 +540,31 @@
   if (result < 0)
     return result;
 
-  if (!http_stream_parser_->IsResponseBodyComplete()) {
-    // Keep draining.
-    next_state_ = STATE_DRAIN_BODY;
-    return OK;
-  }
+  if (http_stream_parser_->IsResponseBodyComplete())
+    return DidDrainBodyForAuthRestart(true);
 
-  return DidDrainBodyForAuthRestart();
+  // Keep draining.
+  next_state_ = STATE_DRAIN_BODY;
+  return OK;
+}
+
+int HttpProxyClientSocket::DoTCPRestart() {
+  next_state_ = STATE_TCP_RESTART_COMPLETE;
+  return transport_->socket()->Connect(
+      base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this)));
+}
+
+int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
+  // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed.
+  tracked_objects::ScopedTracker tracking_profile(
+      FROM_HERE_WITH_EXPLICIT_FUNCTION(
+          "462784 HttpProxyClientSocket::DoTCPRestartComplete"));
+
+  if (result != OK)
+    return result;
+
+  next_state_ = STATE_GENERATE_AUTH_TOKEN;
+  return result;
 }
 
 }  // namespace net
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index ab973cc..439278aa 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -99,6 +99,8 @@
     STATE_READ_HEADERS_COMPLETE,
     STATE_DRAIN_BODY,
     STATE_DRAIN_BODY_COMPLETE,
+    STATE_TCP_RESTART,
+    STATE_TCP_RESTART_COMPLETE,
     STATE_DONE,
   };
 
@@ -108,7 +110,7 @@
   static const int kDrainBodyBufferSize = 1024;
 
   int PrepareForAuthRestart();
-  int DidDrainBodyForAuthRestart();
+  int DidDrainBodyForAuthRestart(bool keep_alive);
 
   void LogBlockedTunnelResponse() const;
 
@@ -124,6 +126,8 @@
   int DoReadHeadersComplete(int result);
   int DoDrainBody();
   int DoDrainBodyComplete(int result);
+  int DoTCPRestart();
+  int DoTCPRestartComplete(int result);
 
   CompletionCallback io_callback_;
   State next_state_;
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index a6e3dde6..e44e6ee1 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -105,6 +105,7 @@
   int64_t GetTotalSentBytes() const override { return 0; }
   void GetSSLInfo(SSLInfo* ssl_info) override {}
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
 
   // Mocked API
   int ReadResponseBody(IOBuffer* buf,
diff --git a/net/http/http_stream.h b/net/http/http_stream.h
index 078b7f1..1febd11 100644
--- a/net/http/http_stream.h
+++ b/net/http/http_stream.h
@@ -28,6 +28,7 @@
 struct HttpRequestInfo;
 class HttpResponseInfo;
 class IOBuffer;
+class IPEndPoint;
 struct LoadTimingInfo;
 class SSLCertRequestInfo;
 class SSLInfo;
@@ -144,6 +145,11 @@
   // behavior is undefined.
   virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) = 0;
 
+  // Gets the remote endpoint of the socket that the HTTP stream is using, if
+  // any. Returns true and fills in |endpoint| if it is available; returns false
+  // and does not modify |endpoint| if it is unavailable.
+  virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0;
+
   // In the case of an HTTP error or redirect, flush the response body (usually
   // a simple error or "this page has moved") so that we can re-use the
   // underlying connection. This stream is responsible for deleting itself when
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index c3a6073..8955017cd 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1279,15 +1279,6 @@
     return OK;
   }
 
-  if (result == ERR_CONNECTION_CLOSED || result == ERR_CONNECTION_RESET ||
-      result == ERR_SOCKET_NOT_CONNECTED) {
-    // The server may have closed the connection while waiting for auth data.
-    // Automatically try to use a new connection.
-    establishing_tunnel_ = false;
-    ReturnToStateInitConnection(true /* close connection */);
-    return OK;
-  }
-
   return ReconsiderProxyAfterError(result);
 }
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index b1799718..ed61ebf 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -93,6 +93,7 @@
   }
   void GetSSLInfo(SSLInfo* ssl_info) override {}
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
   void Drain(HttpNetworkSession* session) override {}
   void SetPriority(RequestPriority priority) override {}
   UploadProgress GetUploadProgress() const override { return UploadProgress(); }
diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h
index a205602..9ccf3f1 100644
--- a/net/http/http_transaction.h
+++ b/net/http/http_transaction.h
@@ -160,6 +160,12 @@
   // provide.
   virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const = 0;
 
+  // Gets the remote endpoint of the socket that the transaction's underlying
+  // stream is using or did use, if any. Returns true and fills in |endpoint|
+  // if it is available; returns false and leaves |endpoint| unchanged if it is
+  // unavailable.
+  virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) const = 0;
+
   // Called when the priority of the parent job changes.
   virtual void SetPriority(RequestPriority priority) = 0;
 
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc
index 40ae10a..628c8fa 100644
--- a/net/http/http_transaction_test_util.cc
+++ b/net/http/http_transaction_test_util.cc
@@ -378,6 +378,16 @@
   return true;
 }
 
+bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  IPAddressNumber number;
+  number.push_back(127);
+  number.push_back(0);
+  number.push_back(0);
+  number.push_back(1);
+  *endpoint = IPEndPoint(number, 80);
+  return true;
+}
+
 void MockNetworkTransaction::SetPriority(RequestPriority priority) {
   priority_ = priority;
 }
diff --git a/net/http/http_transaction_test_util.h b/net/http/http_transaction_test_util.h
index 202b761..61aaeee9 100644
--- a/net/http/http_transaction_test_util.h
+++ b/net/http/http_transaction_test_util.h
@@ -213,6 +213,8 @@
 
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
 
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
+
   void SetPriority(RequestPriority priority) override;
 
   void SetWebSocketHandshakeStreamCreateHelper(
diff --git a/net/http/proxy_connect_redirect_http_stream.cc b/net/http/proxy_connect_redirect_http_stream.cc
index 9a03845..d0f69fe7 100644
--- a/net/http/proxy_connect_redirect_http_stream.cc
+++ b/net/http/proxy_connect_redirect_http_stream.cc
@@ -97,6 +97,11 @@
   NOTREACHED();
 }
 
+bool ProxyConnectRedirectHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+  NOTREACHED();
+  return false;
+}
+
 void ProxyConnectRedirectHttpStream::Drain(HttpNetworkSession* session) {
   NOTREACHED();
 }
diff --git a/net/http/proxy_connect_redirect_http_stream.h b/net/http/proxy_connect_redirect_http_stream.h
index 77745a00..1b0b6d6 100644
--- a/net/http/proxy_connect_redirect_http_stream.h
+++ b/net/http/proxy_connect_redirect_http_stream.h
@@ -56,6 +56,7 @@
 
   void GetSSLInfo(SSLInfo* ssl_info) override;
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   void Drain(HttpNetworkSession* session) override;
 
   // This function may be called.
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h
index ec19b20..fb834860 100644
--- a/net/http/transport_security_state_static.h
+++ b/net/http/transport_security_state_static.h
@@ -2999,424 +2999,423 @@
     0xe0, 0xfb, 0x3a, 0xec, 0xe9, 0xd4, 0x27, 0x9b, 0xc6, 0x71, 0x52, 0x45,
     0x6e, 0x88, 0x3c, 0xd3, 0x7b, 0xa0, 0x60, 0xeb, 0xdf, 0x01, 0xa7, 0x5e,
     0xf6, 0x7f, 0x3a, 0xfe, 0x8e, 0x75, 0xfb, 0x70, 0x75, 0xe0, 0x81, 0xa7,
-    0x5f, 0x04, 0x62, 0x47, 0x52, 0x1b, 0xc7, 0x1c, 0xbe, 0x8f, 0x6a, 0x0e,
-    0xa0, 0xa6, 0x03, 0xc8, 0xea, 0x0e, 0xac, 0x77, 0xad, 0x7c, 0x63, 0xf7,
-    0x63, 0x4e, 0xbf, 0xb6, 0x9c, 0x30, 0x74, 0x75, 0xfd, 0xcf, 0xb3, 0xa0,
-    0x57, 0x3a, 0xfd, 0xd1, 0x8c, 0xd9, 0x97, 0xfd, 0xb9, 0x66, 0xe7, 0x03,
-    0x84, 0xd1, 0x06, 0xb2, 0x69, 0x6a, 0x11, 0x5a, 0x8a, 0xd7, 0xe7, 0x6a,
-    0x2e, 0x0e, 0xbf, 0xa5, 0xd1, 0x7e, 0x7c, 0x75, 0xb1, 0xa7, 0xa4, 0x24,
-    0xb7, 0xe8, 0xf7, 0xe5, 0xb0, 0x75, 0xfe, 0x92, 0x2e, 0x3b, 0xfc, 0x27,
-    0x5f, 0xfe, 0x8c, 0x1e, 0x7d, 0x9b, 0x49, 0xdd, 0x67, 0x5f, 0x9d, 0x8f,
-    0x67, 0x74, 0x7f, 0x9e, 0x34, 0xa5, 0x6d, 0x53, 0x6c, 0x0a, 0xca, 0x1b,
-    0x58, 0xe7, 0xb2, 0x61, 0x85, 0x35, 0xed, 0x64, 0x8e, 0xbf, 0x27, 0x32,
-    0x41, 0x3a, 0xf2, 0x77, 0x0e, 0xba, 0x17, 0x87, 0x80, 0xd2, 0x6b, 0xe0,
-    0xeb, 0xb0, 0x75, 0xf8, 0x76, 0xc3, 0xce, 0x75, 0x61, 0xe4, 0xb9, 0x0d,
-    0xc0, 0x13, 0xaa, 0x13, 0x05, 0x45, 0xbd, 0xba, 0xe8, 0x82, 0xf7, 0x70,
-    0x4e, 0xbf, 0xfe, 0x75, 0x3d, 0x1b, 0xfb, 0x71, 0xe1, 0x7f, 0x8e, 0xbf,
-    0xff, 0x85, 0xd4, 0xfd, 0xfc, 0x5f, 0xda, 0x4e, 0x7a, 0x8c, 0x1d, 0x58,
-    0x8c, 0x91, 0x1a, 0x02, 0x85, 0xda, 0xe0, 0x75, 0xf2, 0x0b, 0x84, 0xeb,
-    0xff, 0x2f, 0x3d, 0xaf, 0xfa, 0x79, 0x61, 0xd7, 0xed, 0x46, 0xfd, 0x07,
-    0x32, 0x6f, 0xe8, 0x28, 0x95, 0xd2, 0xf5, 0xfb, 0xfc, 0xce, 0xfb, 0x3a,
-    0xfb, 0xb8, 0x9c, 0x0e, 0xbf, 0xb4, 0x9b, 0xc0, 0x6c, 0xeb, 0xff, 0xfd,
-    0x13, 0x7e, 0x46, 0x83, 0x7a, 0x07, 0xe5, 0xa7, 0xba, 0x87, 0x56, 0x27,
-    0x58, 0x90, 0xad, 0x59, 0x1f, 0x4a, 0x7c, 0x45, 0xc4, 0x59, 0x72, 0xd5,
-    0x06, 0x8b, 0xf2, 0xfb, 0x5b, 0xcc, 0x3a, 0xff, 0xe9, 0x78, 0x12, 0x92,
-    0xfd, 0xe8, 0x59, 0xd7, 0xfb, 0xda, 0x89, 0xf3, 0x41, 0x3a, 0xee, 0xe1,
-    0xd7, 0xff, 0xdd, 0x80, 0xe3, 0x7f, 0x60, 0xe0, 0x7b, 0x07, 0x5f, 0xfc,
-    0x98, 0x39, 0x9a, 0xfd, 0x2d, 0x2c, 0xeb, 0xff, 0x3c, 0x73, 0x2f, 0xda,
-    0xe4, 0x30, 0x75, 0x05, 0x37, 0xfe, 0x48, 0x11, 0x15, 0x5c, 0xce, 0x61,
-    0x5d, 0x27, 0x79, 0x0e, 0xf2, 0x91, 0xb3, 0xaf, 0xe0, 0xc7, 0xdb, 0xce,
-    0x4e, 0xa6, 0x4f, 0x29, 0x63, 0x97, 0xfa, 0x17, 0x89, 0xb9, 0xa4, 0x75,
-    0xc9, 0x31, 0xd7, 0xff, 0xbd, 0x1d, 0x17, 0x9e, 0x37, 0xb7, 0x91, 0xd7,
-    0xbc, 0x93, 0x9d, 0x7e, 0xf9, 0xf9, 0x89, 0x8e, 0xbc, 0x30, 0xd3, 0xaf,
-    0xfe, 0x0a, 0x4d, 0xd8, 0xdf, 0x32, 0x8d, 0x9d, 0x7f, 0xf0, 0xbf, 0x3a,
-    0xd6, 0x6c, 0x3d, 0xc3, 0xaf, 0xff, 0x43, 0x7f, 0x6f, 0x10, 0x0a, 0x9c,
-    0xe2, 0xc3, 0xa9, 0x11, 0x26, 0x28, 0x75, 0xf9, 0x3b, 0x64, 0x16, 0x5a,
-    0x43, 0x8e, 0x09, 0x4e, 0x86, 0xb8, 0xa1, 0xb1, 0x68, 0x3a, 0xf7, 0x53,
-    0xc7, 0x5b, 0x86, 0x1a, 0xaf, 0xe1, 0xf5, 0x0b, 0xb0, 0x41, 0x5e, 0xc8,
-    0xe9, 0x92, 0x16, 0x7d, 0x23, 0x78, 0xfa, 0x3e, 0x84, 0xb5, 0xff, 0x60,
-    0xc8, 0x71, 0x70, 0xd3, 0xaf, 0xdd, 0x4e, 0x18, 0x13, 0xaf, 0xfc, 0x18,
-    0x1c, 0x10, 0x4b, 0x34, 0x75, 0xf9, 0xd6, 0x9c, 0x58, 0x75, 0xef, 0x47,
-    0x27, 0x56, 0x1e, 0x23, 0x94, 0x5e, 0x15, 0x67, 0x88, 0xeb, 0xff, 0xff,
-    0x47, 0x51, 0x6c, 0xcd, 0x27, 0xdf, 0xfe, 0xa7, 0x3a, 0x6a, 0x4e, 0x75,
-    0x05, 0x39, 0x05, 0x0d, 0x50, 0xa2, 0x67, 0xf1, 0x20, 0xe2, 0x23, 0xbf,
-    0x9f, 0x71, 0xdf, 0xe1, 0x3a, 0xfa, 0x12, 0x78, 0x3a, 0xf9, 0x87, 0xcd,
-    0x1d, 0x7f, 0xd2, 0x5b, 0xcb, 0xda, 0x85, 0x0e, 0xa8, 0x3d, 0xa7, 0x21,
-    0xbd, 0xa4, 0x13, 0xaf, 0xc2, 0xdf, 0xda, 0xe4, 0xea, 0xc3, 0xc4, 0x71,
-    0xaa, 0x74, 0xcb, 0x3e, 0x2e, 0x17, 0xa0, 0x32, 0x5d, 0x3c, 0x8e, 0xbc,
-    0x9d, 0x43, 0xab, 0x93, 0x63, 0xe1, 0x7b, 0xef, 0xe0, 0x7d, 0x1d, 0x7f,
-    0xa4, 0x01, 0x9f, 0x49, 0xc9, 0xd7, 0xdf, 0x7d, 0x9c, 0x9d, 0x7f, 0x71,
-    0x7b, 0x1c, 0x5a, 0x75, 0xff, 0x01, 0xe4, 0x1c, 0xcf, 0xb4, 0x75, 0xfe,
-    0xf9, 0x39, 0xe6, 0x59, 0xe3, 0xab, 0xa7, 0xdb, 0xa3, 0x8b, 0xf7, 0x3a,
-    0x5a, 0x2b, 0x9d, 0x7f, 0xfe, 0xcd, 0x7e, 0xeb, 0xa7, 0xbe, 0x00, 0x8b,
-    0xc8, 0xea, 0x84, 0x40, 0x09, 0x5d, 0xfc, 0xf3, 0xfc, 0xe2, 0x13, 0xaa,
-    0x64, 0xf8, 0xf6, 0x69, 0xd2, 0x4f, 0x42, 0x6f, 0x84, 0x28, 0xb8, 0xc8,
-    0x6f, 0xfb, 0xbf, 0xe1, 0xbc, 0x79, 0xb8, 0x3a, 0xa1, 0x55, 0x56, 0x4a,
-    0x06, 0x76, 0x8b, 0xa6, 0x01, 0xd6, 0x59, 0xd5, 0xc9, 0xa7, 0x54, 0x8b,
-    0xdf, 0xfd, 0x1b, 0xce, 0x0f, 0x2f, 0xb3, 0x02, 0x75, 0xfc, 0xfc, 0xc8,
-    0x60, 0x27, 0x5f, 0xf4, 0x73, 0x24, 0x15, 0xbf, 0x8e, 0xa7, 0x3e, 0x31,
-    0x2c, 0xbf, 0x3c, 0xb2, 0x78, 0x3a, 0xff, 0xe8, 0xd6, 0xb1, 0x7e, 0x18,
-    0x5e, 0x8e, 0xbf, 0xf9, 0x23, 0x42, 0xf2, 0xfd, 0xac, 0xd9, 0xd7, 0xff,
-    0xf9, 0x35, 0x3e, 0x31, 0x82, 0x0e, 0x28, 0x67, 0x05, 0xf6, 0x75, 0xfe,
-    0xe6, 0x5a, 0x9a, 0x51, 0x39, 0xd4, 0x14, 0xd0, 0xda, 0x4c, 0x28, 0x5e,
-    0x43, 0x03, 0x15, 0xff, 0xff, 0xba, 0x9c, 0xfb, 0x39, 0xf6, 0xf7, 0x1e,
-    0xfb, 0xf8, 0xcb, 0xb8, 0x75, 0xf0, 0x42, 0xe2, 0x75, 0xff, 0xa5, 0x03,
-    0xed, 0xa7, 0x0c, 0x09, 0xd7, 0xfe, 0x7e, 0xb5, 0x1f, 0xf6, 0x9f, 0xa7,
-    0x5f, 0xff, 0xb4, 0x3f, 0xba, 0xe9, 0xef, 0x80, 0x22, 0xf2, 0x3a, 0xff,
-    0x75, 0x14, 0xe3, 0x06, 0xd4, 0x3a, 0xff, 0xa1, 0x85, 0xf6, 0x10, 0x67,
-    0x3a, 0xff, 0xf8, 0x73, 0x58, 0xb8, 0x6e, 0x79, 0x37, 0x87, 0x5b, 0x1a,
-    0x8b, 0xbf, 0x1c, 0x70, 0x38, 0xbf, 0xa7, 0xcd, 0xa3, 0x60, 0xeb, 0xe1,
-    0x0c, 0x2c, 0xeb, 0xf7, 0x0c, 0x10, 0x39, 0xd7, 0xf3, 0xfd, 0x81, 0x79,
-    0x1d, 0x50, 0x7e, 0x78, 0x40, 0x84, 0xf4, 0x88, 0xcb, 0xec, 0x27, 0xea,
-    0x17, 0x6f, 0xe7, 0x26, 0x0c, 0x29, 0xf2, 0x36, 0x36, 0xa5, 0x23, 0x84,
-    0xc4, 0x1d, 0x3e, 0xf8, 0xf8, 0x63, 0x10, 0xf4, 0x60, 0x57, 0xff, 0x60,
-    0xfd, 0x99, 0xbd, 0x7a, 0x30, 0xeb, 0xfe, 0xe7, 0xd9, 0xb4, 0x9d, 0xd6,
-    0x75, 0xb3, 0xe3, 0xfa, 0x14, 0x1b, 0xff, 0x62, 0xbb, 0x8f, 0xdf, 0x95,
-    0x32, 0x43, 0xaf, 0xee, 0x1d, 0x48, 0xde, 0x8e, 0xbf, 0xff, 0x40, 0xcb,
-    0x3a, 0x8b, 0x0e, 0x4d, 0x19, 0xb3, 0xaf, 0xd0, 0xde, 0xa4, 0xc7, 0x5e,
-    0x6b, 0xec, 0xeb, 0xf6, 0x9b, 0x1b, 0x50, 0xea, 0xe9, 0xe1, 0xfc, 0x37,
-    0x7f, 0xb2, 0x58, 0x81, 0xea, 0x1d, 0x7d, 0xe9, 0x2f, 0xa7, 0x5f, 0x22,
-    0x88, 0xc1, 0xd5, 0x87, 0x88, 0x24, 0x57, 0x7e, 0xc3, 0xaf, 0xb4, 0x30,
-    0xb3, 0xaa, 0x0d, 0xbf, 0x22, 0xf7, 0xd9, 0xd9, 0x2c, 0xea, 0x85, 0x50,
-    0xf2, 0x27, 0xc4, 0x65, 0x0b, 0xba, 0xa4, 0xed, 0x42, 0x47, 0xa7, 0x40,
-    0x2b, 0xf1, 0x90, 0xde, 0x0a, 0xda, 0x75, 0xba, 0x75, 0xda, 0x91, 0xd5,
-    0xf1, 0xa6, 0x00, 0x85, 0xfd, 0x3c, 0xd2, 0x55, 0x6e, 0x73, 0xaf, 0x3e,
-    0x6c, 0xeb, 0xc3, 0x9e, 0x3a, 0xba, 0x6d, 0x04, 0x6a, 0xef, 0x09, 0xd7,
-    0xa3, 0x9d, 0x1d, 0x7c, 0x83, 0x2c, 0x3a, 0xf4, 0xee, 0x27, 0x50, 0x4f,
-    0x59, 0x63, 0x9e, 0x1f, 0xbf, 0x67, 0xba, 0x9e, 0x3a, 0xfc, 0xfc, 0xe7,
-    0x3e, 0x3a, 0xca, 0x74, 0xf3, 0xbc, 0x4d, 0x72, 0x6c, 0xeb, 0xfa, 0x7f,
-    0xd3, 0xbb, 0xf4, 0xea, 0x56, 0x53, 0xdf, 0x86, 0x99, 0x10, 0x63, 0x5a,
-    0x3e, 0xf4, 0xa5, 0xc5, 0x6f, 0xfb, 0x02, 0x14, 0xe7, 0x39, 0xf1, 0xd7,
-    0xcd, 0x18, 0x91, 0xd5, 0xd3, 0xd9, 0x73, 0x9b, 0xfd, 0x19, 0xe8, 0xeb,
-    0x84, 0xea, 0x9c, 0xf4, 0x42, 0x43, 0x7f, 0xf0, 0x60, 0x3b, 0x8f, 0x23,
-    0x50, 0x27, 0x5f, 0x4d, 0x1c, 0x52, 0x3a, 0xfe, 0xf3, 0x42, 0x15, 0xec,
-    0xeb, 0xfe, 0x9b, 0x5c, 0x1c, 0x67, 0x00, 0x4e, 0xbe, 0xcf, 0x62, 0xce,
-    0xb8, 0x54, 0x3a, 0xda, 0x73, 0x6c, 0x02, 0x0b, 0xfb, 0xa0, 0x9e, 0x6e,
-    0xa1, 0xd7, 0xc2, 0x39, 0xe3, 0xaa, 0x13, 0x9e, 0x09, 0x1e, 0x21, 0x28,
-    0x4a, 0x85, 0xd3, 0x39, 0x74, 0x9b, 0xc5, 0xf7, 0xf7, 0xe9, 0xa3, 0xc3,
-    0xc0, 0xeb, 0xff, 0xc3, 0x1c, 0x37, 0x1b, 0xc4, 0xec, 0x04, 0xeb, 0xc2,
-    0xeb, 0x3a, 0xa4, 0x89, 0x3c, 0x31, 0x44, 0x8b, 0x32, 0xac, 0xbb, 0x8e,
-    0x75, 0x6c, 0xf1, 0x5a, 0x0e, 0x2b, 0x51, 0xb8, 0x94, 0xb5, 0x3c, 0x3a,
-    0xe5, 0x0d, 0x90, 0xce, 0x20, 0xe4, 0xec, 0xd2, 0x90, 0xcd, 0x6c, 0xab,
-    0xee, 0x63, 0xe3, 0x48, 0xcc, 0x66, 0x95, 0x91, 0xb8, 0xda, 0x97, 0x18,
-    0x2f, 0x67, 0xd7, 0x1e, 0x50, 0x57, 0xd1, 0xc3, 0xaa, 0x5b, 0x86, 0x56,
-    0x66, 0xa7, 0x87, 0x3d, 0x2e, 0xc8, 0x10, 0x8d, 0x61, 0x0b, 0x8e, 0x50,
-    0x0f, 0xf9, 0x55, 0xdc, 0x51, 0x82, 0x53, 0x2e, 0xed, 0xb3, 0xb6, 0xe4,
-    0xde, 0xff, 0xf3, 0x2b, 0x79, 0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x13, 0x65,
-    0xfe, 0x67, 0x36, 0xd7, 0x76, 0x9a, 0x2a, 0xdb, 0xfd, 0x29, 0x03, 0xc3,
-    0x12, 0x3a, 0xfb, 0x3a, 0xfe, 0x3a, 0xca, 0x8c, 0x3d, 0x21, 0x32, 0xbf,
-    0xf7, 0x63, 0xb1, 0x3e, 0xe3, 0x02, 0x75, 0xfa, 0x36, 0xbe, 0x84, 0xeb,
-    0xc1, 0xc1, 0x3a, 0xf3, 0xbb, 0x4d, 0x15, 0xa5, 0xf9, 0x4e, 0x74, 0x0e,
-    0x4e, 0xa6, 0x9e, 0x92, 0x13, 0xdf, 0xfe, 0x4f, 0x4a, 0x1b, 0xd4, 0xf6,
-    0x9f, 0x93, 0xab, 0x67, 0xd5, 0xc0, 0x86, 0xff, 0xf7, 0x51, 0x70, 0xdc,
-    0x5e, 0x0f, 0xb8, 0xce, 0xbf, 0xfe, 0x6c, 0x6f, 0x3e, 0x75, 0xbc, 0xa1,
-    0x1a, 0x75, 0xff, 0xf4, 0xb5, 0x83, 0x0b, 0x7c, 0xf7, 0xa1, 0x67, 0x5d,
-    0xef, 0x42, 0x26, 0x5d, 0x36, 0xff, 0xff, 0xf4, 0x70, 0x4f, 0x6b, 0x14,
-    0x6f, 0x53, 0xd9, 0x30, 0xc2, 0xe7, 0xc6, 0x0e, 0xbf, 0xd1, 0xe7, 0xef,
-    0xe0, 0xc1, 0xd7, 0xd2, 0xf2, 0x4e, 0x75, 0xfb, 0xff, 0x86, 0x3e, 0x3a,
-    0xb9, 0x3c, 0xbe, 0x04, 0x57, 0xf9, 0xe5, 0xe4, 0x9f, 0xa8, 0x75, 0x41,
-    0xeb, 0xa1, 0x2d, 0xfb, 0x3a, 0x98, 0xb3, 0xaf, 0xfe, 0x17, 0x46, 0xf5,
-    0xc1, 0x3e, 0xd0, 0xea, 0x9c, 0xf9, 0xfa, 0x4b, 0x7f, 0xa5, 0x1b, 0x9e,
-    0x37, 0x39, 0xd7, 0xb3, 0x7f, 0x1d, 0x7e, 0x9b, 0x02, 0xb5, 0x73, 0xaf,
-    0xe1, 0x86, 0x39, 0x96, 0x8e, 0xa4, 0x3f, 0x59, 0x87, 0x38, 0x8a, 0xea,
-    0x11, 0xb7, 0x90, 0xa9, 0xbf, 0xff, 0xff, 0xb1, 0x1b, 0x9e, 0x81, 0xf6,
-    0xbf, 0x42, 0x07, 0x17, 0xfb, 0x70, 0x92, 0x7d, 0x1d, 0x7f, 0x67, 0x9c,
-    0x7e, 0x01, 0xd7, 0xf7, 0x7f, 0x24, 0xee, 0x27, 0x54, 0x8f, 0x6b, 0x0b,
-    0x2c, 0xca, 0xa9, 0x7a, 0x52, 0x0a, 0xa7, 0x3d, 0x09, 0x3e, 0x43, 0x59,
-    0xa4, 0x89, 0x0e, 0x3d, 0x96, 0xad, 0xeb, 0xb0, 0xd5, 0x78, 0x43, 0x8c,
-    0x3f, 0xb4, 0x4d, 0xe8, 0x70, 0xdf, 0xe6, 0x73, 0x6d, 0x77, 0x69, 0xa2,
-    0xc0, 0xbf, 0x6d, 0xae, 0xed, 0x34, 0x4e, 0xb7, 0xff, 0xfb, 0xb1, 0x38,
-    0x71, 0x6c, 0xeb, 0x59, 0xd4, 0xd0, 0x27, 0x3a, 0xfc, 0xca, 0xde, 0x4c,
-    0xe2, 0x25, 0xa6, 0x33, 0xbf, 0xd2, 0xd3, 0x2a, 0x29, 0x0b, 0x3a, 0xfd,
-    0xb6, 0xbb, 0xb4, 0xd1, 0x6c, 0xdf, 0xff, 0xe7, 0x93, 0x3a, 0x84, 0xc0,
-    0xa6, 0x6b, 0x3c, 0x30, 0x75, 0xff, 0xbe, 0x8d, 0x33, 0xd4, 0x6b, 0xec,
-    0xeb, 0xfe, 0x89, 0x46, 0xe7, 0x8d, 0xce, 0x75, 0x99, 0xc4, 0xc1, 0xd6,
-    0x66, 0xeb, 0x82, 0x7f, 0x7f, 0xfe, 0x7f, 0xbe, 0x06, 0x99, 0xcd, 0xbe,
-    0xba, 0xf2, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x5c, 0xd6, 0x59, 0xd5, 0xb3,
-    0x7a, 0xc1, 0x6d, 0xd3, 0x2c, 0xea, 0x3a, 0xcc, 0xe1, 0xe1, 0xb0, 0x45,
-    0xc6, 0x2f, 0x7e, 0xdb, 0x5d, 0xda, 0x68, 0xbb, 0xef, 0xf4, 0x99, 0xd6,
-    0xf6, 0x8c, 0x1d, 0x66, 0x70, 0xfa, 0x1c, 0xce, 0xf9, 0x95, 0x03, 0xf1,
-    0xd5, 0x0f, 0x91, 0x15, 0x96, 0xee, 0x61, 0xa6, 0xbc, 0xab, 0xa4, 0xf9,
-    0x2e, 0xe1, 0xce, 0xb8, 0x6a, 0xba, 0x17, 0xd1, 0x9e, 0x8a, 0x16, 0xa1,
-    0xaf, 0xe8, 0x50, 0xff, 0x27, 0xbf, 0xf3, 0x0e, 0x33, 0xe9, 0x07, 0x99,
-    0x1d, 0x7f, 0xf6, 0x4f, 0x8c, 0x77, 0x35, 0x88, 0x27, 0x5c, 0x8c, 0xf5,
-    0x10, 0x22, 0x7f, 0x7e, 0xd6, 0x96, 0xf2, 0x3a, 0xff, 0xff, 0xff, 0xdd,
-    0x4e, 0xa4, 0x0f, 0x85, 0xd4, 0xcf, 0x03, 0xc9, 0xed, 0x75, 0x37, 0x13,
-    0xbe, 0xda, 0x75, 0xda, 0x83, 0xaf, 0xfe, 0xe5, 0xa0, 0x7e, 0x7d, 0x98,
-    0x2a, 0x1d, 0x78, 0x5d, 0x98, 0x4c, 0x61, 0xa4, 0xfa, 0x84, 0xbf, 0x85,
-    0x6f, 0x01, 0xd6, 0x75, 0xfb, 0x38, 0xbd, 0x0a, 0x1d, 0x6e, 0x23, 0xaa,
-    0x73, 0x7b, 0x85, 0x55, 0xb3, 0xf9, 0x15, 0x8b, 0xff, 0x69, 0xd4, 0xea,
-    0x40, 0x82, 0x0e, 0xbf, 0xf7, 0x5f, 0xcf, 0xde, 0x65, 0x9e, 0x3a, 0xb0,
-    0xfe, 0x90, 0xf2, 0xe7, 0xf8, 0xeb, 0xff, 0xff, 0xc2, 0xec, 0x0e, 0x7b,
-    0xd9, 0x3c, 0x0b, 0xa9, 0xa5, 0xc6, 0x08, 0x4e, 0xac, 0x44, 0x56, 0xc5,
-    0xaf, 0xf7, 0x70, 0x29, 0xc3, 0x78, 0x75, 0xe7, 0x76, 0x9a, 0x25, 0x7b,
-    0xfc, 0xa3, 0x8f, 0xde, 0xce, 0x9d, 0x4d, 0x3d, 0xa4, 0x27, 0xbf, 0xfd,
-    0xee, 0xe4, 0x9b, 0xd4, 0x0c, 0x0f, 0x8e, 0xa9, 0x23, 0xdb, 0x70, 0x8d,
-    0x12, 0x1b, 0xa5, 0x39, 0xd7, 0xfe, 0x17, 0x60, 0x3d, 0x89, 0xf1, 0x83,
-    0xaf, 0xff, 0xd8, 0x9f, 0x62, 0xd3, 0xda, 0x85, 0xbf, 0x3e, 0x3a, 0xff,
-    0xa1, 0x7e, 0xc9, 0xa4, 0x9e, 0x3a, 0xa4, 0x88, 0xcf, 0x2a, 0x5f, 0x01,
-    0xf7, 0x23, 0xaf, 0xfa, 0x1a, 0x31, 0x3f, 0xcf, 0xe3, 0xaf, 0xff, 0xf2,
-    0x79, 0xd6, 0xe3, 0xf7, 0x58, 0x71, 0x9d, 0xa9, 0x39, 0xd4, 0x14, 0x5d,
-    0x21, 0x0b, 0x9c, 0x5f, 0xf0, 0x3e, 0x5b, 0xcb, 0x5b, 0x09, 0xd7, 0xff,
-    0xfb, 0x10, 0x7d, 0x83, 0xf8, 0x5c, 0x30, 0x33, 0xc6, 0xce, 0xb6, 0x79,
-    0x12, 0xfc, 0x0e, 0xaf, 0xfb, 0x9f, 0xb3, 0x79, 0x9e, 0xd1, 0xd4, 0x15,
-    0x5a, 0x19, 0x0c, 0xbe, 0xc3, 0x74, 0x61, 0x8b, 0xfc, 0xaa, 0xff, 0xde,
-    0x79, 0x6b, 0xb1, 0xbf, 0xe1, 0x3a, 0xff, 0xef, 0x27, 0x04, 0xf4, 0xd2,
-    0x81, 0xf1, 0xd7, 0xff, 0x9f, 0x25, 0xdc, 0x41, 0xcf, 0xb8, 0xf0, 0xeb,
-    0xcf, 0x26, 0x61, 0x7a, 0x86, 0x50, 0x9b, 0x0c, 0x2a, 0xb2, 0x31, 0x85,
-    0x9a, 0x6a, 0x57, 0x3f, 0x96, 0xff, 0xa0, 0x71, 0x22, 0xdf, 0xfe, 0xce,
-    0xb2, 0x38, 0x14, 0x1f, 0x67, 0x4e, 0xbd, 0xe8, 0x09, 0x57, 0xff, 0xba,
-    0xe9, 0xe8, 0x92, 0x6e, 0x70, 0x7c, 0x55, 0xfe, 0x76, 0xb2, 0x1d, 0xaa,
-    0x59, 0x83, 0xe5, 0xd0, 0xdd, 0x99, 0x0b, 0x29, 0x71, 0xb1, 0xa3, 0x2e,
-    0x7d, 0xb7, 0xd0, 0xad, 0xe1, 0x0a, 0xcb, 0xff, 0xcc, 0xad, 0xe4, 0xce,
-    0x6d, 0xae, 0xed, 0x34, 0x4c, 0x37, 0xff, 0xf6, 0x70, 0x70, 0xf6, 0x19,
-    0xf7, 0x70, 0x20, 0xf6, 0x8e, 0xbf, 0xfd, 0xb7, 0xf9, 0x95, 0x3d, 0x26,
-    0x23, 0x52, 0x3a, 0xec, 0x64, 0x51, 0x57, 0xfd, 0x76, 0xff, 0xe5, 0x46,
-    0x73, 0x20, 0x3f, 0x86, 0x24, 0x75, 0xfb, 0x17, 0xfb, 0x95, 0x73, 0xaf,
-    0xe8, 0x5e, 0x7d, 0x1c, 0x0e, 0xa0, 0x9e, 0xdf, 0x4b, 0x6f, 0xdd, 0x80,
-    0xa2, 0x87, 0x52, 0x1e, 0x4f, 0x11, 0x15, 0xfe, 0x87, 0x9f, 0xca, 0x3e,
-    0xce, 0xbf, 0x3e, 0xe4, 0xeb, 0x3a, 0x84, 0xf6, 0x40, 0x67, 0x7f, 0xfe,
-    0x4d, 0xf5, 0xff, 0x07, 0x25, 0xd8, 0xe0, 0x18, 0x3a, 0xff, 0x98, 0xff,
-    0xd8, 0x6f, 0x52, 0x63, 0xaf, 0x80, 0xbc, 0x09, 0xd6, 0xce, 0x4f, 0x77,
-    0x88, 0xf2, 0xba, 0x8d, 0xf1, 0x85, 0xa5, 0xfc, 0xb8, 0xc1, 0xf7, 0x19,
-    0xd6, 0xd1, 0xd7, 0xe8, 0xc1, 0xf7, 0x19, 0xd7, 0xf7, 0x53, 0xda, 0x7e,
-    0x7f, 0x1f, 0x34, 0xc5, 0xcb, 0x10, 0xbf, 0xd2, 0xf4, 0x2f, 0x87, 0xd2,
-    0x3a, 0xff, 0xff, 0x31, 0xc5, 0xec, 0xef, 0xe1, 0xc9, 0xd3, 0x07, 0x99,
-    0x68, 0xeb, 0xf3, 0x1e, 0xce, 0xb4, 0xeb, 0x0e, 0x22, 0x39, 0xd9, 0xaf,
-    0xff, 0x78, 0x5f, 0xee, 0xe2, 0x04, 0x1e, 0xd1, 0xd7, 0xfd, 0x13, 0xff,
-    0x97, 0x40, 0xf3, 0x9d, 0x50, 0x88, 0x5d, 0xa4, 0xdf, 0xfd, 0x9c, 0xcb,
-    0xf7, 0x5d, 0xb0, 0x21, 0x3a, 0xfe, 0xe1, 0xff, 0xc3, 0x1f, 0x1d, 0x7f,
-    0xfa, 0x3d, 0xf4, 0x4b, 0x39, 0xf4, 0xe0, 0x60, 0xea, 0x83, 0xfe, 0x43,
-    0x1b, 0xf9, 0xfe, 0xde, 0xd3, 0x67, 0x5e, 0xf7, 0xec, 0x3a, 0xbe, 0x3c,
-    0xaf, 0xe5, 0xb7, 0xf6, 0x91, 0x45, 0xbf, 0x8e, 0xbf, 0xff, 0xf6, 0xf3,
-    0x84, 0x0f, 0xbf, 0x7f, 0x18, 0xeb, 0xa7, 0xa3, 0xda, 0x3a, 0xfe, 0x1c,
-    0xd7, 0xe6, 0xaa, 0x8e, 0xae, 0x51, 0x9b, 0xb2, 0xde, 0x0d, 0xd7, 0xdf,
-    0xb8, 0x71, 0x4e, 0x75, 0x61, 0xee, 0xa8, 0x67, 0x65, 0x73, 0xae, 0xf6,
-    0x1d, 0x7f, 0xf9, 0x52, 0x30, 0xb7, 0x4e, 0xbf, 0xbb, 0x07, 0x54, 0x1e,
-    0xf8, 0x05, 0x6f, 0xf7, 0x52, 0x67, 0x6e, 0xa4, 0x75, 0xfe, 0x81, 0xf3,
-    0xad, 0x3c, 0x75, 0xff, 0x62, 0x62, 0xc7, 0x27, 0x73, 0xaf, 0xd1, 0xed,
-    0x7c, 0x03, 0xa9, 0x59, 0x4d, 0x4f, 0x1c, 0x9a, 0x43, 0xd3, 0x31, 0x30,
-    0xf1, 0xad, 0xff, 0xfb, 0xa3, 0x9e, 0xea, 0x67, 0x3e, 0xce, 0x11, 0xa3,
-    0xaf, 0xfe, 0x71, 0xec, 0x20, 0x53, 0x59, 0x23, 0xaf, 0x47, 0xdf, 0xce,
-    0xac, 0x45, 0x9b, 0xaa, 0x8a, 0x05, 0xef, 0xe1, 0xc3, 0xaf, 0x2a, 0x74,
-    0xaa, 0x3a, 0x9c, 0xf0, 0x74, 0x3b, 0x7f, 0x85, 0xd8, 0x8f, 0x64, 0xe7,
-    0x59, 0x95, 0x53, 0x2a, 0x6e, 0x21, 0xd6, 0x17, 0xdc, 0x8c, 0x01, 0xb0,
-    0x8d, 0xe5, 0x56, 0x68, 0x62, 0x6e, 0x15, 0x6b, 0x22, 0xec, 0x30, 0xfe,
-    0x6a, 0x18, 0xd3, 0xf5, 0x1b, 0xaf, 0xa3, 0x0e, 0x03, 0x77, 0x19, 0x0d,
-    0xff, 0xf6, 0xd3, 0x99, 0x69, 0x3d, 0xd8, 0xdf, 0xa0, 0xeb, 0xf6, 0xda,
-    0xee, 0xd3, 0x45, 0x5d, 0x7b, 0x70, 0xb3, 0xaf, 0xfa, 0x4c, 0xe6, 0xda,
-    0xee, 0xd3, 0x44, 0x79, 0x7f, 0xd1, 0x28, 0xdc, 0xf1, 0xb9, 0xce, 0xbf,
-    0xf4, 0x79, 0x00, 0xa9, 0xc9, 0x4f, 0x31, 0xd6, 0x64, 0x29, 0xaf, 0x62,
-    0x7e, 0xcc, 0xdc, 0x6c, 0x51, 0x74, 0x73, 0x7e, 0xdb, 0x5d, 0xda, 0x68,
-    0xb0, 0x6f, 0x29, 0x13, 0x9d, 0x7f, 0xff, 0x08, 0x1e, 0x75, 0xe7, 0x18,
-    0x37, 0x9b, 0x97, 0xf9, 0x1d, 0x7e, 0xc1, 0xcf, 0x68, 0xeb, 0xfd, 0xb7,
-    0x5f, 0xfd, 0xbf, 0x27, 0x59, 0x9c, 0x4c, 0x29, 0x43, 0x36, 0x8e, 0xbb,
-    0x07, 0xf2, 0x5b, 0xfc, 0xce, 0x6d, 0xae, 0xed, 0x34, 0x59, 0x57, 0xed,
-    0xb5, 0xdd, 0xa6, 0x8b, 0x4e, 0xff, 0x9c, 0x3d, 0x79, 0xba, 0x8b, 0x3a,
-    0xcc, 0xe1, 0xf5, 0xac, 0xce, 0xfc, 0xad, 0x15, 0x7a, 0xb2, 0xac, 0xab,
-    0x67, 0x5f, 0xf2, 0xab, 0xa8, 0xc0, 0x5d, 0xda, 0x75, 0xf9, 0x5a, 0x2a,
-    0x35, 0x90, 0x75, 0xfe, 0xfe, 0xbc, 0xf6, 0x93, 0x47, 0x59, 0x0e, 0xa5,
-    0x51, 0xe1, 0xf1, 0x9a, 0x5f, 0xff, 0xc9, 0xd7, 0x1f, 0x4b, 0x37, 0x90,
-    0x23, 0x9e, 0x3a, 0xfd, 0xc1, 0xc3, 0x8b, 0x3a, 0xf9, 0x71, 0xce, 0x8e,
-    0xa9, 0x22, 0x7f, 0x15, 0x66, 0x28, 0xbf, 0x7e, 0xde, 0xc1, 0xd3, 0xaf,
-    0xc8, 0xa4, 0x0b, 0x4e, 0xb6, 0x68, 0xf4, 0x3c, 0x55, 0x7f, 0xfc, 0x2d,
-    0xea, 0x75, 0x37, 0x13, 0x31, 0x9d, 0x3a, 0xff, 0xe8, 0x5a, 0xde, 0x5c,
-    0x60, 0xea, 0x6c, 0xea, 0x84, 0x4a, 0xf5, 0x3e, 0xfa, 0x3f, 0xc7, 0x4e,
-    0xbe, 0x6b, 0xbb, 0x4d, 0x16, 0xe5, 0xff, 0xb3, 0x78, 0x3f, 0xbb, 0x9c,
-    0xb0, 0x75, 0xf8, 0x7e, 0x7e, 0x74, 0x75, 0x41, 0xf4, 0x3a, 0x05, 0x72,
-    0x8d, 0x7d, 0x91, 0x6a, 0x12, 0xb7, 0xf9, 0xc7, 0xe9, 0x86, 0x16, 0x75,
-    0xe5, 0x8a, 0x1d, 0x61, 0x3a, 0xff, 0xba, 0x07, 0xd6, 0x60, 0xa8, 0x75,
-    0xfb, 0x4f, 0xcb, 0x84, 0xeb, 0x20, 0x4f, 0x7b, 0xc6, 0xf5, 0x08, 0xae,
-    0xc1, 0xae, 0xb6, 0xdf, 0xf4, 0x38, 0xf7, 0x30, 0x5a, 0x75, 0xfe, 0xf7,
-    0x92, 0x75, 0xc0, 0x9d, 0x52, 0x3e, 0x6c, 0x34, 0xbf, 0xe8, 0x10, 0x2e,
-    0x35, 0xe4, 0x3a, 0xf8, 0x31, 0x9b, 0x3a, 0xfd, 0xfb, 0x9d, 0x22, 0x87,
-    0x59, 0xe7, 0x3c, 0xbe, 0x48, 0x2f, 0xfe, 0x96, 0x75, 0x36, 0x1e, 0xc0,
-    0xb4, 0xeb, 0xfd, 0xcc, 0xa0, 0x7d, 0x9f, 0x1d, 0x7d, 0xaf, 0x93, 0xc7,
-    0x53, 0xa3, 0x03, 0x45, 0x20, 0x42, 0xfe, 0x67, 0x7f, 0xf7, 0x93, 0xe8,
-    0x90, 0x7b, 0x02, 0xd3, 0xa8, 0xeb, 0xc0, 0x7f, 0x1d, 0x70, 0x20, 0xea,
-    0x91, 0xb0, 0xf0, 0xdd, 0x1d, 0x7d, 0xcb, 0x53, 0x67, 0x5e, 0x85, 0xb3,
-    0x88, 0x87, 0xe4, 0xe9, 0x64, 0x3e, 0x0a, 0xa8, 0x4c, 0x65, 0x21, 0x95,
-    0x78, 0x7d, 0xc6, 0x75, 0xff, 0x49, 0x9c, 0xdb, 0x5d, 0xda, 0x68, 0xa1,
-    0xe9, 0x0f, 0x8d, 0xc7, 0xaf, 0xdf, 0x43, 0x71, 0x67, 0x5f, 0x44, 0xd8,
-    0x13, 0xab, 0x67, 0x91, 0xa2, 0x7b, 0xff, 0x2f, 0x20, 0x3d, 0x8e, 0x28,
-    0x98, 0xea, 0x83, 0xe2, 0x72, 0x2b, 0xff, 0x38, 0x60, 0x3d, 0x41, 0x45,
-    0x9d, 0x7f, 0xf6, 0xa0, 0x66, 0xc1, 0xf9, 0xfd, 0x87, 0x5f, 0xed, 0x01,
-    0xb9, 0xe1, 0x83, 0xa9, 0x68, 0xae, 0xe9, 0xdf, 0x90, 0xaf, 0xfe, 0x04,
-    0xba, 0xfb, 0xe7, 0xd0, 0x93, 0x9d, 0x7f, 0xd1, 0x28, 0xdc, 0xf1, 0xb9,
-    0xce, 0xbf, 0x27, 0xb4, 0xe8, 0x75, 0xff, 0x6f, 0xed, 0xb8, 0xfb, 0x3e,
-    0x3a, 0xbe, 0x3d, 0xe0, 0x12, 0xde, 0xff, 0xb9, 0x1d, 0x7f, 0x7f, 0xf0,
-    0x23, 0x27, 0x3a, 0xa4, 0x79, 0xb3, 0x0f, 0x5f, 0xfc, 0xd1, 0x8f, 0x0e,
-    0x70, 0xcd, 0xc8, 0xeb, 0xfe, 0x00, 0xa9, 0xff, 0xbd, 0x06, 0x8e, 0xbf,
-    0xc2, 0x2f, 0xef, 0xf0, 0xd3, 0xaf, 0x87, 0xe9, 0xfe, 0x3a, 0xb0, 0xf5,
-    0x90, 0xca, 0xff, 0x6b, 0xf7, 0xbf, 0x07, 0x04, 0xeb, 0x7c, 0x75, 0x93,
-    0x93, 0xc7, 0xd9, 0xb5, 0xf9, 0xf9, 0xd7, 0x90, 0xea, 0x84, 0xeb, 0xb0,
-    0x8d, 0x10, 0xfb, 0x09, 0x21, 0x67, 0xd1, 0x45, 0xf9, 0xc0, 0xa4, 0x7f,
-    0x3a, 0xfc, 0xaa, 0xcd, 0xc6, 0x8e, 0xa9, 0x8f, 0x4c, 0x4a, 0x6f, 0xf9,
-    0xf5, 0x13, 0x73, 0x2c, 0xe0, 0x75, 0xff, 0xf8, 0x3d, 0x8f, 0xec, 0xf8,
-    0x5f, 0xed, 0x6a, 0x3e, 0x2a, 0xe0, 0xe1, 0xd7, 0xe9, 0xe2, 0x77, 0xd1,
-    0xd5, 0x88, 0x96, 0x45, 0x97, 0x15, 0xbb, 0xe0, 0x1d, 0x7f, 0x3f, 0xd3,
-    0x0c, 0x04, 0xea, 0x83, 0xc4, 0xe8, 0xbd, 0x99, 0x56, 0x19, 0xf9, 0xea,
-    0xda, 0x1a, 0xaf, 0x3c, 0x55, 0x9c, 0xe2, 0x19, 0x12, 0x84, 0x00, 0x61,
-    0x79, 0x90, 0xf9, 0x50, 0xd9, 0xb0, 0xe0, 0xe6, 0x12, 0x88, 0x43, 0x34,
-    0x68, 0x3b, 0x8d, 0x5d, 0x70, 0x8a, 0xec, 0x32, 0x9e, 0x19, 0xdf, 0x18,
-    0x0a, 0x2e, 0xa1, 0x2f, 0xe9, 0x43, 0xc0, 0x85, 0x67, 0x02, 0x2e, 0x38,
-    0x68, 0xff, 0x71, 0xbf, 0x99, 0x9e, 0x37, 0x25, 0x9d, 0x7f, 0x99, 0xcd,
-    0xb5, 0xdd, 0xa6, 0x8b, 0xce, 0xa1, 0xd1, 0xa0, 0xc9, 0xbc, 0x31, 0x81,
-    0x65, 0x2b, 0x2f, 0x99, 0x4f, 0x5b, 0x8d, 0x99, 0x6a, 0x7d, 0x85, 0x50,
-    0xd3, 0xfd, 0xf5, 0x1e, 0x1f, 0x02, 0xfb, 0xfc, 0xce, 0x6d, 0xae, 0xed,
-    0x34, 0x52, 0xd7, 0xed, 0xb5, 0xdd, 0xa6, 0x8b, 0x0a, 0xff, 0xfd, 0x18,
-    0x21, 0x8e, 0xc7, 0x3e, 0xc1, 0x75, 0x9d, 0x7f, 0x03, 0x69, 0x3b, 0xac,
-    0xeb, 0x33, 0x88, 0xb1, 0x59, 0x9f, 0x1a, 0x8d, 0xfe, 0x67, 0x36, 0xd7,
-    0x76, 0x9a, 0x2c, 0xbb, 0xb6, 0xa1, 0xd7, 0xcc, 0xa8, 0xab, 0x2b, 0x07,
-    0x5e, 0x67, 0xfa, 0xce, 0xa6, 0x9e, 0x68, 0x0b, 0xa8, 0x51, 0x0d, 0xa6,
-    0x4b, 0x7c, 0x75, 0xca, 0x4e, 0x75, 0xcf, 0xb9, 0x1a, 0x9c, 0x11, 0xbf,
-    0xe7, 0xe4, 0x73, 0x9f, 0x42, 0x87, 0x5f, 0xe9, 0xf9, 0xd4, 0x07, 0xc8,
-    0x75, 0xfa, 0x33, 0x84, 0x68, 0xeb, 0x43, 0x9e, 0xdb, 0x06, 0x94, 0xe8,
-    0xbb, 0x18, 0x4a, 0x5f, 0x3c, 0xa4, 0x13, 0xaf, 0xe7, 0xdc, 0x79, 0xfa,
-    0x75, 0xe6, 0x18, 0x60, 0xab, 0xfe, 0x89, 0x73, 0xed, 0xc6, 0x72, 0x53,
-    0x25, 0xfd, 0xff, 0x01, 0xf9, 0xcf, 0x27, 0x2c, 0x1d, 0x74, 0x68, 0xea,
-    0x0a, 0x60, 0x7d, 0x21, 0x14, 0xad, 0x24, 0xf0, 0x3a, 0xbf, 0x91, 0xf5,
-    0xf6, 0x80, 0x75, 0xff, 0xfd, 0xd4, 0xf7, 0x73, 0x43, 0x8b, 0x06, 0xba,
-    0xf2, 0x3a, 0xff, 0x44, 0xbc, 0xfd, 0x70, 0x9d, 0x58, 0x88, 0xad, 0xac,
-    0xda, 0x47, 0x5a, 0x47, 0x5a, 0x47, 0x54, 0x1b, 0x05, 0x04, 0x10, 0x42,
-    0xff, 0xfd, 0xed, 0x23, 0x70, 0x77, 0x03, 0x81, 0xc5, 0x0e, 0xb7, 0x27,
-    0x5d, 0xa0, 0x1d, 0x58, 0x7f, 0x3a, 0x52, 0xf0, 0x8d, 0xc9, 0x07, 0x5f,
-    0xc3, 0x0b, 0x18, 0xc3, 0xae, 0x94, 0x1d, 0x41, 0x3d, 0x29, 0x85, 0x00,
-    0x53, 0x7f, 0xff, 0xfd, 0xd8, 0xf6, 0x93, 0x5a, 0x8f, 0x75, 0x23, 0x7f,
-    0x2d, 0xe5, 0x2f, 0x28, 0x75, 0xc9, 0xc9, 0xd7, 0x42, 0xce, 0xbf, 0xff,
-    0xa5, 0x02, 0x09, 0x4a, 0x3d, 0xdc, 0x5f, 0xf8, 0xf8, 0xeb, 0x9a, 0xcc,
-    0x2f, 0x05, 0x4e, 0x96, 0x18, 0x73, 0x64, 0x65, 0x2d, 0x4c, 0xdc, 0x2d,
-    0xdd, 0x48, 0x61, 0x4d, 0xa8, 0x40, 0x78, 0xc3, 0x83, 0xf7, 0x18, 0xb7,
-    0xf1, 0x5b, 0xff, 0xcc, 0xad, 0xe4, 0xce, 0x6d, 0xae, 0xed, 0x34, 0x51,
-    0x97, 0xee, 0x11, 0xb8, 0xf8, 0xeb, 0xf0, 0xbf, 0xd1, 0xfc, 0xeb, 0xff,
-    0xb9, 0x6a, 0x6f, 0xb9, 0x83, 0x2d, 0x1d, 0x66, 0x61, 0x12, 0x9d, 0x29,
-    0xf1, 0x45, 0x49, 0x93, 0xf3, 0xb8, 0x78, 0x2c, 0xe5, 0xe7, 0xb3, 0xf5,
-    0x0e, 0x0f, 0x43, 0xae, 0xff, 0xe6, 0x5e, 0x4c, 0xe6, 0xda, 0xee, 0xd3,
-    0x44, 0x73, 0x7f, 0xf9, 0x95, 0xbc, 0x99, 0xcd, 0xb5, 0xdd, 0xa6, 0x89,
-    0xca, 0xff, 0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x16, 0x65, 0xff, 0x4b, 0x4e,
-    0xb6, 0x7b, 0xef, 0x8e, 0xbf, 0xe5, 0x5c, 0x1c, 0x5c, 0x73, 0x0b, 0x3a,
-    0xff, 0xbe, 0xdc, 0x7b, 0xaf, 0xcc, 0x8e, 0xbf, 0xd9, 0xad, 0xef, 0x39,
-    0xd1, 0xd7, 0x72, 0xb3, 0xac, 0xca, 0xb0, 0x8c, 0x28, 0x3e, 0x91, 0xd7,
-    0x19, 0x9d, 0xfe, 0x67, 0x36, 0xd7, 0x76, 0x9a, 0x2d, 0xdb, 0xf8, 0x5d,
-    0x9d, 0xcf, 0xd3, 0xaf, 0x27, 0x3f, 0x1d, 0x7e, 0xdb, 0x5d, 0xda, 0x68,
-    0xa4, 0x2f, 0xfd, 0x9d, 0x4e, 0x1d, 0xcc, 0x16, 0x9d, 0x79, 0xe4, 0xce,
-    0x1f, 0x86, 0x8c, 0xec, 0xcb, 0x51, 0xdd, 0xb2, 0xe5, 0xc2, 0x36, 0xff,
-    0xe6, 0x5e, 0x4c, 0xe6, 0xda, 0xee, 0xd3, 0x44, 0xa5, 0x53, 0xab, 0xe9,
-    0x99, 0x45, 0x6a, 0xee, 0x7f, 0xf4, 0x3f, 0x45, 0x2f, 0xd1, 0x96, 0xf1,
-    0x1e, 0x5f, 0xe9, 0x20, 0xfb, 0x10, 0x27, 0x5e, 0xd0, 0x16, 0x75, 0x99,
-    0xe4, 0xf3, 0x10, 0xc2, 0xf0, 0xbc, 0x8e, 0xbf, 0xf3, 0xc9, 0x9c, 0xdb,
-    0x5d, 0xda, 0x68, 0x9d, 0xae, 0x9d, 0x5c, 0xeb, 0xff, 0xf2, 0x04, 0x0b,
-    0x8e, 0x27, 0x08, 0xc0, 0xe3, 0x4e, 0xbf, 0xe8, 0x94, 0x6e, 0x78, 0xdc,
-    0xe7, 0x59, 0x9c, 0x4c, 0x2d, 0x63, 0x5d, 0x4a, 0x71, 0xa1, 0x54, 0xbf,
-    0xfe, 0x67, 0xff, 0x1b, 0x8f, 0xd9, 0xe8, 0x14, 0xf8, 0xeb, 0xff, 0x9d,
-    0x7d, 0xc6, 0xbf, 0x63, 0xfc, 0x8e, 0xbc, 0x81, 0x73, 0xaf, 0xfe, 0x1c,
-    0xeb, 0xcf, 0x9a, 0x17, 0xe4, 0xeb, 0xb8, 0xd9, 0x0a, 0x28, 0x3a, 0x89,
-    0xa1, 0xaa, 0x92, 0xab, 0x75, 0xc6, 0x69, 0xa4, 0xfe, 0x38, 0x7a, 0x5f,
-    0xff, 0xc1, 0x7f, 0x33, 0x9a, 0x81, 0xe7, 0xed, 0x6a, 0x3e, 0x3a, 0xfd,
-    0xb6, 0xbb, 0xb4, 0xd1, 0x16, 0x5f, 0xf9, 0xe4, 0xce, 0x6d, 0xae, 0xed,
-    0x34, 0x4b, 0xb7, 0xff, 0xf6, 0x07, 0xb1, 0xfd, 0x9f, 0x0b, 0xfd, 0xad,
-    0x47, 0xc5, 0x59, 0x9c, 0x46, 0xda, 0xcc, 0xf8, 0xd2, 0xaf, 0xff, 0x32,
-    0xb7, 0x93, 0x39, 0xb6, 0xbb, 0xb4, 0xd1, 0x31, 0x5f, 0xb6, 0xd7, 0x76,
-    0x9a, 0x2a, 0x9b, 0x61, 0xd5, 0x87, 0x84, 0xa1, 0x9d, 0xff, 0xff, 0xed,
-    0xbf, 0x79, 0x96, 0x79, 0x9e, 0xbe, 0xb6, 0x8c, 0x7b, 0xa9, 0xb9, 0x1d,
-    0x4c, 0xa2, 0x71, 0xc8, 0xaf, 0xff, 0x32, 0xb7, 0x93, 0x39, 0xb6, 0xbb,
-    0xb4, 0xd1, 0x3a, 0x5f, 0xe4, 0x7d, 0xc4, 0x9f, 0x81, 0xd7, 0xe9, 0xa2,
-    0x68, 0xd1, 0xd7, 0xf3, 0x18, 0x9c, 0x30, 0x4e, 0xa4, 0x3d, 0x5d, 0x14,
-    0x5e, 0x4e, 0xc1, 0xcc, 0x9a, 0x1b, 0xff, 0x81, 0xaf, 0x47, 0x2c, 0x82,
-    0x64, 0x59, 0xd4, 0xb3, 0xf2, 0xe9, 0x5d, 0xff, 0x9e, 0x4c, 0xe6, 0xda,
-    0xee, 0xd3, 0x44, 0xef, 0x7e, 0xf0, 0x1d, 0x68, 0x55, 0xff, 0x86, 0x3d,
-    0x9a, 0xcc, 0xe6, 0x47, 0x50, 0x53, 0xe8, 0xc8, 0xc6, 0x96, 0x44, 0xe9,
-    0x5e, 0x26, 0xbf, 0xa1, 0x9f, 0x87, 0x02, 0x75, 0x32, 0x7f, 0x82, 0x9f,
-    0x7f, 0xf9, 0x95, 0xbc, 0x99, 0xcd, 0xb5, 0xdd, 0xa6, 0x8a, 0x16, 0xff,
-    0xff, 0xf7, 0x40, 0xb5, 0xbc, 0x99, 0x6f, 0x41, 0xe8, 0x1c, 0x9d, 0x40,
-    0x44, 0xc7, 0x5f, 0x81, 0xcf, 0x91, 0xa7, 0x5f, 0xb3, 0xec, 0x71, 0x3a,
-    0xf4, 0x7c, 0xcc, 0xe7, 0x9a, 0x25, 0x14, 0x88, 0xfd, 0x18, 0x64, 0x5f,
-    0xfe, 0x65, 0x6f, 0x26, 0x73, 0x6d, 0x77, 0x69, 0xa2, 0x92, 0xbf, 0xff,
-    0xd9, 0xa6, 0x7f, 0xe4, 0xdd, 0x75, 0xfb, 0xb1, 0xe0, 0x2c, 0xea, 0x85,
-    0xfd, 0xb9, 0xe3, 0x38, 0x91, 0xcb, 0x63, 0x35, 0xd9, 0x1a, 0xe5, 0x5d,
-    0xfc, 0x45, 0xe8, 0xd5, 0x00, 0x4d, 0xc6, 0xaf, 0x7f, 0x99, 0xcd, 0xb5,
-    0xdd, 0xa6, 0x88, 0x92, 0xff, 0xf3, 0x2b, 0x79, 0x33, 0x9b, 0x6b, 0xbb,
-    0x4d, 0x12, 0xf5, 0xf6, 0xc1, 0xed, 0x1d, 0x7e, 0xdf, 0xcb, 0x4d, 0x1d,
-    0x7a, 0x07, 0x93, 0xaf, 0xde, 0xfe, 0xb1, 0x83, 0xac, 0x9d, 0x3c, 0x31,
-    0x1b, 0xbf, 0xfd, 0xde, 0x10, 0x3f, 0x2b, 0xe0, 0x73, 0x7c, 0x9d, 0x74,
-    0x78, 0xeb, 0xff, 0xc0, 0x0a, 0x6f, 0xfc, 0xdc, 0x40, 0x71, 0x98, 0xea,
-    0x92, 0x36, 0x90, 0x9b, 0xe4, 0xfd, 0x0a, 0xdf, 0xfc, 0xf3, 0x6a, 0x38,
-    0x3f, 0x63, 0x99, 0x8e, 0xbf, 0x64, 0xf9, 0xa5, 0x9d, 0x7f, 0xf4, 0xdf,
-    0xbf, 0x8c, 0x70, 0x7e, 0x11, 0x31, 0xd4, 0x75, 0xfd, 0x34, 0x9f, 0xcf,
-    0xc0, 0xea, 0x84, 0x42, 0xe2, 0x63, 0x85, 0x5d, 0xb8, 0x3a, 0x82, 0xab,
-    0x65, 0x08, 0xa6, 0x8d, 0x17, 0x67, 0xa2, 0x8f, 0xc2, 0x15, 0x9c, 0x45,
-    0xb7, 0x07, 0x93, 0xaf, 0xf9, 0x1c, 0x41, 0xe9, 0xa1, 0x43, 0xaf, 0xff,
-    0x93, 0x7f, 0xbb, 0x09, 0xed, 0x01, 0xa0, 0x83, 0xaf, 0x92, 0x7f, 0x95,
-    0xce, 0xbe, 0x6b, 0xbb, 0x4d, 0x14, 0xbd, 0xf0, 0xfa, 0x36, 0x75, 0xff,
-    0x66, 0xd5, 0xf0, 0x39, 0xbe, 0x4e, 0xa4, 0x3d, 0xbe, 0x04, 0x14, 0xa2,
-    0x64, 0x33, 0x28, 0x6c, 0x9b, 0xb0, 0x88, 0xbf, 0x0f, 0xa7, 0xc6, 0x0e,
-    0xbf, 0xf4, 0x0c, 0x77, 0xf0, 0x04, 0x0d, 0x3a, 0xf0, 0x1f, 0x47, 0x5f,
-    0xa3, 0xe7, 0xe7, 0x47, 0x5e, 0x14, 0xf8, 0xeb, 0xd9, 0xed, 0x1d, 0x50,
-    0x6d, 0xb4, 0x37, 0x41, 0x46, 0xbc, 0xc7, 0xdf, 0x0d, 0xf9, 0x7a, 0xfc,
-    0xae, 0xe2, 0x1e, 0x23, 0xaf, 0xfb, 0xed, 0x6e, 0x39, 0x92, 0x2c, 0xeb,
-    0xde, 0x7e, 0x07, 0x5f, 0xf3, 0xcf, 0xfa, 0x70, 0x4d, 0x0a, 0xe7, 0x54,
-    0x22, 0x5d, 0xce, 0x80, 0x3b, 0x7f, 0xc9, 0xa9, 0x90, 0x7d, 0x1f, 0x1d,
-    0x52, 0x3e, 0x65, 0x97, 0x5c, 0xe2, 0x75, 0xff, 0x47, 0xdf, 0xbb, 0x0b,
-    0x71, 0x3a, 0xdb, 0xe4, 0xf3, 0x78, 0x0a, 0x54, 0x27, 0x87, 0x91, 0x94,
-    0xa3, 0x7d, 0xed, 0xc2, 0xce, 0xbf, 0xa0, 0x66, 0xf2, 0x28, 0x75, 0xff,
-    0x4b, 0x37, 0x36, 0x0c, 0x2c, 0xeb, 0xf7, 0xd0, 0xdc, 0x59, 0xd4, 0x87,
-    0xbd, 0xb3, 0x7b, 0xa5, 0x87, 0x5e, 0x8f, 0xb4, 0x75, 0x41, 0xe9, 0x04,
-    0x85, 0x81, 0x5b, 0xf7, 0x40, 0xa6, 0x09, 0xd7, 0xfd, 0x1d, 0xd3, 0xfa,
-    0x37, 0xc4, 0x75, 0xff, 0x96, 0xe1, 0xff, 0x34, 0xa0, 0x79, 0x3a, 0x82,
-    0x7f, 0x68, 0x75, 0x7d, 0xbf, 0xbf, 0xf0, 0x3a, 0xf2, 0x31, 0xe3, 0xab,
-    0xa7, 0x87, 0xa2, 0x7a, 0x0a, 0x65, 0x1d, 0x85, 0x17, 0x99, 0x2f, 0xfb,
-    0xe4, 0xee, 0x6d, 0xe6, 0xd1, 0xd7, 0xff, 0xe8, 0x90, 0xc4, 0xff, 0xe6,
-    0xd7, 0x73, 0x8b, 0x7f, 0x1d, 0x7f, 0x7e, 0x5e, 0x79, 0xfc, 0x75, 0x9a,
-    0x75, 0xdc, 0xeb, 0x0d, 0xf3, 0x97, 0x57, 0x28, 0xff, 0x59, 0xcb, 0xc2,
-    0x6a, 0xff, 0x63, 0x12, 0x4d, 0x01, 0x67, 0x5d, 0xc3, 0x47, 0x5f, 0xb2,
-    0x7c, 0xee, 0x8e, 0xa8, 0x37, 0xe2, 0x31, 0x7b, 0x37, 0xa3, 0xa9, 0xa6,
-    0xeb, 0x80, 0xfd, 0xff, 0x7d, 0x1f, 0x7f, 0xe1, 0x03, 0xc4, 0x75, 0x42,
-    0x61, 0xf9, 0x0a, 0xc4, 0x23, 0xbf, 0xff, 0xfb, 0xb1, 0xbe, 0x5a, 0x9c,
-    0xfe, 0x51, 0xff, 0x6b, 0xae, 0xd8, 0x10, 0x9d, 0x7d, 0xe1, 0x45, 0x9d,
-    0x7f, 0x86, 0x1c, 0x7d, 0x82, 0x75, 0xfe, 0xeb, 0xcc, 0x9b, 0x89, 0xce,
-    0xbb, 0x16, 0x75, 0x05, 0x30, 0xdc, 0x77, 0x59, 0x03, 0x97, 0x70, 0x33,
-    0xbf, 0x71, 0x22, 0xe3, 0x47, 0x5f, 0x9f, 0x86, 0x6f, 0x47, 0x50, 0x4f,
-    0x45, 0x65, 0x37, 0xee, 0xb8, 0xa2, 0xce, 0xbe, 0x52, 0x6d, 0x41, 0xd7,
-    0xf9, 0xfe, 0xd4, 0x76, 0x34, 0x75, 0x42, 0x27, 0x30, 0x89, 0x09, 0x44,
-    0x8e, 0xef, 0x9a, 0x75, 0xb4, 0x75, 0xc8, 0xa6, 0x8d, 0x38, 0x05, 0xef,
-    0x7c, 0xed, 0x3a, 0xff, 0xfc, 0x81, 0xce, 0x0f, 0xb9, 0xbf, 0xc9, 0xfc,
-    0xeb, 0x3a, 0xa0, 0xfd, 0x36, 0x39, 0x66, 0x61, 0x9b, 0x83, 0x27, 0x50,
-    0x8b, 0xe4, 0x6b, 0x3c, 0xa2, 0xa4, 0x3f, 0xe6, 0x94, 0x05, 0xb3, 0x45,
-    0x8d, 0xf6, 0x1b, 0xaf, 0x1a, 0xbf, 0xd1, 0x9a, 0x8c, 0x68, 0x9a, 0x8d,
-    0x03, 0xd1, 0x9c, 0x71, 0xb0, 0x7f, 0x85, 0x0d, 0xfe, 0x67, 0x36, 0xd7,
-    0x76, 0x9a, 0x29, 0xcb, 0xff, 0x26, 0xdf, 0x5d, 0xcc, 0x16, 0x9d, 0x7e,
-    0x5e, 0xf7, 0x9a, 0x3a, 0xff, 0xfd, 0xd0, 0x7b, 0x71, 0xed, 0x63, 0x75,
-    0x1b, 0x69, 0xd7, 0xf9, 0x16, 0x18, 0xd0, 0x04, 0xeb, 0xfb, 0x3d, 0xcc,
-    0xa1, 0x83, 0xaf, 0xfe, 0x51, 0x39, 0xd0, 0xe0, 0x7a, 0xec, 0x1d, 0x7f,
-    0xec, 0xec, 0x6f, 0x19, 0x61, 0x86, 0x0a, 0xb9, 0x18, 0x3a, 0xe9, 0xd9,
-    0x0a, 0x76, 0x58, 0x76, 0xd2, 0x7e, 0xaa, 0x89, 0x8f, 0x8b, 0xb8, 0xd1,
-    0x78, 0x90, 0x6f, 0xdb, 0x6b, 0xbb, 0x4d, 0x15, 0xe5, 0xff, 0xfd, 0x81,
-    0xec, 0x7f, 0x67, 0xc2, 0xff, 0x6b, 0x51, 0xf1, 0x56, 0x67, 0x11, 0x23,
-    0xc6, 0x67, 0x7f, 0xf3, 0x2f, 0x26, 0x73, 0x6d, 0x77, 0x69, 0xa2, 0x47,
-    0xbc, 0xdc, 0x59, 0xd7, 0x93, 0xe8, 0x3a, 0xf3, 0x71, 0x65, 0x32, 0x5d,
-    0xdf, 0xb6, 0xd7, 0x76, 0x9a, 0x24, 0x8b, 0xff, 0xfa, 0x13, 0x69, 0xc5,
-    0x03, 0x3c, 0x79, 0x3a, 0xf3, 0x9d, 0x74, 0x99, 0x84, 0x5c, 0xe1, 0x5f,
-    0x4c, 0xef, 0xd9, 0xd6, 0x71, 0x67, 0x59, 0x98, 0x4d, 0x45, 0xe1, 0xdf,
-    0xe3, 0xbb, 0xff, 0x99, 0x79, 0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x12, 0x55,
-    0xfb, 0x6d, 0x77, 0x69, 0xa2, 0xf1, 0xbf, 0xe9, 0x33, 0x9b, 0x6b, 0xbb,
-    0x4d, 0x12, 0x6d, 0x99, 0xc3, 0xf8, 0x73, 0x3b, 0x98, 0xe9, 0xd7, 0xe4,
-    0xfb, 0x58, 0x27, 0x5f, 0xff, 0x01, 0xf9, 0xcc, 0x51, 0x47, 0x96, 0x73,
-    0xe3, 0xaa, 0x47, 0xef, 0xa2, 0x6b, 0xb7, 0xe3, 0xaf, 0x4c, 0x33, 0x9d,
-    0x61, 0x3a, 0xef, 0xff, 0xce, 0xaf, 0x8d, 0x4f, 0xf0, 0xfb, 0xb8, 0xd9,
-    0x84, 0xcc, 0x32, 0x11, 0xce, 0x45, 0xa1, 0x6f, 0xe8, 0xd5, 0x0d, 0xcf,
-    0x64, 0xe7, 0xf2, 0xac, 0x3c, 0x43, 0x19, 0x72, 0x47, 0xe3, 0x34, 0x62,
-    0xab, 0x2c, 0xec, 0x74, 0x5e, 0x3b, 0x04, 0x32, 0x7f, 0xc6, 0xaf, 0x51,
-    0x2f, 0x96, 0xa2, 0x79, 0x48, 0xd2, 0x9d, 0x77, 0x0c, 0xea, 0x56, 0x62,
-    0x2e, 0x21, 0x49, 0xc6, 0xd6, 0xde, 0x92, 0xcf, 0x35, 0x8b, 0xfa, 0x52,
-    0x5f, 0x55, 0xe5, 0x11, 0xcd, 0x6b, 0xfc, 0x77, 0x68, 0x25, 0x17, 0x9b,
-    0x1d, 0x1f, 0x69, 0x4d, 0x4f, 0x6c, 0x7a, 0xfe, 0x9f, 0x35, 0x54, 0xc7,
-    0xc6, 0x35, 0x91, 0x3e, 0xab, 0x60, 0x4f, 0x5e, 0x92, 0x00, 0x2d, 0x78,
-    0x1f, 0x0a, 0x56, 0x3b, 0x13, 0x8b, 0x5c, 0x72, 0xe1, 0x7f, 0xd2, 0x0a,
-    0x38, 0xab, 0xa9, 0x7a,
+    0x5f, 0x04, 0x62, 0x47, 0x52, 0x1b, 0xc7, 0x1c, 0xa0, 0xa3, 0x87, 0x91,
+    0xd4, 0x1d, 0x58, 0xef, 0x5a, 0xee, 0xc6, 0x9d, 0x7f, 0x6d, 0x38, 0x60,
+    0xe8, 0xeb, 0xfb, 0x9f, 0x67, 0x40, 0xae, 0x75, 0xfb, 0xa3, 0x19, 0xb3,
+    0x2f, 0xfb, 0x72, 0xcd, 0xce, 0x07, 0x09, 0xa2, 0x0d, 0x64, 0xd2, 0xd4,
+    0x22, 0xb5, 0x15, 0xaf, 0xce, 0xd4, 0x5c, 0x1d, 0x7f, 0x4b, 0xa2, 0xfc,
+    0xf8, 0xeb, 0x63, 0x4f, 0x48, 0x49, 0x6f, 0xd1, 0xef, 0xcb, 0x60, 0xeb,
+    0xfd, 0x24, 0x5c, 0x77, 0xf8, 0x4e, 0xbf, 0xfd, 0x18, 0x3c, 0xfb, 0x36,
+    0x93, 0xba, 0xce, 0xbf, 0x3b, 0x1e, 0xce, 0xe8, 0xff, 0x3c, 0x69, 0x4a,
+    0xda, 0xa6, 0xd8, 0x15, 0x94, 0x36, 0xb1, 0xcf, 0x64, 0xc3, 0x0a, 0x6b,
+    0xda, 0xc9, 0x1d, 0x7e, 0x4e, 0x64, 0x82, 0x75, 0xe4, 0xee, 0x1d, 0x74,
+    0x2f, 0x0f, 0x01, 0xa4, 0xd7, 0xc1, 0xd7, 0x60, 0xeb, 0xf0, 0xed, 0x87,
+    0x9c, 0xea, 0xc3, 0xc9, 0x72, 0x1b, 0x80, 0x27, 0x54, 0x26, 0x0a, 0x8b,
+    0x7b, 0x75, 0xd1, 0x05, 0xee, 0xe0, 0x9d, 0x7f, 0xfc, 0xea, 0x7a, 0x37,
+    0xf6, 0xe3, 0xc2, 0xff, 0x1d, 0x7f, 0xff, 0x0b, 0xa9, 0xfb, 0xf8, 0xbf,
+    0xb4, 0x9c, 0xf5, 0x18, 0x3a, 0xb1, 0x19, 0x22, 0x34, 0x05, 0x0b, 0xb5,
+    0xc0, 0xeb, 0xe4, 0x17, 0x09, 0xd7, 0xfe, 0x5e, 0x7b, 0x5f, 0xf4, 0xf2,
+    0xc3, 0xaf, 0xda, 0x8d, 0xfa, 0x0e, 0x64, 0xdf, 0xd0, 0x51, 0x2b, 0xa5,
+    0xeb, 0xf7, 0xf9, 0x9d, 0xf6, 0x75, 0xf7, 0x71, 0x38, 0x1d, 0x7f, 0x69,
+    0x37, 0x80, 0xd9, 0xd7, 0xff, 0xfa, 0x26, 0xfc, 0x8d, 0x06, 0xf4, 0x0f,
+    0xcb, 0x4f, 0x75, 0x0e, 0xac, 0x4e, 0xb1, 0x21, 0x5a, 0xb2, 0x3e, 0x94,
+    0xf8, 0x8b, 0x88, 0xb2, 0xe5, 0xaa, 0x0d, 0x17, 0xe5, 0xf6, 0xb7, 0x98,
+    0x75, 0xff, 0xd2, 0xf0, 0x25, 0x25, 0xfb, 0xd0, 0xb3, 0xaf, 0xf7, 0xb5,
+    0x13, 0xe6, 0x82, 0x75, 0xdd, 0xc3, 0xaf, 0xff, 0xbb, 0x01, 0xc6, 0xfe,
+    0xc1, 0xc0, 0xf6, 0x0e, 0xbf, 0xf9, 0x30, 0x73, 0x35, 0xfa, 0x5a, 0x59,
+    0xd7, 0xfe, 0x78, 0xe6, 0x5f, 0xb5, 0xc8, 0x60, 0xea, 0x0a, 0x6f, 0xfc,
+    0x90, 0x22, 0x2a, 0xb9, 0x9c, 0xc2, 0xba, 0x4e, 0xf2, 0x1d, 0xe5, 0x23,
+    0x67, 0x5f, 0xc1, 0x8f, 0xb7, 0x9c, 0x9d, 0x4c, 0x9e, 0x52, 0xc7, 0x2f,
+    0xf4, 0x2f, 0x13, 0x73, 0x48, 0xeb, 0x92, 0x63, 0xaf, 0xff, 0x7a, 0x3a,
+    0x2f, 0x3c, 0x6f, 0x6f, 0x23, 0xaf, 0x79, 0x27, 0x3a, 0xfd, 0xf3, 0xf3,
+    0x13, 0x1d, 0x78, 0x61, 0xa7, 0x5f, 0xfc, 0x14, 0x9b, 0xb1, 0xbe, 0x65,
+    0x1b, 0x3a, 0xff, 0xe1, 0x7e, 0x75, 0xac, 0xd8, 0x7b, 0x87, 0x5f, 0xfe,
+    0x86, 0xfe, 0xde, 0x20, 0x15, 0x39, 0xc5, 0x87, 0x52, 0x22, 0x4c, 0x50,
+    0xeb, 0xf2, 0x76, 0xc8, 0x2c, 0xb4, 0x87, 0x1c, 0x12, 0x9d, 0x0d, 0x71,
+    0x43, 0x62, 0xd0, 0x75, 0xee, 0xa7, 0x8e, 0xb7, 0x0c, 0x35, 0x5f, 0xc3,
+    0xea, 0x17, 0x60, 0x82, 0xbd, 0x91, 0xd3, 0x24, 0x2c, 0xfa, 0x46, 0xf1,
+    0xf4, 0x7d, 0x09, 0x6b, 0xfe, 0xc1, 0x90, 0xe2, 0xe1, 0xa7, 0x5f, 0xba,
+    0x9c, 0x30, 0x27, 0x5f, 0xf8, 0x30, 0x38, 0x20, 0x96, 0x68, 0xeb, 0xf3,
+    0xad, 0x38, 0xb0, 0xeb, 0xde, 0x8e, 0x4e, 0xac, 0x3c, 0x47, 0x28, 0xbc,
+    0x2a, 0xcf, 0x11, 0xd7, 0xff, 0xfe, 0x8e, 0xa2, 0xd9, 0x9a, 0x4f, 0xbf,
+    0xfd, 0x4e, 0x74, 0xd4, 0x9c, 0xea, 0x0a, 0x72, 0x0a, 0x1a, 0xa1, 0x44,
+    0xcf, 0xe2, 0x41, 0xc4, 0x47, 0x7f, 0x3e, 0xe3, 0xbf, 0xc2, 0x75, 0xf4,
+    0x24, 0xf0, 0x75, 0xf3, 0x0f, 0x9a, 0x3a, 0xff, 0xa4, 0xb7, 0x97, 0xb5,
+    0x0a, 0x1d, 0x50, 0x7b, 0x4e, 0x43, 0x7b, 0x48, 0x27, 0x5f, 0x85, 0xbf,
+    0xb5, 0xc9, 0xd5, 0x87, 0x88, 0xe3, 0x54, 0xe9, 0x96, 0x7c, 0x5c, 0x2f,
+    0x40, 0x64, 0xba, 0x79, 0x1d, 0x79, 0x3a, 0x87, 0x57, 0x26, 0xc7, 0xc2,
+    0xf7, 0xdf, 0xc0, 0xfa, 0x3a, 0xff, 0x48, 0x03, 0x3e, 0x93, 0x93, 0xaf,
+    0xbe, 0xfb, 0x39, 0x3a, 0xfe, 0xe2, 0xf6, 0x38, 0xb4, 0xeb, 0xfe, 0x03,
+    0xc8, 0x39, 0x9f, 0x68, 0xeb, 0xfd, 0xf2, 0x73, 0xcc, 0xb3, 0xc7, 0x57,
+    0x4f, 0xb7, 0x47, 0x17, 0xee, 0x74, 0xb4, 0x57, 0x3a, 0xff, 0xfd, 0x9a,
+    0xfd, 0xd7, 0x4f, 0x7c, 0x01, 0x17, 0x91, 0xd5, 0x08, 0x80, 0x12, 0xbb,
+    0xf9, 0xe7, 0xf9, 0xc4, 0x27, 0x54, 0xc9, 0xf1, 0xec, 0xd3, 0xa4, 0x9e,
+    0x84, 0xdf, 0x08, 0x51, 0x71, 0x90, 0xdf, 0xf7, 0x7f, 0xc3, 0x78, 0xf3,
+    0x70, 0x75, 0x42, 0xaa, 0xac, 0x94, 0x0c, 0xed, 0x17, 0x4c, 0x03, 0xac,
+    0xb3, 0xab, 0x93, 0x4e, 0xa9, 0x17, 0xbf, 0xfa, 0x37, 0x9c, 0x1e, 0x5f,
+    0x66, 0x04, 0xeb, 0xf9, 0xf9, 0x90, 0xc0, 0x4e, 0xbf, 0xe8, 0xe6, 0x48,
+    0x2b, 0x7f, 0x1d, 0x4e, 0x7c, 0x62, 0x59, 0x7e, 0x79, 0x64, 0xf0, 0x75,
+    0xff, 0xd1, 0xad, 0x62, 0xfc, 0x30, 0xbd, 0x1d, 0x7f, 0xf2, 0x46, 0x85,
+    0xe5, 0xfb, 0x59, 0xb3, 0xaf, 0xff, 0xf2, 0x6a, 0x7c, 0x63, 0x04, 0x1c,
+    0x50, 0xce, 0x0b, 0xec, 0xeb, 0xfd, 0xcc, 0xb5, 0x34, 0xa2, 0x73, 0xa8,
+    0x29, 0xa1, 0xb4, 0x98, 0x50, 0xbc, 0x86, 0x06, 0x2b, 0xff, 0xff, 0x75,
+    0x39, 0xf6, 0x73, 0xed, 0xee, 0x3d, 0xf7, 0xf1, 0x97, 0x70, 0xeb, 0xe0,
+    0x85, 0xc4, 0xeb, 0xff, 0x4a, 0x07, 0xdb, 0x4e, 0x18, 0x13, 0xaf, 0xfc,
+    0xfd, 0x6a, 0x3f, 0xed, 0x3f, 0x4e, 0xbf, 0xff, 0x68, 0x7f, 0x75, 0xd3,
+    0xdf, 0x00, 0x45, 0xe4, 0x75, 0xfe, 0xea, 0x29, 0xc6, 0x0d, 0xa8, 0x75,
+    0xff, 0x43, 0x0b, 0xec, 0x20, 0xce, 0x75, 0xff, 0xf0, 0xe6, 0xb1, 0x70,
+    0xdc, 0xf2, 0x6f, 0x0e, 0xb6, 0x35, 0x17, 0x7e, 0x38, 0xe0, 0x71, 0x7f,
+    0x4f, 0x9b, 0x46, 0xc1, 0xd7, 0xc2, 0x18, 0x59, 0xd7, 0xee, 0x18, 0x20,
+    0x73, 0xaf, 0xe7, 0xfb, 0x02, 0xf2, 0x3a, 0xa0, 0xfc, 0xf0, 0x81, 0x09,
+    0xe9, 0x11, 0x97, 0xd8, 0x4f, 0xd4, 0x2e, 0xdf, 0xce, 0x4c, 0x18, 0x53,
+    0xe4, 0x6c, 0x6d, 0x4a, 0x47, 0x09, 0x88, 0x3a, 0x7d, 0xf1, 0xf0, 0xc6,
+    0x21, 0xe8, 0xc0, 0xaf, 0xfe, 0xc1, 0xfb, 0x33, 0x7a, 0xf4, 0x61, 0xd7,
+    0xfd, 0xcf, 0xb3, 0x69, 0x3b, 0xac, 0xeb, 0x67, 0xc7, 0xf4, 0x28, 0x37,
+    0xfe, 0xc5, 0x77, 0x1f, 0xbf, 0x2a, 0x64, 0x87, 0x5f, 0xdc, 0x3a, 0x91,
+    0xbd, 0x1d, 0x7f, 0xfe, 0x81, 0x96, 0x75, 0x16, 0x1c, 0x9a, 0x33, 0x67,
+    0x5f, 0xa1, 0xbd, 0x49, 0x8e, 0xbc, 0xd7, 0xd9, 0xd7, 0xed, 0x36, 0x36,
+    0xa1, 0xd5, 0xd3, 0xc3, 0xf8, 0x6e, 0xff, 0x64, 0xb1, 0x03, 0xd4, 0x3a,
+    0xfb, 0xd2, 0x5f, 0x4e, 0xbe, 0x45, 0x11, 0x83, 0xab, 0x0f, 0x10, 0x48,
+    0xae, 0xfd, 0x87, 0x5f, 0x68, 0x61, 0x67, 0x54, 0x1b, 0x7e, 0x45, 0xef,
+    0xb3, 0xb2, 0x59, 0xd5, 0x0a, 0xa1, 0xe4, 0x4f, 0x88, 0xca, 0x17, 0x75,
+    0x49, 0xda, 0x84, 0x8f, 0x4e, 0x80, 0x57, 0xe3, 0x21, 0xbc, 0x15, 0xb4,
+    0xeb, 0x74, 0xeb, 0xb5, 0x23, 0xab, 0xe3, 0x4c, 0x01, 0x0b, 0xfa, 0x79,
+    0xa4, 0xaa, 0xdc, 0xe7, 0x5e, 0x7c, 0xd9, 0xd7, 0x87, 0x3c, 0x75, 0x74,
+    0xda, 0x08, 0xd5, 0xde, 0x13, 0xaf, 0x47, 0x3a, 0x3a, 0xf9, 0x06, 0x58,
+    0x75, 0xe9, 0xdc, 0x4e, 0xa0, 0x9e, 0xb2, 0xc7, 0x3c, 0x3f, 0x7e, 0xcf,
+    0x75, 0x3c, 0x75, 0xf9, 0xf9, 0xce, 0x7c, 0x75, 0x94, 0xe9, 0xe7, 0x78,
+    0x9a, 0xe4, 0xd9, 0xd7, 0xf4, 0xff, 0xa7, 0x77, 0xe9, 0xd4, 0xac, 0xa7,
+    0xbf, 0x0d, 0x32, 0x20, 0xc6, 0xb4, 0x7d, 0xe9, 0x4b, 0x8a, 0xdf, 0xf6,
+    0x04, 0x29, 0xce, 0x73, 0xe3, 0xaf, 0x9a, 0x31, 0x23, 0xab, 0xa7, 0xb2,
+    0xe7, 0x37, 0xfa, 0x33, 0xd1, 0xd7, 0x09, 0xd5, 0x39, 0xe8, 0x84, 0x86,
+    0xff, 0xe0, 0xc0, 0x77, 0x1e, 0x46, 0xa0, 0x4e, 0xbe, 0x9a, 0x38, 0xa4,
+    0x75, 0xfd, 0xe6, 0x84, 0x2b, 0xd9, 0xd7, 0xfd, 0x36, 0xb8, 0x38, 0xce,
+    0x00, 0x9d, 0x7d, 0x9e, 0xc5, 0x9d, 0x70, 0xa8, 0x75, 0xb4, 0xe6, 0xd8,
+    0x04, 0x17, 0xf7, 0x41, 0x3c, 0xdd, 0x43, 0xaf, 0x84, 0x73, 0xc7, 0x54,
+    0x27, 0x3c, 0x12, 0x3c, 0x42, 0x50, 0x95, 0x0b, 0xa6, 0x72, 0xe9, 0x37,
+    0x8b, 0xef, 0xef, 0xd3, 0x47, 0x87, 0x81, 0xd7, 0xff, 0x86, 0x38, 0x6e,
+    0x37, 0x89, 0xd8, 0x09, 0xd7, 0x85, 0xd6, 0x75, 0x49, 0x12, 0x78, 0x62,
+    0x89, 0x16, 0x65, 0x59, 0x77, 0x16, 0xca, 0xd9, 0xe2, 0xb4, 0x1c, 0x56,
+    0xa3, 0x71, 0x29, 0x6a, 0x78, 0x75, 0xca, 0x1b, 0x21, 0x9c, 0x41, 0xc9,
+    0xd9, 0xa5, 0x21, 0x9a, 0xd9, 0x57, 0xdc, 0xc7, 0xc6, 0x91, 0x88, 0xcd,
+    0x2a, 0xdf, 0x71, 0xb5, 0x2e, 0x30, 0x5e, 0xcf, 0xae, 0x3c, 0xa0, 0xaf,
+    0xa3, 0x87, 0x54, 0xb7, 0x0c, 0xac, 0xcd, 0x4f, 0x0e, 0x7a, 0x5d, 0x90,
+    0x21, 0x1a, 0xc2, 0x17, 0x1c, 0xa0, 0x1f, 0xf2, 0xab, 0xb8, 0xa3, 0x04,
+    0xa6, 0x5d, 0xd9, 0xdf, 0x6d, 0xc8, 0x35, 0xff, 0xe6, 0x56, 0xf2, 0x67,
+    0x36, 0xd7, 0x76, 0x9a, 0x26, 0xcb, 0xfc, 0xce, 0x6d, 0xae, 0xed, 0x34,
+    0x55, 0xb7, 0xfa, 0x52, 0x07, 0x86, 0x24, 0x75, 0xf6, 0x75, 0xfc, 0x75,
+    0x95, 0x18, 0x7a, 0x42, 0x65, 0x7f, 0xee, 0xc7, 0x62, 0x7d, 0xc6, 0x04,
+    0xeb, 0xf4, 0x6d, 0x7d, 0x09, 0xd7, 0x83, 0x82, 0x75, 0xe7, 0x76, 0x9a,
+    0x2b, 0x4b, 0xf2, 0x9c, 0xe8, 0x1c, 0x9d, 0x4d, 0x3d, 0x24, 0x27, 0xbf,
+    0xfc, 0x9e, 0x94, 0x37, 0xa9, 0xed, 0x3f, 0x27, 0x56, 0xcf, 0xab, 0x81,
+    0x0d, 0xff, 0xee, 0xa2, 0xe1, 0xb8, 0xbc, 0x1f, 0x71, 0x9d, 0x7f, 0xfc,
+    0xd8, 0xde, 0x7c, 0xeb, 0x79, 0x42, 0x34, 0xeb, 0xff, 0xe9, 0x6b, 0x06,
+    0x16, 0xf9, 0xef, 0x42, 0xce, 0xbb, 0xde, 0x84, 0x4c, 0xba, 0x6d, 0xff,
+    0xff, 0xe8, 0xe0, 0x9e, 0xd6, 0x28, 0xde, 0xa7, 0xb2, 0x61, 0x85, 0xcf,
+    0x8c, 0x1d, 0x7f, 0xa3, 0xcf, 0xdf, 0xc1, 0x83, 0xaf, 0xa5, 0xe4, 0x9c,
+    0xeb, 0xf7, 0xff, 0x0c, 0x7c, 0x75, 0x72, 0x79, 0x7c, 0x08, 0xaf, 0xf3,
+    0xcb, 0xc9, 0x3f, 0x50, 0xea, 0x83, 0xd7, 0x42, 0x5b, 0xf6, 0x75, 0x31,
+    0x67, 0x5f, 0xfc, 0x2e, 0x8d, 0xeb, 0x82, 0x7d, 0xa1, 0xd5, 0x39, 0xf3,
+    0xf4, 0x96, 0xff, 0x4a, 0x37, 0x3c, 0x6e, 0x73, 0xaf, 0x66, 0xfe, 0x3a,
+    0xfd, 0x36, 0x05, 0x6a, 0xe7, 0x5f, 0xc3, 0x0c, 0x73, 0x2d, 0x1d, 0x48,
+    0x7e, 0xb3, 0x0e, 0x71, 0x15, 0xd4, 0x23, 0x6f, 0x21, 0x53, 0x7f, 0xff,
+    0xff, 0x62, 0x37, 0x3d, 0x03, 0xed, 0x7e, 0x84, 0x0e, 0x2f, 0xf6, 0xe1,
+    0x24, 0xfa, 0x3a, 0xfe, 0xcf, 0x38, 0xfc, 0x03, 0xaf, 0xee, 0xfe, 0x49,
+    0xdc, 0x4e, 0xa9, 0x1e, 0xd6, 0x16, 0x59, 0x95, 0x52, 0xf4, 0xa4, 0x15,
+    0x4e, 0x7a, 0x12, 0x7c, 0x86, 0xb3, 0x49, 0x12, 0x1c, 0x7b, 0x2d, 0x5b,
+    0xd7, 0x61, 0xaa, 0xf0, 0x87, 0x18, 0x7f, 0x68, 0x9b, 0xd0, 0xe1, 0xbf,
+    0xcc, 0xe6, 0xda, 0xee, 0xd3, 0x45, 0x81, 0x7e, 0xdb, 0x5d, 0xda, 0x68,
+    0x9d, 0x6f, 0xff, 0xf7, 0x62, 0x70, 0xe2, 0xd9, 0xd6, 0xb3, 0xa9, 0xa0,
+    0x4e, 0x75, 0xf9, 0x95, 0xbc, 0x99, 0xc4, 0x4b, 0x4c, 0x67, 0x7f, 0xa5,
+    0xa6, 0x54, 0x52, 0x16, 0x75, 0xfb, 0x6d, 0x77, 0x69, 0xa2, 0xd9, 0xbf,
+    0xff, 0xcf, 0x26, 0x75, 0x09, 0x81, 0x4c, 0xd6, 0x78, 0x60, 0xeb, 0xff,
+    0x7d, 0x1a, 0x67, 0xa8, 0xd7, 0xd9, 0xd7, 0xfd, 0x12, 0x8d, 0xcf, 0x1b,
+    0x9c, 0xeb, 0x33, 0x89, 0x83, 0xac, 0xcd, 0xd7, 0x04, 0xfe, 0xff, 0xfc,
+    0xff, 0x7c, 0x0d, 0x33, 0x9b, 0x7d, 0x75, 0xe4, 0x75, 0xf3, 0x5d, 0xda,
+    0x68, 0xb9, 0xac, 0xb3, 0xab, 0x66, 0xf5, 0x82, 0xdb, 0xa6, 0x59, 0xd4,
+    0x75, 0x99, 0xc3, 0xc3, 0x60, 0x8b, 0x8c, 0x5e, 0xfd, 0xb6, 0xbb, 0xb4,
+    0xd1, 0x77, 0xdf, 0xe9, 0x33, 0xad, 0xed, 0x18, 0x3a, 0xcc, 0xe1, 0xf4,
+    0x39, 0x9d, 0xf3, 0x2a, 0x07, 0xe3, 0xaa, 0x1f, 0x21, 0x67, 0x2d, 0xdb,
+    0x3b, 0x4d, 0x79, 0x57, 0x49, 0xf2, 0x5d, 0xc3, 0x9d, 0x70, 0xd5, 0x74,
+    0x2f, 0xa3, 0x3d, 0x14, 0x2d, 0x43, 0x5f, 0xd0, 0xa1, 0xfe, 0x4f, 0x7f,
+    0xe6, 0x1c, 0x67, 0xd2, 0x0f, 0x32, 0x3a, 0xff, 0xec, 0x9f, 0x18, 0xee,
+    0x6b, 0x10, 0x4e, 0xb9, 0x19, 0xea, 0x20, 0x44, 0xfe, 0xfd, 0xad, 0x2d,
+    0xe4, 0x75, 0xff, 0xff, 0xff, 0xba, 0x9d, 0x48, 0x1f, 0x0b, 0xa9, 0x9e,
+    0x07, 0x93, 0xda, 0xea, 0x6e, 0x27, 0x7d, 0xb4, 0xeb, 0xb5, 0x07, 0x5f,
+    0xfd, 0xcb, 0x40, 0xfc, 0xfb, 0x30, 0x54, 0x3a, 0xf0, 0xbb, 0x30, 0x98,
+    0xc3, 0x49, 0xf5, 0x09, 0x7f, 0x0a, 0xde, 0x03, 0xac, 0xeb, 0xf6, 0x71,
+    0x7a, 0x14, 0x3a, 0xdc, 0x47, 0x54, 0xe6, 0xf7, 0x0a, 0xab, 0x67, 0xf2,
+    0x2b, 0x17, 0xfe, 0xd3, 0xa9, 0xd4, 0x81, 0x04, 0x1d, 0x7f, 0xee, 0xbf,
+    0x9f, 0xbc, 0xcb, 0x3c, 0x75, 0x61, 0xfd, 0x21, 0xe5, 0xcf, 0xf1, 0xd7,
+    0xff, 0xff, 0x85, 0xd8, 0x1c, 0xf7, 0xb2, 0x78, 0x17, 0x53, 0x4b, 0x8c,
+    0x10, 0x9d, 0x58, 0x88, 0xad, 0x8b, 0x5f, 0xee, 0xe0, 0x53, 0x86, 0xf0,
+    0xeb, 0xce, 0xed, 0x34, 0x4a, 0xf7, 0xf9, 0x47, 0x1f, 0xbd, 0x9d, 0x3a,
+    0x9a, 0x7b, 0x48, 0x4f, 0x7f, 0xfb, 0xdd, 0xc9, 0x37, 0xa8, 0x18, 0x1f,
+    0x1d, 0x52, 0x47, 0xb6, 0xe1, 0x1a, 0x24, 0x37, 0x4a, 0x73, 0xaf, 0xfc,
+    0x2e, 0xc0, 0x7b, 0x13, 0xe3, 0x07, 0x5f, 0xff, 0xb1, 0x3e, 0xc5, 0xa7,
+    0xb5, 0x0b, 0x7e, 0x7c, 0x75, 0xff, 0x42, 0xfd, 0x93, 0x49, 0x3c, 0x75,
+    0x49, 0x11, 0x9e, 0x54, 0xbe, 0x03, 0xee, 0x47, 0x5f, 0xf4, 0x34, 0x62,
+    0x7f, 0x9f, 0xc7, 0x5f, 0xff, 0xe4, 0xf3, 0xad, 0xc7, 0xee, 0xb0, 0xe3,
+    0x3b, 0x52, 0x73, 0xa8, 0x28, 0xba, 0x42, 0x17, 0x38, 0xbf, 0xe0, 0x7c,
+    0xb7, 0x96, 0xb6, 0x13, 0xaf, 0xff, 0xf6, 0x20, 0xfb, 0x07, 0xf0, 0xb8,
+    0x60, 0x67, 0x8d, 0x9d, 0x6c, 0xf2, 0x25, 0xf8, 0x1d, 0x5f, 0xf7, 0x3f,
+    0x66, 0xf3, 0x3d, 0xa3, 0xa8, 0x2a, 0xb4, 0x32, 0x19, 0x7d, 0x86, 0xe8,
+    0xc3, 0x17, 0xf9, 0x55, 0xff, 0xbc, 0xf2, 0xd7, 0x63, 0x7f, 0xc2, 0x75,
+    0xff, 0xde, 0x4e, 0x09, 0xe9, 0xa5, 0x03, 0xe3, 0xaf, 0xff, 0x3e, 0x4b,
+    0xb8, 0x83, 0x9f, 0x71, 0xe1, 0xd7, 0x9e, 0x4c, 0xc2, 0xf5, 0x0c, 0xa1,
+    0x36, 0x18, 0x55, 0x64, 0x63, 0x0b, 0x34, 0xd4, 0xae, 0x7f, 0x2d, 0xff,
+    0x40, 0xe2, 0x45, 0xbf, 0xfd, 0x9d, 0x64, 0x70, 0x28, 0x3e, 0xce, 0x9d,
+    0x7b, 0xd0, 0x12, 0xaf, 0xff, 0x75, 0xd3, 0xd1, 0x24, 0xdc, 0xe0, 0xf8,
+    0xab, 0xfc, 0xed, 0x64, 0x3b, 0x54, 0xb3, 0x07, 0xcb, 0xa1, 0xbb, 0x32,
+    0x16, 0x52, 0xe3, 0x63, 0x46, 0x5c, 0xfb, 0x6f, 0xa1, 0x5b, 0xc2, 0x15,
+    0x97, 0xff, 0x99, 0x5b, 0xc9, 0x9c, 0xdb, 0x5d, 0xda, 0x68, 0x98, 0x6f,
+    0xff, 0xec, 0xe0, 0xe1, 0xec, 0x33, 0xee, 0xe0, 0x41, 0xed, 0x1d, 0x7f,
+    0xfb, 0x6f, 0xf3, 0x2a, 0x7a, 0x4c, 0x46, 0xa4, 0x75, 0xd8, 0xc8, 0xa2,
+    0xaf, 0xfa, 0xed, 0xff, 0xca, 0x8c, 0xe6, 0x40, 0x7f, 0x0c, 0x48, 0xeb,
+    0xf6, 0x2f, 0xf7, 0x2a, 0xe7, 0x5f, 0xd0, 0xbc, 0xfa, 0x38, 0x1d, 0x41,
+    0x3d, 0xbe, 0x96, 0xdf, 0xbb, 0x01, 0x45, 0x0e, 0xa4, 0x3c, 0x9e, 0x22,
+    0x2b, 0xfd, 0x0f, 0x3f, 0x94, 0x7d, 0x9d, 0x7e, 0x7d, 0xc9, 0xd6, 0x75,
+    0x09, 0xec, 0x80, 0xce, 0xff, 0xfc, 0x9b, 0xeb, 0xfe, 0x0e, 0x4b, 0xb1,
+    0xc0, 0x30, 0x75, 0xff, 0x31, 0xff, 0xb0, 0xde, 0xa4, 0xc7, 0x5f, 0x01,
+    0x78, 0x13, 0xad, 0x9c, 0x9e, 0xef, 0x11, 0xe5, 0x75, 0x1b, 0xe3, 0x0b,
+    0x4b, 0xf9, 0x71, 0x83, 0xee, 0x33, 0xad, 0xa3, 0xaf, 0xd1, 0x83, 0xee,
+    0x33, 0xaf, 0xee, 0xa7, 0xb4, 0xfc, 0xfe, 0x3e, 0x69, 0x8b, 0x96, 0x21,
+    0x7f, 0xa5, 0xe8, 0x5f, 0x0f, 0xa4, 0x75, 0xff, 0xfe, 0x63, 0x8b, 0xd9,
+    0xdf, 0xc3, 0x93, 0xa6, 0x0f, 0x32, 0xd1, 0xd7, 0xe6, 0x3d, 0x9d, 0x69,
+    0xd6, 0x1c, 0x44, 0x73, 0xb3, 0x5f, 0xfe, 0xf0, 0xbf, 0xdd, 0xc4, 0x08,
+    0x3d, 0xa3, 0xaf, 0xfa, 0x27, 0xff, 0x2e, 0x81, 0xe7, 0x3a, 0xa1, 0x10,
+    0xbb, 0x49, 0xbf, 0xfb, 0x39, 0x97, 0xee, 0xbb, 0x60, 0x42, 0x75, 0xfd,
+    0xc3, 0xff, 0x86, 0x3e, 0x3a, 0xff, 0xf4, 0x7b, 0xe8, 0x96, 0x73, 0xe9,
+    0xc0, 0xc1, 0xd5, 0x07, 0xfc, 0x86, 0x37, 0xf3, 0xfd, 0xbd, 0xa6, 0xce,
+    0xbd, 0xef, 0xd8, 0x75, 0x7c, 0x79, 0x5f, 0xcb, 0x6f, 0xed, 0x22, 0x8b,
+    0x7f, 0x1d, 0x7f, 0xff, 0xed, 0xe7, 0x08, 0x1f, 0x7e, 0xfe, 0x31, 0xd7,
+    0x4f, 0x47, 0xb4, 0x75, 0xfc, 0x39, 0xaf, 0xcd, 0x55, 0x1d, 0x5c, 0xa3,
+    0x37, 0x65, 0xbc, 0x1b, 0xaf, 0xbf, 0x70, 0xe2, 0x9c, 0xea, 0xc3, 0xdd,
+    0x50, 0xce, 0xca, 0xe7, 0x5d, 0xec, 0x3a, 0xff, 0xf2, 0xa4, 0x61, 0x6e,
+    0x9d, 0x7f, 0x76, 0x0e, 0xa8, 0x3d, 0xf0, 0x0a, 0xdf, 0xee, 0xa4, 0xce,
+    0xdd, 0x48, 0xeb, 0xfd, 0x03, 0xe7, 0x5a, 0x78, 0xeb, 0xfe, 0xc4, 0xc5,
+    0x8e, 0x4e, 0xe7, 0x5f, 0xa3, 0xda, 0xf8, 0x07, 0x52, 0xb2, 0x9a, 0x9e,
+    0x39, 0x34, 0x87, 0xa6, 0x62, 0x61, 0xe3, 0x5b, 0xff, 0xf7, 0x47, 0x3d,
+    0xd4, 0xce, 0x7d, 0x9c, 0x23, 0x47, 0x5f, 0xfc, 0xe3, 0xd8, 0x40, 0xa6,
+    0xb2, 0x47, 0x5e, 0x8f, 0xbf, 0x9d, 0x58, 0x8b, 0x37, 0x55, 0x14, 0x0b,
+    0xdf, 0xc3, 0x87, 0x5e, 0x54, 0xe9, 0x54, 0x75, 0x39, 0xe0, 0xe8, 0x76,
+    0xff, 0x0b, 0xb1, 0x1e, 0xc9, 0xce, 0xb3, 0x2a, 0xa6, 0x54, 0xdc, 0x43,
+    0xac, 0x2f, 0xb9, 0x18, 0x03, 0x61, 0x1b, 0xca, 0xac, 0xd0, 0xc4, 0xdc,
+    0x2a, 0xd6, 0x45, 0xd8, 0x61, 0xfc, 0xd4, 0x31, 0xa7, 0xea, 0x37, 0x5f,
+    0x46, 0x1c, 0x06, 0xee, 0x32, 0x1b, 0xff, 0xed, 0xa7, 0x32, 0xd2, 0x7b,
+    0xb1, 0xbf, 0x41, 0xd7, 0xed, 0xb5, 0xdd, 0xa6, 0x8a, 0xba, 0xf6, 0xe1,
+    0x67, 0x5f, 0xf4, 0x99, 0xcd, 0xb5, 0xdd, 0xa6, 0x88, 0xf2, 0xff, 0xa2,
+    0x51, 0xb9, 0xe3, 0x73, 0x9d, 0x7f, 0xe8, 0xf2, 0x01, 0x53, 0x92, 0x9e,
+    0x63, 0xac, 0xc8, 0x53, 0x5e, 0xc4, 0xfd, 0x99, 0xb8, 0xd8, 0xa2, 0xe8,
+    0xe6, 0xfd, 0xb6, 0xbb, 0xb4, 0xd1, 0x60, 0xde, 0x52, 0x27, 0x3a, 0xff,
+    0xfe, 0x10, 0x3c, 0xeb, 0xce, 0x30, 0x6f, 0x37, 0x2f, 0xf2, 0x3a, 0xfd,
+    0x83, 0x9e, 0xd1, 0xd7, 0xfb, 0x6e, 0xbf, 0xfb, 0x7e, 0x4e, 0xb3, 0x38,
+    0x98, 0x52, 0x86, 0x6d, 0x1d, 0x76, 0x0f, 0xe4, 0xb7, 0xf9, 0x9c, 0xdb,
+    0x5d, 0xda, 0x68, 0xb2, 0xaf, 0xdb, 0x6b, 0xbb, 0x4d, 0x16, 0x9d, 0xff,
+    0x38, 0x7a, 0xf3, 0x75, 0x16, 0x75, 0x99, 0xc3, 0xeb, 0x59, 0x9d, 0xf9,
+    0x5a, 0x2a, 0xf5, 0x65, 0x59, 0x56, 0xce, 0xbf, 0xe5, 0x57, 0x51, 0x80,
+    0xbb, 0xb4, 0xeb, 0xf2, 0xb4, 0x54, 0x6b, 0x20, 0xeb, 0xfd, 0xfd, 0x79,
+    0xed, 0x26, 0x8e, 0xb2, 0x1d, 0x4a, 0xa3, 0xc3, 0xe3, 0x34, 0xbf, 0xff,
+    0x93, 0xae, 0x3e, 0x96, 0x6f, 0x20, 0x47, 0x3c, 0x75, 0xfb, 0x83, 0x87,
+    0x16, 0x75, 0xf2, 0xe3, 0x9d, 0x1d, 0x52, 0x44, 0xfe, 0x2a, 0xcc, 0x51,
+    0x7e, 0xfd, 0xbd, 0x83, 0xa7, 0x5f, 0x91, 0x48, 0x16, 0x9d, 0x6c, 0xd1,
+    0xe8, 0x78, 0xaa, 0xff, 0xf8, 0x5b, 0xd4, 0xea, 0x6e, 0x26, 0x63, 0x3a,
+    0x75, 0xff, 0xd0, 0xb5, 0xbc, 0xb8, 0xc1, 0xd4, 0xd9, 0xd5, 0x08, 0x95,
+    0xea, 0x7d, 0xf4, 0x7f, 0x8e, 0x9d, 0x7c, 0xd7, 0x76, 0x9a, 0x2d, 0xcb,
+    0xff, 0x66, 0xf0, 0x7f, 0x77, 0x39, 0x60, 0xeb, 0xf0, 0xfc, 0xfc, 0xe8,
+    0xea, 0x83, 0xe8, 0x74, 0x0a, 0xe5, 0x1a, 0xfb, 0x22, 0xd4, 0x25, 0x6f,
+    0xf3, 0x8f, 0xd3, 0x0c, 0x2c, 0xeb, 0xcb, 0x14, 0x3a, 0xc2, 0x75, 0xff,
+    0x74, 0x0f, 0xac, 0xc1, 0x50, 0xeb, 0xf6, 0x9f, 0x97, 0x09, 0xd6, 0x40,
+    0x9e, 0xf7, 0x8d, 0xea, 0x11, 0x5d, 0x83, 0x5d, 0x6d, 0xbf, 0xe8, 0x71,
+    0xee, 0x60, 0xb4, 0xeb, 0xfd, 0xef, 0x24, 0xeb, 0x81, 0x3a, 0xa4, 0x7c,
+    0xd8, 0x69, 0x7f, 0xd0, 0x20, 0x5c, 0x6b, 0xc8, 0x75, 0xf0, 0x63, 0x36,
+    0x75, 0xfb, 0xf7, 0x3a, 0x45, 0x0e, 0xb3, 0xce, 0x79, 0x7c, 0x90, 0x5f,
+    0xfd, 0x2c, 0xea, 0x6c, 0x3d, 0x81, 0x69, 0xd7, 0xfb, 0x99, 0x40, 0xfb,
+    0x3e, 0x3a, 0xfb, 0x5f, 0x27, 0x8e, 0xa7, 0x46, 0x06, 0x8a, 0x40, 0x85,
+    0xfc, 0xce, 0xff, 0xef, 0x27, 0xd1, 0x20, 0xf6, 0x05, 0xa7, 0x51, 0xd7,
+    0x80, 0xfe, 0x3a, 0xe0, 0x41, 0xd5, 0x23, 0x61, 0xe1, 0xba, 0x3a, 0xfb,
+    0x96, 0xa6, 0xce, 0xbd, 0x0b, 0x67, 0x11, 0x0f, 0xc9, 0xd2, 0xc8, 0x7c,
+    0x15, 0x50, 0x98, 0xca, 0x43, 0x2a, 0xf0, 0xfb, 0x8c, 0xeb, 0xfe, 0x93,
+    0x39, 0xb6, 0xbb, 0xb4, 0xd1, 0x43, 0xd2, 0x1f, 0x1b, 0x8f, 0x5f, 0xbe,
+    0x86, 0xe2, 0xce, 0xbe, 0x89, 0xb0, 0x27, 0x56, 0xcf, 0x23, 0x44, 0xf7,
+    0xfe, 0x5e, 0x40, 0x7b, 0x1c, 0x51, 0x31, 0xd5, 0x07, 0xc4, 0xe4, 0x57,
+    0xfe, 0x70, 0xc0, 0x7a, 0x82, 0x8b, 0x3a, 0xff, 0xed, 0x40, 0xcd, 0x83,
+    0xf3, 0xfb, 0x0e, 0xbf, 0xda, 0x03, 0x73, 0xc3, 0x07, 0x52, 0xd1, 0x5d,
+    0xd3, 0xbf, 0x21, 0x5f, 0xfc, 0x09, 0x75, 0xf7, 0xcf, 0xa1, 0x27, 0x3a,
+    0xff, 0xa2, 0x51, 0xb9, 0xe3, 0x73, 0x9d, 0x7e, 0x4f, 0x69, 0xd0, 0xeb,
+    0xfe, 0xdf, 0xdb, 0x71, 0xf6, 0x7c, 0x75, 0x7c, 0x7b, 0xc0, 0x25, 0xbd,
+    0xff, 0x72, 0x3a, 0xfe, 0xff, 0xe0, 0x46, 0x4e, 0x75, 0x48, 0xf3, 0x66,
+    0x1e, 0xbf, 0xf9, 0xa3, 0x1e, 0x1c, 0xe1, 0x9b, 0x91, 0xd7, 0xfc, 0x01,
+    0x53, 0xff, 0x7a, 0x0d, 0x1d, 0x7f, 0x84, 0x5f, 0xdf, 0xe1, 0xa7, 0x5f,
+    0x0f, 0xd3, 0xfc, 0x75, 0x61, 0xeb, 0x21, 0x95, 0xfe, 0xd7, 0xef, 0x7e,
+    0x0e, 0x09, 0xd6, 0xf8, 0xeb, 0x27, 0x27, 0x8f, 0xb3, 0x6b, 0xf3, 0xf3,
+    0xaf, 0x21, 0xd5, 0x09, 0xd7, 0x61, 0x1a, 0x21, 0xf6, 0x12, 0x42, 0xcf,
+    0xa2, 0x8b, 0xf3, 0x81, 0x48, 0xfe, 0x75, 0xf9, 0x55, 0x9b, 0x8d, 0x1d,
+    0x53, 0x1e, 0x98, 0x94, 0xdf, 0xf3, 0xea, 0x26, 0xe6, 0x59, 0xc0, 0xeb,
+    0xff, 0xf0, 0x7b, 0x1f, 0xd9, 0xf0, 0xbf, 0xda, 0xd4, 0x7c, 0x55, 0xc1,
+    0xc3, 0xaf, 0xd3, 0xc4, 0xef, 0xa3, 0xab, 0x11, 0x2c, 0x8b, 0x2e, 0x2b,
+    0x77, 0xc0, 0x3a, 0xfe, 0x7f, 0xa6, 0x18, 0x09, 0xd5, 0x07, 0x89, 0xd1,
+    0x7b, 0x32, 0xac, 0x33, 0xf3, 0xd5, 0xb4, 0x35, 0x5e, 0x78, 0xab, 0x39,
+    0xc4, 0x32, 0x25, 0x08, 0x00, 0xc2, 0xf3, 0x21, 0xf2, 0xa1, 0xb3, 0x61,
+    0xc1, 0xcc, 0x25, 0x10, 0x86, 0x68, 0xd0, 0x77, 0x1a, 0xba, 0xe1, 0x15,
+    0xd8, 0x65, 0x3c, 0x33, 0xbe, 0x30, 0x14, 0x5d, 0x42, 0x5f, 0xd2, 0x87,
+    0x81, 0x0a, 0xce, 0x04, 0x5c, 0x70, 0xd1, 0xfe, 0xe3, 0x7f, 0x33, 0x3c,
+    0x6e, 0x4b, 0x3a, 0xff, 0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x17, 0x9d, 0x43,
+    0xa3, 0x41, 0x93, 0x78, 0x63, 0x02, 0xca, 0x56, 0x5f, 0x32, 0x9e, 0xb7,
+    0x1b, 0x32, 0xd4, 0xfb, 0x0a, 0xa1, 0xa7, 0xfb, 0xea, 0x3c, 0x3e, 0x05,
+    0xf7, 0xf9, 0x9c, 0xdb, 0x5d, 0xda, 0x68, 0xa5, 0xaf, 0xdb, 0x6b, 0xbb,
+    0x4d, 0x16, 0x15, 0xff, 0xfa, 0x30, 0x43, 0x1d, 0x8e, 0x7d, 0x82, 0xeb,
+    0x3a, 0xfe, 0x06, 0xd2, 0x77, 0x59, 0xd6, 0x67, 0x11, 0x62, 0xb3, 0x3e,
+    0x35, 0x1b, 0xfc, 0xce, 0x6d, 0xae, 0xed, 0x34, 0x59, 0x77, 0x6d, 0x43,
+    0xaf, 0x99, 0x51, 0x56, 0x56, 0x0e, 0xbc, 0xcf, 0xf5, 0x9d, 0x4d, 0x3c,
+    0xd0, 0x17, 0x50, 0xa2, 0x1b, 0x4c, 0x96, 0xf8, 0xeb, 0x94, 0x9c, 0xeb,
+    0x9f, 0x72, 0x35, 0x38, 0x23, 0x7f, 0xcf, 0xc8, 0xe7, 0x3e, 0x85, 0x0e,
+    0xbf, 0xd3, 0xf3, 0xa8, 0x0f, 0x90, 0xeb, 0xf4, 0x67, 0x08, 0xd1, 0xd6,
+    0x87, 0x3d, 0xb6, 0x0d, 0x29, 0xd1, 0x76, 0x30, 0x94, 0xbe, 0x79, 0x48,
+    0x27, 0x5f, 0xcf, 0xb8, 0xf3, 0xf4, 0xeb, 0xcc, 0x30, 0xc1, 0x57, 0xfd,
+    0x12, 0xe7, 0xdb, 0x8c, 0xe4, 0xa6, 0x4b, 0xfb, 0xfe, 0x03, 0xf3, 0x9e,
+    0x4e, 0x58, 0x3a, 0xe8, 0xd1, 0xd4, 0x14, 0xc0, 0xfa, 0x42, 0x29, 0x5a,
+    0x49, 0xe0, 0x75, 0x7f, 0x23, 0xeb, 0xed, 0x00, 0xeb, 0xff, 0xfb, 0xa9,
+    0xee, 0xe6, 0x87, 0x16, 0x0d, 0x75, 0xe4, 0x75, 0xfe, 0x89, 0x79, 0xfa,
+    0xe1, 0x3a, 0xb1, 0x11, 0x5b, 0x59, 0xb4, 0x8e, 0xb4, 0x8e, 0xb4, 0x8e,
+    0xa8, 0x36, 0x0a, 0x08, 0x20, 0x85, 0xff, 0xfb, 0xda, 0x46, 0xe0, 0xee,
+    0x07, 0x03, 0x8a, 0x1d, 0x6e, 0x4e, 0xbb, 0x40, 0x3a, 0xb0, 0xfe, 0x74,
+    0xa5, 0xe1, 0x1b, 0x92, 0x0e, 0xbf, 0x86, 0x16, 0x31, 0x87, 0x5d, 0x28,
+    0x3a, 0x82, 0x7a, 0x53, 0x0a, 0x00, 0xa6, 0xff, 0xff, 0xfb, 0xb1, 0xed,
+    0x26, 0xb5, 0x1e, 0xea, 0x46, 0xfe, 0x5b, 0xca, 0x5e, 0x50, 0xeb, 0x93,
+    0x93, 0xae, 0x85, 0x9d, 0x7f, 0xff, 0x4a, 0x04, 0x12, 0x94, 0x7b, 0xb8,
+    0xbf, 0xf1, 0xf1, 0xd7, 0x35, 0x98, 0x5e, 0x0a, 0x9d, 0x2c, 0x30, 0xe6,
+    0xc8, 0xca, 0x5a, 0x99, 0xb8, 0x5b, 0xba, 0x90, 0xc2, 0x9b, 0x50, 0x80,
+    0xf1, 0x87, 0x07, 0xee, 0x31, 0x6f, 0xe2, 0xb7, 0xff, 0x99, 0x5b, 0xc9,
+    0x9c, 0xdb, 0x5d, 0xda, 0x68, 0xa3, 0x2f, 0xdc, 0x23, 0x71, 0xf1, 0xd7,
+    0xe1, 0x7f, 0xa3, 0xf9, 0xd7, 0xff, 0x72, 0xd4, 0xdf, 0x73, 0x06, 0x5a,
+    0x3a, 0xcc, 0xc2, 0x25, 0x3a, 0x53, 0xe2, 0x8a, 0x93, 0x27, 0xe7, 0x70,
+    0xf0, 0x59, 0xcb, 0xcf, 0x67, 0xea, 0x1c, 0x1e, 0x87, 0x5d, 0xff, 0xcc,
+    0xbc, 0x99, 0xcd, 0xb5, 0xdd, 0xa6, 0x88, 0xe6, 0xff, 0xf3, 0x2b, 0x79,
+    0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x13, 0x95, 0xfe, 0x67, 0x36, 0xd7, 0x76,
+    0x9a, 0x2c, 0xcb, 0xfe, 0x96, 0x9d, 0x6c, 0xf7, 0xdf, 0x1d, 0x7f, 0xca,
+    0xb8, 0x38, 0xb8, 0xe6, 0x16, 0x75, 0xff, 0x7d, 0xb8, 0xf7, 0x5f, 0x99,
+    0x1d, 0x7f, 0xb3, 0x5b, 0xde, 0x73, 0xa3, 0xae, 0xe5, 0x67, 0x59, 0x95,
+    0x61, 0x18, 0x50, 0x7d, 0x23, 0xae, 0x33, 0x3b, 0xfc, 0xce, 0x6d, 0xae,
+    0xed, 0x34, 0x5b, 0xb7, 0xf0, 0xbb, 0x3b, 0x9f, 0xa7, 0x5e, 0x4e, 0x7e,
+    0x3a, 0xfd, 0xb6, 0xbb, 0xb4, 0xd1, 0x48, 0x5f, 0xfb, 0x3a, 0x9c, 0x3b,
+    0x98, 0x2d, 0x3a, 0xf3, 0xc9, 0x9c, 0x3f, 0x0d, 0x19, 0xd9, 0x96, 0xa3,
+    0xbb, 0x65, 0xcb, 0x84, 0x6d, 0xff, 0xcc, 0xbc, 0x99, 0xcd, 0xb5, 0xdd,
+    0xa6, 0x89, 0x4a, 0xa7, 0x57, 0xd3, 0x32, 0x8a, 0xd5, 0xdc, 0xff, 0xe8,
+    0x7e, 0x8a, 0x5f, 0xa3, 0x2d, 0xe2, 0x3c, 0xbf, 0xd2, 0x41, 0xf6, 0x20,
+    0x4e, 0xbd, 0xa0, 0x2c, 0xeb, 0x33, 0xc9, 0xe6, 0x21, 0x85, 0xe1, 0x79,
+    0x1d, 0x7f, 0xe7, 0x93, 0x39, 0xb6, 0xbb, 0xb4, 0xd1, 0x3b, 0x5d, 0x3a,
+    0xb9, 0xd7, 0xff, 0xe4, 0x08, 0x17, 0x1c, 0x4e, 0x11, 0x81, 0xc6, 0x9d,
+    0x7f, 0xd1, 0x28, 0xdc, 0xf1, 0xb9, 0xce, 0xb3, 0x38, 0x98, 0x5a, 0xc6,
+    0xba, 0x94, 0xe3, 0x42, 0xa9, 0x7f, 0xfc, 0xcf, 0xfe, 0x37, 0x1f, 0xb3,
+    0xd0, 0x29, 0xf1, 0xd7, 0xff, 0x3a, 0xfb, 0x8d, 0x7e, 0xc7, 0xf9, 0x1d,
+    0x79, 0x02, 0xe7, 0x5f, 0xfc, 0x39, 0xd7, 0x9f, 0x34, 0x2f, 0xc9, 0xd7,
+    0x71, 0xb2, 0x14, 0x50, 0x75, 0x13, 0x43, 0x55, 0x25, 0x56, 0xeb, 0x8c,
+    0xd3, 0x49, 0xfc, 0x70, 0xf4, 0xbf, 0xff, 0x82, 0xfe, 0x67, 0x35, 0x03,
+    0xcf, 0xda, 0xd4, 0x7c, 0x75, 0xfb, 0x6d, 0x77, 0x69, 0xa2, 0x2c, 0xbf,
+    0xf3, 0xc9, 0x9c, 0xdb, 0x5d, 0xda, 0x68, 0x97, 0x6f, 0xff, 0xec, 0x0f,
+    0x63, 0xfb, 0x3e, 0x17, 0xfb, 0x5a, 0x8f, 0x8a, 0xb3, 0x38, 0x8d, 0xb5,
+    0x99, 0xf1, 0xa5, 0x5f, 0xfe, 0x65, 0x6f, 0x26, 0x73, 0x6d, 0x77, 0x69,
+    0xa2, 0x62, 0xbf, 0x6d, 0xae, 0xed, 0x34, 0x55, 0x36, 0xc3, 0xab, 0x0f,
+    0x09, 0x43, 0x3b, 0xff, 0xff, 0xdb, 0x7e, 0xf3, 0x2c, 0xf3, 0x3d, 0x7d,
+    0x6d, 0x18, 0xf7, 0x53, 0x72, 0x3a, 0x99, 0x44, 0xe3, 0x91, 0x5f, 0xfe,
+    0x65, 0x6f, 0x26, 0x73, 0x6d, 0x77, 0x69, 0xa2, 0x74, 0xbf, 0xc8, 0xfb,
+    0x89, 0x3f, 0x03, 0xaf, 0xd3, 0x44, 0xd1, 0xa3, 0xaf, 0xe6, 0x31, 0x38,
+    0x60, 0x9d, 0x48, 0x7a, 0xba, 0x28, 0xbc, 0x9d, 0x83, 0x99, 0x34, 0x37,
+    0xff, 0x03, 0x5e, 0x8e, 0x59, 0x04, 0xc8, 0xb3, 0xa9, 0x67, 0xe5, 0xd2,
+    0xbb, 0xff, 0x3c, 0x99, 0xcd, 0xb5, 0xdd, 0xa6, 0x89, 0xde, 0xfd, 0xe0,
+    0x3a, 0xd0, 0xab, 0xff, 0x0c, 0x7b, 0x35, 0x99, 0xcc, 0x8e, 0xa0, 0xa7,
+    0xd1, 0x91, 0x8d, 0x2c, 0x89, 0xd2, 0xbc, 0x4d, 0x7f, 0x43, 0x3f, 0x0e,
+    0x04, 0xea, 0x64, 0xff, 0x05, 0x3e, 0xff, 0xf3, 0x2b, 0x79, 0x33, 0x9b,
+    0x6b, 0xbb, 0x4d, 0x14, 0x2d, 0xff, 0xff, 0xee, 0x81, 0x6b, 0x79, 0x32,
+    0xde, 0x83, 0xd0, 0x39, 0x3a, 0x80, 0x89, 0x8e, 0xbf, 0x03, 0x9f, 0x23,
+    0x4e, 0xbf, 0x67, 0xd8, 0xe2, 0x75, 0xe8, 0xf9, 0x99, 0xcf, 0x34, 0x4a,
+    0x29, 0x11, 0xfa, 0x30, 0xc8, 0xbf, 0xfc, 0xca, 0xde, 0x4c, 0xe6, 0xda,
+    0xee, 0xd3, 0x45, 0x25, 0x7f, 0xff, 0xb3, 0x4c, 0xff, 0xc9, 0xba, 0xeb,
+    0xf7, 0x63, 0xc0, 0x59, 0xd5, 0x0b, 0xfb, 0x73, 0xc6, 0x71, 0x23, 0x96,
+    0xc6, 0x6b, 0xb2, 0x35, 0xca, 0xbb, 0xf8, 0x8b, 0xd1, 0xaa, 0x00, 0x9b,
+    0x8d, 0x5e, 0xff, 0x33, 0x9b, 0x6b, 0xbb, 0x4d, 0x11, 0x25, 0xff, 0xe6,
+    0x56, 0xf2, 0x67, 0x36, 0xd7, 0x76, 0x9a, 0x25, 0xeb, 0xed, 0x83, 0xda,
+    0x3a, 0xfd, 0xbf, 0x96, 0x9a, 0x3a, 0xf4, 0x0f, 0x27, 0x5f, 0xbd, 0xfd,
+    0x63, 0x07, 0x59, 0x3a, 0x78, 0x62, 0x37, 0x7f, 0xfb, 0xbc, 0x20, 0x7e,
+    0x57, 0xc0, 0xe6, 0xf9, 0x3a, 0xe8, 0xf1, 0xd7, 0xff, 0x80, 0x14, 0xdf,
+    0xf9, 0xb8, 0x80, 0xe3, 0x31, 0xd5, 0x24, 0x6d, 0x21, 0x37, 0xc9, 0xfa,
+    0x15, 0xbf, 0xf9, 0xe6, 0xd4, 0x70, 0x7e, 0xc7, 0x33, 0x1d, 0x7e, 0xc9,
+    0xf3, 0x4b, 0x3a, 0xff, 0xe9, 0xbf, 0x7f, 0x18, 0xe0, 0xfc, 0x22, 0x63,
+    0xa8, 0xeb, 0xfa, 0x69, 0x3f, 0x9f, 0x81, 0xd5, 0x08, 0x85, 0xc4, 0xc7,
+    0x0a, 0xbb, 0x70, 0x75, 0x05, 0x56, 0xca, 0x11, 0x4d, 0x1a, 0x2e, 0xcf,
+    0x45, 0x1f, 0x84, 0x2b, 0x38, 0x8b, 0x6e, 0x0f, 0x27, 0x5f, 0xf2, 0x38,
+    0x83, 0xd3, 0x42, 0x87, 0x5f, 0xff, 0x26, 0xff, 0x76, 0x13, 0xda, 0x03,
+    0x41, 0x07, 0x5f, 0x24, 0xff, 0x2b, 0x9d, 0x7c, 0xd7, 0x76, 0x9a, 0x29,
+    0x7b, 0xe1, 0xf4, 0x6c, 0xeb, 0xfe, 0xcd, 0xab, 0xe0, 0x73, 0x7c, 0x9d,
+    0x48, 0x7b, 0x7c, 0x08, 0x29, 0x44, 0xc8, 0x66, 0x50, 0xd9, 0x37, 0x61,
+    0x11, 0x7e, 0x1f, 0x4f, 0x8c, 0x1d, 0x7f, 0xe8, 0x18, 0xef, 0xe0, 0x08,
+    0x1a, 0x75, 0xe0, 0x3e, 0x8e, 0xbf, 0x47, 0xcf, 0xce, 0x8e, 0xbc, 0x29,
+    0xf1, 0xd7, 0xb3, 0xda, 0x3a, 0xa0, 0xdb, 0x68, 0x6e, 0x82, 0x8d, 0x79,
+    0x8f, 0xbe, 0x1b, 0xf2, 0xf5, 0xf9, 0x5d, 0xc4, 0x3c, 0x47, 0x5f, 0xf7,
+    0xda, 0xdc, 0x73, 0x24, 0x59, 0xd7, 0xbc, 0xfc, 0x0e, 0xbf, 0xe7, 0x9f,
+    0xf4, 0xe0, 0x9a, 0x15, 0xce, 0xa8, 0x44, 0xbb, 0x9d, 0x00, 0x76, 0xff,
+    0x93, 0x53, 0x20, 0xfa, 0x3e, 0x3a, 0xa4, 0x7c, 0xcb, 0x2e, 0xb9, 0xc4,
+    0xeb, 0xfe, 0x8f, 0xbf, 0x76, 0x16, 0xe2, 0x75, 0xb7, 0xc9, 0xe6, 0xf0,
+    0x14, 0xa8, 0x4f, 0x0f, 0x23, 0x29, 0x46, 0xfb, 0xdb, 0x85, 0x9d, 0x7f,
+    0x40, 0xcd, 0xe4, 0x50, 0xeb, 0xfe, 0x96, 0x6e, 0x6c, 0x18, 0x59, 0xd7,
+    0xef, 0xa1, 0xb8, 0xb3, 0xa9, 0x0f, 0x7b, 0x66, 0xf7, 0x4b, 0x0e, 0xbd,
+    0x1f, 0x68, 0xea, 0x83, 0xd2, 0x09, 0x0b, 0x02, 0xb7, 0xee, 0x81, 0x4c,
+    0x13, 0xaf, 0xfa, 0x3b, 0xa7, 0xf4, 0x6f, 0x88, 0xeb, 0xff, 0x2d, 0xc3,
+    0xfe, 0x69, 0x40, 0xf2, 0x75, 0x04, 0xfe, 0xd0, 0xea, 0xfb, 0x7f, 0x7f,
+    0xe0, 0x75, 0xe4, 0x63, 0xc7, 0x57, 0x4f, 0x0f, 0x44, 0xf4, 0x14, 0xca,
+    0x3b, 0x0a, 0x2f, 0x32, 0x5f, 0xf7, 0xc9, 0xdc, 0xdb, 0xcd, 0xa3, 0xaf,
+    0xff, 0xd1, 0x21, 0x89, 0xff, 0xcd, 0xae, 0xe7, 0x16, 0xfe, 0x3a, 0xfe,
+    0xfc, 0xbc, 0xf3, 0xf8, 0xeb, 0x34, 0xeb, 0xb9, 0xd6, 0x1b, 0xe7, 0x2e,
+    0xae, 0x51, 0xfe, 0xb3, 0x97, 0x84, 0xd5, 0xfe, 0xc6, 0x24, 0x9a, 0x02,
+    0xce, 0xbb, 0x86, 0x8e, 0xbf, 0x64, 0xf9, 0xdd, 0x1d, 0x50, 0x6f, 0xc4,
+    0x62, 0xf6, 0x6f, 0x47, 0x53, 0x4d, 0xd7, 0x01, 0xfb, 0xfe, 0xfa, 0x3e,
+    0xff, 0xc2, 0x07, 0x88, 0xea, 0x84, 0xc3, 0xf2, 0x15, 0x88, 0x47, 0x7f,
+    0xff, 0xf7, 0x63, 0x7c, 0xb5, 0x39, 0xfc, 0xa3, 0xfe, 0xd7, 0x5d, 0xb0,
+    0x21, 0x3a, 0xfb, 0xc2, 0x8b, 0x3a, 0xff, 0x0c, 0x38, 0xfb, 0x04, 0xeb,
+    0xfd, 0xd7, 0x99, 0x37, 0x13, 0x9d, 0x76, 0x2c, 0xea, 0x0a, 0x61, 0xb8,
+    0xee, 0xb2, 0x07, 0x2e, 0xe0, 0x67, 0x7e, 0xe2, 0x45, 0xc6, 0x8e, 0xbf,
+    0x3f, 0x0c, 0xde, 0x8e, 0xa0, 0x9e, 0x8a, 0xca, 0x6f, 0xdd, 0x71, 0x45,
+    0x9d, 0x7c, 0xa4, 0xda, 0x83, 0xaf, 0xf3, 0xfd, 0xa8, 0xec, 0x68, 0xea,
+    0x84, 0x4e, 0x61, 0x12, 0x12, 0x89, 0x1d, 0xdf, 0x34, 0xeb, 0x68, 0xeb,
+    0x91, 0x4d, 0x1a, 0x70, 0x0b, 0xde, 0xf9, 0xda, 0x75, 0xff, 0xf9, 0x03,
+    0x9c, 0x1f, 0x73, 0x7f, 0x93, 0xf9, 0xd6, 0x75, 0x41, 0xfa, 0x6c, 0x72,
+    0xcc, 0xc3, 0x37, 0x06, 0x4e, 0xa1, 0x17, 0xc8, 0xd6, 0x79, 0x45, 0x48,
+    0x7f, 0xcd, 0x28, 0x0b, 0x66, 0x8b, 0x1b, 0xec, 0x37, 0x5e, 0x35, 0x7f,
+    0xa3, 0x35, 0x18, 0xd1, 0x35, 0x1a, 0x07, 0xa3, 0x38, 0xe3, 0x60, 0xff,
+    0x0a, 0x1b, 0xfc, 0xce, 0x6d, 0xae, 0xed, 0x34, 0x53, 0x97, 0xfe, 0x4d,
+    0xbe, 0xbb, 0x98, 0x2d, 0x3a, 0xfc, 0xbd, 0xef, 0x34, 0x75, 0xff, 0xfb,
+    0xa0, 0xf6, 0xe3, 0xda, 0xc6, 0xea, 0x36, 0xd3, 0xaf, 0xf2, 0x2c, 0x31,
+    0xa0, 0x09, 0xd7, 0xf6, 0x7b, 0x99, 0x43, 0x07, 0x5f, 0xfc, 0xa2, 0x73,
+    0xa1, 0xc0, 0xf5, 0xd8, 0x3a, 0xff, 0xd9, 0xd8, 0xde, 0x32, 0xc3, 0x0c,
+    0x15, 0x72, 0x30, 0x75, 0xd3, 0xb2, 0x14, 0xec, 0xb0, 0xed, 0xa4, 0xfd,
+    0x55, 0x13, 0x1f, 0x17, 0x71, 0xa2, 0xf1, 0x20, 0xdf, 0xb6, 0xd7, 0x76,
+    0x9a, 0x2b, 0xcb, 0xff, 0xfb, 0x03, 0xd8, 0xfe, 0xcf, 0x85, 0xfe, 0xd6,
+    0xa3, 0xe2, 0xac, 0xce, 0x22, 0x47, 0x8c, 0xce, 0xff, 0xe6, 0x5e, 0x4c,
+    0xe6, 0xda, 0xee, 0xd3, 0x44, 0x8f, 0x79, 0xb8, 0xb3, 0xaf, 0x27, 0xd0,
+    0x75, 0xe6, 0xe2, 0xca, 0x64, 0xbb, 0xbf, 0x6d, 0xae, 0xed, 0x34, 0x49,
+    0x17, 0xff, 0xf4, 0x26, 0xd3, 0x8a, 0x06, 0x78, 0xf2, 0x75, 0xe7, 0x3a,
+    0xe9, 0x33, 0x08, 0xb9, 0xc2, 0xbe, 0x99, 0xdf, 0xb3, 0xac, 0xe2, 0xce,
+    0xb3, 0x30, 0x9a, 0x8b, 0xc3, 0xbf, 0xc7, 0x77, 0xff, 0x32, 0xf2, 0x67,
+    0x36, 0xd7, 0x76, 0x9a, 0x24, 0xab, 0xf6, 0xda, 0xee, 0xd3, 0x45, 0xe3,
+    0x7f, 0xd2, 0x67, 0x36, 0xd7, 0x76, 0x9a, 0x24, 0xdb, 0x33, 0x87, 0xf0,
+    0xe6, 0x77, 0x31, 0xd3, 0xaf, 0xc9, 0xf6, 0xb0, 0x4e, 0xbf, 0xfe, 0x03,
+    0xf3, 0x98, 0xa2, 0x8f, 0x2c, 0xe7, 0xc7, 0x54, 0x8f, 0xdf, 0x44, 0xd7,
+    0x6f, 0xc7, 0x5e, 0x98, 0x67, 0x3a, 0xc2, 0x75, 0xdf, 0xff, 0x9d, 0x5f,
+    0x1a, 0x9f, 0xe1, 0xf7, 0x71, 0xb3, 0x09, 0x98, 0x64, 0x23, 0x9c, 0x8b,
+    0x42, 0xdf, 0xd1, 0xaa, 0x1b, 0x9e, 0xc9, 0xcf, 0xe5, 0x58, 0x78, 0x86,
+    0x32, 0xe4, 0x8f, 0xc6, 0x68, 0xc5, 0x56, 0x59, 0xd8, 0xe8, 0xbc, 0x76,
+    0x08, 0x64, 0xff, 0x8d, 0x5e, 0xa2, 0x5f, 0x2b, 0xbc, 0xf2, 0x91, 0xa5,
+    0x3a, 0xee, 0x19, 0xd4, 0xac, 0xc4, 0x5c, 0x42, 0x93, 0x8d, 0xad, 0xbd,
+    0x25, 0x9e, 0x6b, 0x17, 0xf4, 0xa4, 0xbe, 0xab, 0xca, 0x23, 0x9a, 0xd7,
+    0xf8, 0xee, 0xd0, 0x4a, 0x2f, 0x36, 0x3a, 0x3e, 0xd2, 0x9a, 0x9e, 0xd8,
+    0xf5, 0xfd, 0x3e, 0x6a, 0xa9, 0x8f, 0x8c, 0x6b, 0x22, 0x7d, 0x56, 0xc0,
+    0x9e, 0xbd, 0x20, 0xf0, 0x5a, 0xf0, 0x3e, 0x14, 0xac, 0x76, 0x27, 0x16,
+    0xb8, 0xe5, 0xc2, 0xff, 0xa4, 0x14, 0x71, 0x57, 0x52, 0xf4,
 };
 
-static const unsigned kPreloadedHSTSBits = 259903;
+static const unsigned kPreloadedHSTSBits = 259854;
 
-static const unsigned kHSTSRootPosition = 259290;
+static const unsigned kHSTSRootPosition = 259241;
 
 #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index e891e3c..284a78a7 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -2205,7 +2205,6 @@
     { "name": "301.website", "include_subdomains": true, "mode": "force-https" },
     { "name": "alza.cz", "include_subdomains": true, "mode": "force-https" },
     { "name": "armytricka.cz", "include_subdomains": true, "mode": "force-https" },
-    { "name": "astaxi.net", "include_subdomains": true, "mode": "force-https" },
     { "name": "bradkovach.com", "include_subdomains": true, "mode": "force-https" },
     { "name": "crypto.graphics", "include_subdomains": true, "mode": "force-https" },
     { "name": "cryptography.io", "include_subdomains": true, "mode": "force-https" },
diff --git a/net/net.gyp b/net/net.gyp
index cd23f61..2b2b343 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -1415,6 +1415,8 @@
           'type': 'none',
           'variables': {
             'java_in_dir': '../net/test/android/javatests',
+            # TODO(jbudorick): remove chromium_code: 0 line once crbug.com/488192 is fixed.
+            'chromium_code': 0,
           },
           'dependencies': [
             'net_java',
@@ -1535,10 +1537,6 @@
                   '<(PRODUCT_DIR)/net_unittests_apk/assets/natives_blob.bin',
                   '<(PRODUCT_DIR)/net_unittests_apk/assets/snapshot_blob.bin',
                 ],
-                'inputs': [
-                  '<(PRODUCT_DIR)/natives_blob.bin',
-                  '<(PRODUCT_DIR)/snapshot_blob.bin',
-                ],
               }],
             ],
           },
diff --git a/net/net.gypi b/net/net.gypi
index 09750111..0ba77a87 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -505,8 +505,6 @@
       'base/upload_bytes_element_reader.h',
       'base/upload_data_stream.cc',
       'base/upload_data_stream.h',
-      'base/upload_disk_cache_entry_element_reader.cc',
-      'base/upload_disk_cache_entry_element_reader.h',
       'base/upload_element_reader.cc',
       'base/upload_element_reader.h',
       'base/upload_file_element_reader.cc',
@@ -1285,7 +1283,6 @@
       'base/static_cookie_policy_unittest.cc',
       'base/test_completion_callback_unittest.cc',
       'base/upload_bytes_element_reader_unittest.cc',
-      'base/upload_disk_cache_entry_element_reader_unittest.cc',
       'base/upload_file_element_reader_unittest.cc',
       'base/url_util_unittest.cc',
       'cert/cert_policy_enforcer_unittest.cc',
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index 3dfd3ce..62a332b 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -61,7 +61,7 @@
   RequestContext() : storage_(this) {
     ProxyConfig no_proxy;
     storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
-    storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier).Pass());
+    storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier));
     storage_.set_transport_security_state(
         make_scoped_ptr(new TransportSecurityState));
     storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy));
diff --git a/net/quic/crypto/aead_base_decrypter.h b/net/quic/crypto/aead_base_decrypter.h
index ce217c52..edb06d0 100644
--- a/net/quic/crypto/aead_base_decrypter.h
+++ b/net/quic/crypto/aead_base_decrypter.h
@@ -12,12 +12,6 @@
 #include "net/quic/crypto/scoped_evp_aead_ctx.h"
 #else
 #include <pkcs11t.h>
-#include <seccomon.h>
-typedef struct PK11SymKeyStr PK11SymKey;
-typedef SECStatus (*PK11_DecryptFunction)(
-      PK11SymKey* symKey, CK_MECHANISM_TYPE mechanism, SECItem* param,
-      unsigned char* out, unsigned int* outLen, unsigned int maxLen,
-      const unsigned char* enc, unsigned encLen);
 #endif
 
 namespace net {
@@ -32,7 +26,6 @@
                     size_t nonce_prefix_size);
 #else
   AeadBaseDecrypter(CK_MECHANISM_TYPE aead_mechanism,
-                    PK11_DecryptFunction pk11_decrypt,
                     size_t key_size,
                     size_t auth_tag_size,
                     size_t nonce_prefix_size);
@@ -63,11 +56,7 @@
     unsigned int len;
     union {
       CK_GCM_PARAMS gcm_params;
-#if !defined(USE_NSS_CERTS)
-      // USE_NSS_CERTS implies we are using system NSS rather than our copy of
-      // NSS. The system NSS <pkcs11n.h> header doesn't define this type yet.
       CK_NSS_AEAD_PARAMS nss_aead_params;
-#endif
     } data;
   };
 
@@ -82,7 +71,6 @@
   const EVP_AEAD* const aead_alg_;
 #else
   const CK_MECHANISM_TYPE aead_mechanism_;
-  const PK11_DecryptFunction pk11_decrypt_;
 #endif
   const size_t key_size_;
   const size_t auth_tag_size_;
diff --git a/net/quic/crypto/aead_base_decrypter_nss.cc b/net/quic/crypto/aead_base_decrypter_nss.cc
index 0cd99c8..806abe252 100644
--- a/net/quic/crypto/aead_base_decrypter_nss.cc
+++ b/net/quic/crypto/aead_base_decrypter_nss.cc
@@ -14,12 +14,10 @@
 namespace net {
 
 AeadBaseDecrypter::AeadBaseDecrypter(CK_MECHANISM_TYPE aead_mechanism,
-                                     PK11_DecryptFunction pk11_decrypt,
                                      size_t key_size,
                                      size_t auth_tag_size,
                                      size_t nonce_prefix_size)
     : aead_mechanism_(aead_mechanism),
-      pk11_decrypt_(pk11_decrypt),
       key_size_(key_size),
       auth_tag_size_(auth_tag_size),
       nonce_prefix_size_(nonce_prefix_size) {
@@ -77,20 +75,12 @@
   key_item.len = key_size_;
   PK11SlotInfo* slot = PK11_GetInternalSlot();
 
-  // TODO(wtc): For an AES-GCM key, the correct value for |key_mechanism| is
-  // CKM_AES_GCM, but because of NSS bug
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=853285, use CKM_AES_ECB as a
-  // workaround. Remove this when we require NSS 3.15.
-  CK_MECHANISM_TYPE key_mechanism = aead_mechanism_;
-  if (key_mechanism == CKM_AES_GCM) {
-    key_mechanism = CKM_AES_ECB;
-  }
-
   // The exact value of the |origin| argument doesn't matter to NSS as long as
   // it's not PK11_OriginFortezzaHack, so pass PK11_OriginUnwrap as a
   // placeholder.
-  crypto::ScopedPK11SymKey aead_key(PK11_ImportSymKey(
-      slot, key_mechanism, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, nullptr));
+  crypto::ScopedPK11SymKey aead_key(
+      PK11_ImportSymKey(slot, aead_mechanism_, PK11_OriginUnwrap, CKA_DECRYPT,
+                        &key_item, nullptr));
   PK11_FreeSlot(slot);
   slot = nullptr;
   if (!aead_key) {
@@ -108,11 +98,11 @@
   param.len = aead_params.len;
 
   unsigned int output_len;
-  if (pk11_decrypt_(aead_key.get(), aead_mechanism_, &param,
-                    reinterpret_cast<uint8*>(output), &output_len,
-                    max_output_length,
-                    reinterpret_cast<const unsigned char*>(ciphertext.data()),
-                    ciphertext.length()) != SECSuccess) {
+  if (PK11_Decrypt(aead_key.get(), aead_mechanism_, &param,
+                   reinterpret_cast<uint8*>(output), &output_len,
+                   max_output_length,
+                   reinterpret_cast<const unsigned char*>(ciphertext.data()),
+                   ciphertext.length()) != SECSuccess) {
     return false;
   }
 
diff --git a/net/quic/crypto/aead_base_encrypter.h b/net/quic/crypto/aead_base_encrypter.h
index 869cc43..25bef1d 100644
--- a/net/quic/crypto/aead_base_encrypter.h
+++ b/net/quic/crypto/aead_base_encrypter.h
@@ -12,12 +12,6 @@
 #include "net/quic/crypto/scoped_evp_aead_ctx.h"
 #else
 #include <pkcs11t.h>
-#include <seccomon.h>
-typedef struct PK11SymKeyStr PK11SymKey;
-typedef SECStatus (*PK11_EncryptFunction)(
-    PK11SymKey* symKey, CK_MECHANISM_TYPE mechanism, SECItem* param,
-    unsigned char* out, unsigned int* outLen, unsigned int maxLen,
-    const unsigned char* data, unsigned int dataLen);
 #endif
 
 namespace net {
@@ -32,7 +26,6 @@
                     size_t nonce_prefix_size);
 #else
   AeadBaseEncrypter(CK_MECHANISM_TYPE aead_mechanism,
-                    PK11_EncryptFunction pk11_encrypt,
                     size_t key_size,
                     size_t auth_tag_size,
                     size_t nonce_prefix_size);
@@ -74,11 +67,7 @@
     unsigned int len;
     union {
       CK_GCM_PARAMS gcm_params;
-#if !defined(USE_NSS_CERTS)
-      // USE_NSS_CERTS implies we are using system NSS rather than our copy of
-      // NSS. The system NSS <pkcs11n.h> header doesn't define this type yet.
       CK_NSS_AEAD_PARAMS nss_aead_params;
-#endif
     } data;
   };
 
@@ -93,7 +82,6 @@
   const EVP_AEAD* const aead_alg_;
 #else
   const CK_MECHANISM_TYPE aead_mechanism_;
-  const PK11_EncryptFunction pk11_encrypt_;
 #endif
   const size_t key_size_;
   const size_t auth_tag_size_;
diff --git a/net/quic/crypto/aead_base_encrypter_nss.cc b/net/quic/crypto/aead_base_encrypter_nss.cc
index 22eff87c..37a5c89 100644
--- a/net/quic/crypto/aead_base_encrypter_nss.cc
+++ b/net/quic/crypto/aead_base_encrypter_nss.cc
@@ -14,12 +14,10 @@
 namespace net {
 
 AeadBaseEncrypter::AeadBaseEncrypter(CK_MECHANISM_TYPE aead_mechanism,
-                                     PK11_EncryptFunction pk11_encrypt,
                                      size_t key_size,
                                      size_t auth_tag_size,
                                      size_t nonce_prefix_size)
     : aead_mechanism_(aead_mechanism),
-      pk11_encrypt_(pk11_encrypt),
       key_size_(key_size),
       auth_tag_size_(auth_tag_size),
       nonce_prefix_size_(nonce_prefix_size) {
@@ -64,20 +62,12 @@
   key_item.len = key_size_;
   PK11SlotInfo* slot = PK11_GetInternalSlot();
 
-  // TODO(wtc): For an AES-GCM key, the correct value for |key_mechanism| is
-  // CKM_AES_GCM, but because of NSS bug
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=853285, use CKM_AES_ECB as a
-  // workaround. Remove this when we require NSS 3.15.
-  CK_MECHANISM_TYPE key_mechanism = aead_mechanism_;
-  if (key_mechanism == CKM_AES_GCM) {
-    key_mechanism = CKM_AES_ECB;
-  }
-
   // The exact value of the |origin| argument doesn't matter to NSS as long as
   // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a
   // placeholder.
-  crypto::ScopedPK11SymKey aead_key(PK11_ImportSymKey(
-      slot, key_mechanism, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, nullptr));
+  crypto::ScopedPK11SymKey aead_key(
+      PK11_ImportSymKey(slot, aead_mechanism_, PK11_OriginUnwrap, CKA_ENCRYPT,
+                        &key_item, nullptr));
   PK11_FreeSlot(slot);
   slot = nullptr;
   if (!aead_key) {
@@ -94,11 +84,11 @@
   param.len = aead_params.len;
 
   unsigned int output_len;
-  if (pk11_encrypt_(aead_key.get(), aead_mechanism_, &param,
-                    output, &output_len, ciphertext_size,
-                    reinterpret_cast<const unsigned char*>(plaintext.data()),
-                    plaintext.size()) != SECSuccess) {
-    DVLOG(1) << "pk11_encrypt_ failed";
+  if (PK11_Encrypt(aead_key.get(), aead_mechanism_, &param, output, &output_len,
+                   ciphertext_size,
+                   reinterpret_cast<const unsigned char*>(plaintext.data()),
+                   plaintext.size()) != SECSuccess) {
+    DVLOG(1) << "PK11_Encrypt failed";
     return false;
   }
 
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
index fd144560..aa7e17a 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
@@ -7,8 +7,6 @@
 #include <pk11pub.h>
 #include <secerr.h>
 
-#include "crypto/aes_128_gcm_helpers_nss.h"
-
 using base::StringPiece;
 
 namespace net {
@@ -18,23 +16,10 @@
 const size_t kKeySize = 16;
 const size_t kNoncePrefixSize = 4;
 
-SECStatus My_Decrypt(PK11SymKey* key,
-                     CK_MECHANISM_TYPE mechanism,
-                     SECItem* param,
-                     unsigned char* out,
-                     unsigned int* out_len,
-                     unsigned int max_len,
-                     const unsigned char* data,
-                     unsigned int data_len) {
-  return crypto::PK11DecryptHelper(key, mechanism, param, out, out_len, max_len,
-                                   data, data_len);
-}
-
 }  // namespace
 
 Aes128Gcm12Decrypter::Aes128Gcm12Decrypter()
-    : AeadBaseDecrypter(CKM_AES_GCM, My_Decrypt, kKeySize, kAuthTagSize,
-                        kNoncePrefixSize) {
+    : AeadBaseDecrypter(CKM_AES_GCM, kKeySize, kAuthTagSize, kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
index bc9b519e..847f29dc 100644
--- a/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
+++ b/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
@@ -7,8 +7,6 @@
 #include <pk11pub.h>
 #include <secerr.h>
 
-#include "crypto/aes_128_gcm_helpers_nss.h"
-
 using base::StringPiece;
 
 namespace net {
@@ -18,23 +16,10 @@
 const size_t kKeySize = 16;
 const size_t kNoncePrefixSize = 4;
 
-SECStatus My_Encrypt(PK11SymKey* key,
-                     CK_MECHANISM_TYPE mechanism,
-                     SECItem* param,
-                     unsigned char* out,
-                     unsigned int* out_len,
-                     unsigned int max_len,
-                     const unsigned char* data,
-                     unsigned int data_len) {
-  return crypto::PK11EncryptHelper(key, mechanism, param, out, out_len, max_len,
-                                   data, data_len);
-}
-
 }  // namespace
 
 Aes128Gcm12Encrypter::Aes128Gcm12Encrypter()
-    : AeadBaseEncrypter(CKM_AES_GCM, My_Encrypt, kKeySize, kAuthTagSize,
-                        kNoncePrefixSize) {
+    : AeadBaseEncrypter(CKM_AES_GCM, kKeySize, kAuthTagSize, kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
index 44f52c4..d69097e4 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
+++ b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
@@ -6,8 +6,6 @@
 
 #include <pk11pub.h>
 
-#include "base/logging.h"
-
 using base::StringPiece;
 
 namespace net {
@@ -19,36 +17,11 @@
 
 }  // namespace
 
-#if defined(USE_NSS_CERTS)
-
-// System NSS doesn't support ChaCha20+Poly1305 yet.
-
 ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter()
-    : AeadBaseDecrypter(CKM_INVALID_MECHANISM, nullptr, kKeySize,
-                        kAuthTagSize, kNoncePrefixSize) {
-  NOTIMPLEMENTED();
-}
-
-ChaCha20Poly1305Decrypter::~ChaCha20Poly1305Decrypter() {}
-
-// static
-bool ChaCha20Poly1305Decrypter::IsSupported() {
-  return false;
-}
-
-void ChaCha20Poly1305Decrypter::FillAeadParams(
-    StringPiece nonce,
-    const StringPiece& associated_data,
-    size_t auth_tag_size,
-    AeadParams* aead_params) const {
-  NOTIMPLEMENTED();
-}
-
-#else  // defined(USE_NSS_CERTS)
-
-ChaCha20Poly1305Decrypter::ChaCha20Poly1305Decrypter()
-    : AeadBaseDecrypter(CKM_NSS_CHACHA20_POLY1305, PK11_Decrypt, kKeySize,
-                        kAuthTagSize, kNoncePrefixSize) {
+    : AeadBaseDecrypter(CKM_NSS_CHACHA20_POLY1305,
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
@@ -77,8 +50,6 @@
   nss_aead_params->ulTagLen = auth_tag_size;
 }
 
-#endif  // defined(USE_NSS_CERTS)
-
 const char* ChaCha20Poly1305Decrypter::cipher_name() const {
   // TODO(rtenneti): Use TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 instead of
   // hard coded string.
diff --git a/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc
index 2c51da83..cdb21dd 100644
--- a/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc
+++ b/net/quic/crypto/chacha20_poly1305_encrypter_nss.cc
@@ -6,8 +6,6 @@
 
 #include <pk11pub.h>
 
-#include "base/logging.h"
-
 using base::StringPiece;
 
 namespace net {
@@ -19,35 +17,11 @@
 
 }  // namespace
 
-#if defined(USE_NSS_CERTS)
-
-// System NSS doesn't support ChaCha20+Poly1305 yet.
-
 ChaCha20Poly1305Encrypter::ChaCha20Poly1305Encrypter()
-    : AeadBaseEncrypter(CKM_INVALID_MECHANISM, nullptr, kKeySize,
-                        kAuthTagSize, kNoncePrefixSize) {
-  NOTIMPLEMENTED();
-}
-
-ChaCha20Poly1305Encrypter::~ChaCha20Poly1305Encrypter() {}
-
-// static
-bool ChaCha20Poly1305Encrypter::IsSupported() {
-  return false;
-}
-
-void ChaCha20Poly1305Encrypter::FillAeadParams(StringPiece nonce,
-                                               StringPiece associated_data,
-                                               size_t auth_tag_size,
-                                               AeadParams* aead_params) const {
-  NOTIMPLEMENTED();
-}
-
-#else  // defined(USE_NSS_CERTS)
-
-ChaCha20Poly1305Encrypter::ChaCha20Poly1305Encrypter()
-    : AeadBaseEncrypter(CKM_NSS_CHACHA20_POLY1305, PK11_Encrypt, kKeySize,
-                        kAuthTagSize, kNoncePrefixSize) {
+    : AeadBaseEncrypter(CKM_NSS_CHACHA20_POLY1305,
+                        kKeySize,
+                        kAuthTagSize,
+                        kNoncePrefixSize) {
   static_assert(kKeySize <= kMaxKeySize, "key size too big");
   static_assert(kNoncePrefixSize <= kMaxNoncePrefixSize,
                 "nonce prefix size too big");
@@ -75,6 +49,4 @@
   nss_aead_params->ulTagLen = auth_tag_size;
 }
 
-#endif  // defined(USE_NSS_CERTS)
-
 }  // namespace net
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 0d83e0b..1abab6b 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -161,9 +161,12 @@
     scoped_ptr<DatagramClientSocket> socket,
     QuicStreamFactory* stream_factory,
     QuicCryptoClientStreamFactory* crypto_client_stream_factory,
+    QuicClock* clock,
     TransportSecurityState* transport_security_state,
     scoped_ptr<QuicServerInfo> server_info,
     const QuicServerId& server_id,
+    int yield_after_packets,
+    QuicTime::Delta yield_after_duration,
     int cert_verify_flags,
     const QuicConfig& config,
     QuicCryptoClientConfig* crypto_config,
@@ -182,7 +185,12 @@
       num_total_streams_(0),
       task_runner_(task_runner),
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
-      packet_reader_(socket_.get(), this, net_log_),
+      packet_reader_(socket_.get(),
+                     clock,
+                     this,
+                     yield_after_packets,
+                     yield_after_duration,
+                     net_log_),
       dns_resolution_end_time_(dns_resolution_end_time),
       logger_(new QuicConnectionLogger(this,
                                        connection_description,
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index d71e21f..0a1ac86 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -25,6 +25,7 @@
 #include "net/quic/quic_packet_reader.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_reliable_client_stream.h"
+#include "net/quic/quic_time.h"
 
 namespace net {
 
@@ -111,9 +112,12 @@
       scoped_ptr<DatagramClientSocket> socket,
       QuicStreamFactory* stream_factory,
       QuicCryptoClientStreamFactory* crypto_client_stream_factory,
+      QuicClock* clock,
       TransportSecurityState* transport_security_state,
       scoped_ptr<QuicServerInfo> server_info,
       const QuicServerId& server_id,
+      int yield_after_packets,
+      QuicTime::Delta yield_after_duration,
       int cert_verify_flags,
       const QuicConfig& config,
       QuicCryptoClientConfig* crypto_config,
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index dee5e74dd..f22ccde4 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -22,6 +22,7 @@
 #include "net/quic/crypto/quic_decrypter.h"
 #include "net/quic/crypto/quic_encrypter.h"
 #include "net/quic/crypto/quic_server_info.h"
+#include "net/quic/quic_packet_reader.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_chromium_client_session_peer.h"
 #include "net/quic/test_tools/quic_spdy_session_peer.h"
@@ -51,12 +52,16 @@
                  GetSocket().Pass(),
                  /*stream_factory=*/nullptr,
                  /*crypto_client_stream_factory=*/nullptr,
+                 &clock_,
                  &transport_security_state_,
                  make_scoped_ptr((QuicServerInfo*)nullptr),
                  QuicServerId(kServerHostname,
                               kServerPort,
                               /*is_secure=*/false,
                               PRIVACY_MODE_DISABLED),
+                 kQuicYieldAfterPacketsRead,
+                 QuicTime::Delta::FromMilliseconds(
+                     kQuicYieldAfterDurationMilliseconds),
                  /*cert_verify_flags=*/0,
                  DefaultQuicConfig(),
                  &crypto_config_,
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc
index 0229034..86bb9cd 100644
--- a/net/quic/quic_end_to_end_unittest.cc
+++ b/net/quic/quic_end_to_end_unittest.cc
@@ -272,7 +272,13 @@
   CheckResponse(consumer, "HTTP/1.1 200 OK", kResponseBody);
 }
 
-TEST_F(QuicEndToEndTest, UberTest) {
+// crbug.com/536845
+#if defined(THREAD_SANITIZER)
+#define MAYBE_UberTest DISABLED_UberTest
+#else
+#define MAYBE_UberTest UberTest
+#endif
+TEST_F(QuicEndToEndTest, MAYBE_UberTest) {
   // FLAGS_fake_packet_loss_percentage = 30;
 
   const char kResponseBody[] = "some really big response body";
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 8d18dc5..9245a13 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -282,6 +282,14 @@
   NOTIMPLEMENTED();
 }
 
+bool QuicHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+  if (!session_)
+    return false;
+
+  *endpoint = session_->peer_address();
+  return true;
+}
+
 void QuicHttpStream::Drain(HttpNetworkSession* session) {
   NOTREACHED();
   Close(false);
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h
index 668b502..f7605ca 100644
--- a/net/quic/quic_http_stream.h
+++ b/net/quic/quic_http_stream.h
@@ -58,6 +58,7 @@
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
   void GetSSLInfo(SSLInfo* ssl_info) override;
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   void Drain(HttpNetworkSession* session) override;
   void SetPriority(RequestPriority priority) override;
 
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 6914674d..deaf7b80 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -27,6 +27,7 @@
 #include "net/quic/quic_connection_helper.h"
 #include "net/quic/quic_default_packet_writer.h"
 #include "net/quic/quic_http_utils.h"
+#include "net/quic/quic_packet_reader.h"
 #include "net/quic/quic_reliable_client_stream.h"
 #include "net/quic/quic_write_blocked_list.h"
 #include "net/quic/spdy_utils.h"
@@ -218,10 +219,12 @@
     connection_->SetSendAlgorithm(send_algorithm_);
     session_.reset(new QuicChromiumClientSession(
         connection_, scoped_ptr<DatagramClientSocket>(socket),
-        /*stream_factory=*/nullptr, &crypto_client_stream_factory_,
+        /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
         &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr),
         QuicServerId(kDefaultServerHostName, kDefaultServerPort,
                      /*is_secure=*/false, PRIVACY_MODE_DISABLED),
+        kQuicYieldAfterPacketsRead,
+        QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
         /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_,
         "CONNECTION_UNKNOWN", base::TimeTicks::Now(),
         base::ThreadTaskRunnerHandle::Get().get(),
diff --git a/net/quic/quic_packet_reader.cc b/net/quic/quic_packet_reader.cc
index c58a51fa..7b90dc9 100644
--- a/net/quic/quic_packet_reader.cc
+++ b/net/quic/quic_packet_reader.cc
@@ -9,20 +9,28 @@
 #include "base/single_thread_task_runner.h"
 #include "base/thread_task_runner_handle.h"
 #include "net/base/net_errors.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_time.h"
 
 namespace net {
 
 QuicPacketReader::QuicPacketReader(DatagramClientSocket* socket,
+                                   QuicClock* clock,
                                    Visitor* visitor,
+                                   int yield_after_packets,
+                                   QuicTime::Delta yield_after_duration,
                                    const BoundNetLog& net_log)
     : socket_(socket),
       visitor_(visitor),
       read_pending_(false),
       num_packets_read_(0),
+      clock_(clock),
+      yield_after_packets_(yield_after_packets),
+      yield_after_duration_(yield_after_duration),
+      yield_after_(QuicTime::Infinite()),
       read_buffer_(new IOBufferWithSize(static_cast<size_t>(kMaxPacketSize))),
       net_log_(net_log),
-      weak_factory_(this) {
-}
+      weak_factory_(this) {}
 
 QuicPacketReader::~QuicPacketReader() {
 }
@@ -31,6 +39,9 @@
   if (read_pending_)
     return;
 
+  if (num_packets_read_ == 0)
+    yield_after_ = clock_->Now().Add(yield_after_duration_);
+
   DCHECK(socket_);
   read_pending_ = true;
   int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(),
@@ -42,7 +53,8 @@
     return;
   }
 
-  if (++num_packets_read_ > 32) {
+  if (++num_packets_read_ > yield_after_packets_ ||
+      clock_->Now() > yield_after_) {
     num_packets_read_ = 0;
     // Data was read, process it.
     // Schedule the work through the message loop to 1) prevent infinite
diff --git a/net/quic/quic_packet_reader.h b/net/quic/quic_packet_reader.h
index abd3e80..02c38774 100644
--- a/net/quic/quic_packet_reader.h
+++ b/net/quic/quic_packet_reader.h
@@ -15,6 +15,15 @@
 
 namespace net {
 
+class QuicClock;
+class QuicTime;
+
+// If more than this many packets have been read or more than that many
+// milliseconds have passed, QuicPacketReader::StartReading() yields by doing a
+// QuicPacketReader::PostTask().
+const int kQuicYieldAfterPacketsRead = 32;
+const int kQuicYieldAfterDurationMilliseconds = 20;
+
 class NET_EXPORT_PRIVATE QuicPacketReader {
  public:
   class NET_EXPORT_PRIVATE Visitor {
@@ -27,7 +36,10 @@
   };
 
   QuicPacketReader(DatagramClientSocket* socket,
+                   QuicClock* clock,
                    Visitor* visitor,
+                   int yield_after_packets,
+                   QuicTime::Delta yield_after_duration,
                    const BoundNetLog& net_log);
   virtual ~QuicPacketReader();
 
@@ -43,6 +55,10 @@
   Visitor* visitor_;
   bool read_pending_;
   int num_packets_read_;
+  QuicClock* clock_;  // Owned by QuicStreamFactory
+  int yield_after_packets_;
+  QuicTime::Delta yield_after_duration_;
+  QuicTime yield_after_;
   scoped_refptr<IOBufferWithSize> read_buffer_;
   BoundNetLog net_log_;
 
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index bf6d977..62fd664 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -38,6 +38,7 @@
 #include "net/quic/quic_default_packet_writer.h"
 #include "net/quic/quic_flags.h"
 #include "net/quic/quic_http_stream.h"
+#include "net/quic/quic_packet_reader.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_server_id.h"
 #include "net/socket/client_socket_factory.h"
@@ -631,6 +632,9 @@
           threshold_public_resets_post_handshake),
       socket_receive_buffer_size_(socket_receive_buffer_size),
       delay_tcp_race_(delay_tcp_race),
+      yield_after_packets_(kQuicYieldAfterPacketsRead),
+      yield_after_duration_(QuicTime::Delta::FromMilliseconds(
+          kQuicYieldAfterDurationMilliseconds)),
       port_seed_(random_generator_->RandUint64()),
       check_persisted_supports_quic_(true),
       quic_supported_servers_at_startup_initialzied_(false),
@@ -1288,10 +1292,10 @@
 
   *session = new QuicChromiumClientSession(
       connection, socket.Pass(), this, quic_crypto_client_stream_factory_,
-      transport_security_state_, server_info.Pass(), server_id,
-      cert_verify_flags, config, &crypto_config_,
-      network_connection_.GetDescription(), dns_resolution_end_time,
-      base::ThreadTaskRunnerHandle::Get().get(),
+      clock_.get(), transport_security_state_, server_info.Pass(), server_id,
+      yield_after_packets_, yield_after_duration_, cert_verify_flags, config,
+      &crypto_config_, network_connection_.GetDescription(),
+      dns_resolution_end_time, base::ThreadTaskRunnerHandle::Get().get(),
       socket_performance_watcher.Pass(), net_log.net_log());
 
   all_sessions_[*session] = server_id;  // owning pointer
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 558e5341..162607b 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -443,6 +443,12 @@
   // Set if we do want to delay TCP connection when it is racing with QUIC.
   bool delay_tcp_race_;
 
+  // If more than |yield_after_packets_| packets have been read or more than
+  // |yield_after_duration_| time has passed, then
+  // QuicPacketReader::StartReading() yields by doing a PostTask().
+  int yield_after_packets_;
+  QuicTime::Delta yield_after_duration_;
+
   // Each profile will (probably) have a unique port_seed_ value.  This value
   // is used to help seed a pseudo-random number generator (PortSuggester) so
   // that we consistently (within this profile) suggest the same ephemeral
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 36744a15..4209bc47 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -29,6 +29,7 @@
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "net/quic/test_tools/test_task_runner.h"
 #include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_session_test_util.h"
 #include "net/spdy/spdy_test_utils.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
@@ -157,6 +158,16 @@
     factory->delay_tcp_race_ = delay_tcp_race;
   }
 
+  static void SetYieldAfterPackets(QuicStreamFactory* factory,
+                                   int yield_after_packets) {
+    factory->yield_after_packets_ = yield_after_packets;
+  }
+
+  static void SetYieldAfterDuration(QuicStreamFactory* factory,
+                                    QuicTime::Delta yield_after_duration) {
+    factory->yield_after_duration_ = yield_after_duration;
+  }
+
   static void SetHttpServerProperties(
       QuicStreamFactory* factory,
       base::WeakPtr<HttpServerProperties> http_server_properties) {
@@ -363,6 +374,11 @@
     return port;
   }
 
+  scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
+      QuicPacketNumber num) {
+    return maker_.MakeConnectionClosePacket(num);
+  }
+
   scoped_ptr<QuicEncryptedPacket> ConstructRstPacket() {
     QuicStreamId stream_id = kClientDataStreamId1;
     return maker_.MakeRstPacket(
@@ -2666,5 +2682,94 @@
       QuicStreamFactoryPeer::SupportsQuicAtStartUp(&factory_, host_port_pair_));
 }
 
+TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
+  QuicStreamFactoryPeer::SetYieldAfterPackets(&factory_, 0);
+
+  scoped_ptr<QuicEncryptedPacket> close_packet(
+      ConstructConnectionClosePacket(0));
+  std::vector<MockRead> reads;
+  reads.push_back(
+      MockRead(SYNCHRONOUS, close_packet->data(), close_packet->length(), 0));
+  reads.push_back(MockRead(ASYNC, OK, 1));
+  DeterministicSocketData socket_data(&reads[0], reads.size(), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  // Set up the TaskObserver to verify QuicPacketReader::StartReading posts a
+  // task.
+  // TODO(rtenneti): Change SpdySessionTestTaskObserver to NetTestTaskObserver??
+  SpdySessionTestTaskObserver observer("quic_packet_reader.cc", "StartReading");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK, request.Request(host_port_pair_, is_https_, privacy_mode_,
+                                /*cert_verify_flags=*/0, host_port_pair_.host(),
+                                "GET", net_log_, callback_.callback()));
+
+  // Call run_loop so that QuicPacketReader::OnReadComplete() gets called.
+  base::RunLoop run_loop;
+  run_loop.RunUntilIdle();
+
+  // Verify task that the observer's executed_count is 1, which indicates
+  // QuicPacketReader::StartReading() has posted only one task and yielded the
+  // read.
+  EXPECT_EQ(1u, observer.executed_count());
+
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
+TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
+  QuicStreamFactoryPeer::SetYieldAfterDuration(
+      &factory_, QuicTime::Delta::FromMilliseconds(-1));
+
+  scoped_ptr<QuicEncryptedPacket> close_packet(
+      ConstructConnectionClosePacket(0));
+  std::vector<MockRead> reads;
+  reads.push_back(
+      MockRead(SYNCHRONOUS, close_packet->data(), close_packet->length(), 0));
+  reads.push_back(MockRead(ASYNC, OK, 1));
+  DeterministicSocketData socket_data(&reads[0], reads.size(), nullptr, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  // Set up the TaskObserver to verify QuicPacketReader::StartReading posts a
+  // task.
+  // TODO(rtenneti): Change SpdySessionTestTaskObserver to NetTestTaskObserver??
+  SpdySessionTestTaskObserver observer("quic_packet_reader.cc", "StartReading");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK, request.Request(host_port_pair_, is_https_, privacy_mode_,
+                                /*cert_verify_flags=*/0, host_port_pair_.host(),
+                                "GET", net_log_, callback_.callback()));
+
+  // Call run_loop so that QuicPacketReader::OnReadComplete() gets called.
+  base::RunLoop run_loop;
+  run_loop.RunUntilIdle();
+
+  // Verify task that the observer's executed_count is 1, which indicates
+  // QuicPacketReader::StartReading() has posted only one task and yielded the
+  // read.
+  EXPECT_EQ(1u, observer.executed_count());
+
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.AllReadDataConsumed());
+  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index cb5d851..e0bc81d5 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -5,48 +5,28 @@
 #include "net/socket/client_socket_factory.h"
 
 #include "base/lazy_instance.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "build/build_config.h"
 #include "net/cert/cert_database.h"
 #include "net/socket/client_socket_handle.h"
-#if defined(USE_OPENSSL)
-#include "net/socket/ssl_client_socket_openssl.h"
-#elif defined(USE_NSS_CERTS) || defined(OS_MACOSX) || defined(OS_WIN)
-#include "net/socket/ssl_client_socket_nss.h"
-#endif
 #include "net/socket/tcp_client_socket.h"
 #include "net/udp/udp_client_socket.h"
 
+#if defined(USE_OPENSSL)
+#include "net/socket/ssl_client_socket_openssl.h"
+#else
+#include "net/socket/ssl_client_socket_nss.h"
+#endif
+
 namespace net {
 
 class X509Certificate;
 
 namespace {
 
-// ChromeOS and Linux may require interaction with smart cards or TPMs, which
-// may cause NSS functions to block for upwards of several seconds. To avoid
-// blocking all activity on the current task runner, such as network or IPC
-// traffic, run NSS SSL functions on a dedicated thread.
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
-bool g_use_dedicated_nss_thread = true;
-#else
-bool g_use_dedicated_nss_thread = false;
-#endif
-
 class DefaultClientSocketFactory : public ClientSocketFactory,
                                    public CertDatabase::Observer {
  public:
   DefaultClientSocketFactory() {
-    if (g_use_dedicated_nss_thread) {
-      // Use a single thread for the worker pool.
-      worker_pool_ = new base::SequencedWorkerPool(1, "NSS SSL Thread");
-      nss_thread_task_runner_ =
-          worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior(
-              worker_pool_->GetSequenceToken(),
-              base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
-    }
-
     CertDatabase::GetInstance()->AddObserver(this);
   }
 
@@ -89,42 +69,17 @@
       const HostPortPair& host_and_port,
       const SSLConfig& ssl_config,
       const SSLClientSocketContext& context) override {
-    // nss_thread_task_runner_ may be NULL if g_use_dedicated_nss_thread is
-    // false or if the dedicated NSS thread failed to start. If so, cause NSS
-    // functions to execute on the current task runner.
-    //
-    // Note: The current task runner is obtained on each call due to unit
-    // tests, which may create and tear down the current thread's TaskRunner
-    // between each test. Because the DefaultClientSocketFactory is leaky, it
-    // may span multiple tests, and thus the current task runner may change
-    // from call to call.
-    scoped_refptr<base::SequencedTaskRunner> nss_task_runner(
-        nss_thread_task_runner_);
-    if (!nss_task_runner.get())
-      nss_task_runner = base::ThreadTaskRunnerHandle::Get();
-
 #if defined(USE_OPENSSL)
     return scoped_ptr<SSLClientSocket>(
         new SSLClientSocketOpenSSL(transport_socket.Pass(), host_and_port,
                                    ssl_config, context));
-#elif defined(USE_NSS_CERTS) || defined(OS_MACOSX) || defined(OS_WIN)
-    return scoped_ptr<SSLClientSocket>(
-        new SSLClientSocketNSS(nss_task_runner.get(),
-                               transport_socket.Pass(),
-                               host_and_port,
-                               ssl_config,
-                               context));
 #else
-    NOTIMPLEMENTED();
-    return scoped_ptr<SSLClientSocket>();
+    return scoped_ptr<SSLClientSocket>(new SSLClientSocketNSS(
+        transport_socket.Pass(), host_and_port, ssl_config, context));
 #endif
   }
 
   void ClearSSLSessionCache() override { SSLClientSocket::ClearSessionCache(); }
-
- private:
-  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
-  scoped_refptr<base::SequencedTaskRunner> nss_thread_task_runner_;
 };
 
 static base::LazyInstance<DefaultClientSocketFactory>::Leaky
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 7820cf9..3066171 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -18,6 +18,7 @@
 #include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
+#include "net/ssl/ssl_config.h"
 
 namespace net {
 
@@ -127,8 +128,7 @@
     // should be the same for all connections, whereas version_max may
     // change for version fallbacks.
     std::string prefix = "ssl/";
-    if (ssl_config_for_origin.version_max !=
-        SSLClientSocket::GetMaxSupportedSSLVersion()) {
+    if (ssl_config_for_origin.version_max != kDefaultSSLVersionMax) {
       switch (ssl_config_for_origin.version_max) {
         case SSL_PROTOCOL_VERSION_TLS1_2:
           prefix = "ssl(max:3.3)/";
diff --git a/net/socket/next_proto.cc b/net/socket/next_proto.cc
index 0a80372..0285044 100644
--- a/net/socket/next_proto.cc
+++ b/net/socket/next_proto.cc
@@ -40,4 +40,15 @@
          next_proto <= kProtoSPDYMaximumVersion;
 }
 
+void DisableHTTP2(NextProtoVector* next_protos) {
+  for (NextProtoVector::iterator it = next_protos->begin();
+       it != next_protos->end();) {
+    if (*it == kProtoHTTP2) {
+      it = next_protos->erase(it);
+      continue;
+    }
+    ++it;
+  }
+}
+
 }  // namespace net
diff --git a/net/socket/next_proto.h b/net/socket/next_proto.h
index 62cac9a8..06f31ba 100644
--- a/net/socket/next_proto.h
+++ b/net/socket/next_proto.h
@@ -58,6 +58,9 @@
 // Returns true if |next_proto| is a version of SPDY or HTTP/2.
 bool NextProtoIsSPDY(NextProto next_proto);
 
+// Remove HTTP/2 from |next_protos|.
+NET_EXPORT void DisableHTTP2(NextProtoVector* next_protos);
+
 }  // namespace net
 
 #endif  // NET_SOCKET_NEXT_PROTO_H_
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 1d5da044..1436b14 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -1007,19 +1007,17 @@
 }
 
 void MockTCPClientSocket::GetConnectionAttempts(ConnectionAttempts* out) const {
-  int connect_result = data_->connect_data().result;
-
-  out->clear();
-  if (connected_ && connect_result != OK)
-    out->push_back(ConnectionAttempt(addresses_[0], connect_result));
+  *out = connection_attempts_;
 }
 
 void MockTCPClientSocket::ClearConnectionAttempts() {
-  NOTIMPLEMENTED();
+  connection_attempts_.clear();
 }
 
-void MockTCPClientSocket::AddConnectionAttempts(const ConnectionAttempts& in) {
-  NOTIMPLEMENTED();
+void MockTCPClientSocket::AddConnectionAttempts(
+    const ConnectionAttempts& attempts) {
+  connection_attempts_.insert(connection_attempts_.begin(), attempts.begin(),
+                              attempts.end());
 }
 
 int MockTCPClientSocket::Connect(const CompletionCallback& callback) {
@@ -1027,18 +1025,29 @@
     return OK;
   connected_ = true;
   peer_closed_connection_ = false;
-  if (data_->connect_data().mode == ASYNC) {
-    if (data_->connect_data().result == ERR_IO_PENDING)
-      pending_read_callback_ = callback;
-    else
-      RunCallbackAsync(callback, data_->connect_data().result);
-    return ERR_IO_PENDING;
+
+  int result = data_->connect_data().result;
+  IoMode mode = data_->connect_data().mode;
+
+  if (result != OK && result != ERR_IO_PENDING) {
+    IPEndPoint address;
+    if (GetPeerAddress(&address) == OK)
+      connection_attempts_.push_back(ConnectionAttempt(address, result));
   }
-  return data_->connect_data().result;
+
+  if (mode == SYNCHRONOUS)
+    return result;
+
+  if (result == ERR_IO_PENDING)
+    pending_connect_callback_ = callback;
+  else
+    RunCallbackAsync(callback, result);
+  return ERR_IO_PENDING;
 }
 
 void MockTCPClientSocket::Disconnect() {
   MockClientSocket::Disconnect();
+  pending_connect_callback_.Reset();
   pending_read_callback_.Reset();
 }
 
@@ -1102,7 +1111,7 @@
 }
 
 void MockTCPClientSocket::OnConnectComplete(const MockConnect& data) {
-  CompletionCallback callback = pending_read_callback_;
+  CompletionCallback callback = pending_connect_callback_;
   RunCallback(callback, data.result);
 }
 
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 523e9ac..6b966df 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -30,6 +30,7 @@
 #include "net/log/net_log.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/client_socket_handle.h"
+#include "net/socket/connection_attempts.h"
 #include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/ssl_client_socket_pool.h"
@@ -734,10 +735,13 @@
   // While an asynchronous read is pending, we save our user-buffer state.
   scoped_refptr<IOBuffer> pending_read_buf_;
   int pending_read_buf_len_;
+  CompletionCallback pending_connect_callback_;
   CompletionCallback pending_read_callback_;
   CompletionCallback pending_write_callback_;
   bool was_used_to_convey_data_;
 
+  ConnectionAttempts connection_attempts_;
+
   DISALLOW_COPY_AND_ASSIGN(MockTCPClientSocket);
 };
 
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index 8f88b31..3472fd0 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -189,13 +189,9 @@
 
 // static
 std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
-    const NextProtoVector& next_protos,
-    bool can_advertise_http2) {
+    const NextProtoVector& next_protos) {
   std::vector<uint8_t> wire_protos;
   for (const NextProto next_proto : next_protos) {
-    if (!can_advertise_http2 && next_proto == kProtoHTTP2) {
-      continue;
-    }
     const std::string proto = NextProtoToString(next_proto);
     if (proto.size() > 255) {
       LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << proto;
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index 6780060..1d38048d0 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -122,10 +122,6 @@
   // sessions.
   static void ClearSessionCache();
 
-  // Get the maximum SSL version supported by the underlying library and
-  // cryptographic implementation.
-  static uint16 GetMaxSupportedSSLVersion();
-
   // Returns the ChannelIDService used by this socket, or NULL if
   // channel ids are not supported.
   virtual ChannelIDService* GetChannelIDService() const = 0;
@@ -178,12 +174,10 @@
   // inadequate TLS version.
   static bool IsTLSVersionAdequateForHTTP2(const SSLConfig& ssl_config);
 
-  // Serializes |next_protos| in the wire format for ALPN: protocols are listed
-  // in order, each prefixed by a one-byte length.  Any HTTP/2 protocols in
-  // |next_protos| are ignored if |can_advertise_http2| is false.
+  // Serialize |next_protos| in the wire format for ALPN and NPN: protocols are
+  // listed in order, each prefixed by a one-byte length.
   static std::vector<uint8_t> SerializeNextProtos(
-      const NextProtoVector& next_protos,
-      bool can_advertise_http2);
+      const NextProtoVector& next_protos);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SSLClientSocket, SerializeNextProtos);
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index f558e71..ecff0e5 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -137,14 +137,6 @@
     } while (0)
 #endif
 
-#if !defined(CKM_AES_GCM)
-#define CKM_AES_GCM 0x00001087
-#endif
-
-#if !defined(CKM_NSS_CHACHA20_POLY1305)
-#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
-#endif
-
 namespace {
 
 // SSL plaintext fragments are shorter than 16KB. Although the record layer
@@ -852,16 +844,11 @@
   SECStatus rv = SECSuccess;
 
   if (!ssl_config_.next_protos.empty()) {
+    NextProtoVector next_protos = ssl_config_.next_protos;
     // TODO(bnc): Check ssl_config_.disabled_cipher_suites.
-    const bool adequate_encryption =
-        PK11_TokenExists(CKM_AES_GCM) ||
-        PK11_TokenExists(CKM_NSS_CHACHA20_POLY1305);
-    const bool adequate_key_agreement = PK11_TokenExists(CKM_DH_PKCS_DERIVE) ||
-                                        PK11_TokenExists(CKM_ECDH1_DERIVE);
-    std::vector<uint8_t> wire_protos =
-        SerializeNextProtos(ssl_config_.next_protos,
-                            adequate_encryption && adequate_key_agreement &&
-                                IsTLSVersionAdequateForHTTP2(ssl_config_));
+    if (!IsTLSVersionAdequateForHTTP2(ssl_config_))
+      DisableHTTP2(&next_protos);
+    std::vector<uint8_t> wire_protos = SerializeNextProtos(next_protos);
     rv = SSL_SetNextProtoNego(
         nss_fd_, wire_protos.empty() ? NULL : &wire_protos[0],
         wire_protos.size());
@@ -2368,13 +2355,11 @@
 }
 
 SSLClientSocketNSS::SSLClientSocketNSS(
-    base::SequencedTaskRunner* nss_task_runner,
     scoped_ptr<ClientSocketHandle> transport_socket,
     const HostPortPair& host_and_port,
     const SSLConfig& ssl_config,
     const SSLClientSocketContext& context)
-    : nss_task_runner_(nss_task_runner),
-      transport_(transport_socket.Pass()),
+    : transport_(transport_socket.Pass()),
       host_and_port_(host_and_port),
       ssl_config_(ssl_config),
       cert_verifier_(context.cert_verifier),
@@ -2412,20 +2397,6 @@
   SSL_ClearSessionCache();
 }
 
-#if !defined(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-
-// static
-uint16 SSLClientSocket::GetMaxSupportedSSLVersion() {
-  crypto::EnsureNSSInit();
-  if (PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
-    return SSL_PROTOCOL_VERSION_TLS1_2;
-  } else {
-    return SSL_PROTOCOL_VERSION_TLS1_1;
-  }
-}
-
 bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
   EnterFunction("");
   ssl_info->Reset();
@@ -2715,13 +2686,12 @@
 }
 
 void SSLClientSocketNSS::InitCore() {
+  // TODO(davidben): Both task runners are now always the same. Unwind this code
+  // further, although the entire class is due to be deleted eventually, so it
+  // may not be worth bothering.
   core_ = new Core(base::ThreadTaskRunnerHandle::Get().get(),
-                   nss_task_runner_.get(),
-                   transport_.get(),
-                   host_and_port_,
-                   ssl_config_,
-                   &net_log_,
-                   channel_id_service_);
+                   base::ThreadTaskRunnerHandle::Get().get(), transport_.get(),
+                   host_and_port_, ssl_config_, &net_log_, channel_id_service_);
 }
 
 int SSLClientSocketNSS::InitializeSSLOptions() {
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 84bb6acf..0cec7eb 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -30,10 +30,6 @@
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_config_service.h"
 
-namespace base {
-class SequencedTaskRunner;
-}
-
 namespace net {
 
 class BoundNetLog;
@@ -54,14 +50,7 @@
   // authentication is requested, the host_and_port field of SSLCertRequestInfo
   // will be populated with |host_and_port|.  |ssl_config| specifies
   // the SSL settings.
-  //
-  // Because calls to NSS may block, such as due to needing to access slow
-  // hardware or needing to synchronously unlock protected tokens, calls to
-  // NSS may optionally be run on a dedicated thread. If synchronous/blocking
-  // behaviour is desired, for performance or compatibility, the current task
-  // runner should be supplied instead.
-  SSLClientSocketNSS(base::SequencedTaskRunner* nss_task_runner,
-                     scoped_ptr<ClientSocketHandle> transport_socket,
+  SSLClientSocketNSS(scoped_ptr<ClientSocketHandle> transport_socket,
                      const HostPortPair& host_and_port,
                      const SSLConfig& ssl_config,
                      const SSLClientSocketContext& context);
@@ -155,8 +144,6 @@
   // the |ssl_info|.signed_certificate_timestamps list.
   void AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const;
 
-  // The task runner used to perform NSS operations.
-  scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
   scoped_ptr<ClientSocketHandle> transport_;
   HostPortPair host_and_port_;
   SSLConfig ssl_config_;
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 9d7289a..c3af8b8 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -290,11 +290,6 @@
     return socket->PrivateKeyTypeCallback();
   }
 
-  static int PrivateKeySupportsDigestCallback(SSL* ssl, const EVP_MD* md) {
-    SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
-    return socket->PrivateKeySupportsDigestCallback(md);
-  }
-
   static size_t PrivateKeyMaxSignatureLenCallback(SSL* ssl) {
     SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
     return socket->PrivateKeyMaxSignatureLenCallback();
@@ -338,7 +333,6 @@
 const SSL_PRIVATE_KEY_METHOD
     SSLClientSocketOpenSSL::SSLContext::kPrivateKeyMethod = {
         &SSLClientSocketOpenSSL::SSLContext::PrivateKeyTypeCallback,
-        &SSLClientSocketOpenSSL::SSLContext::PrivateKeySupportsDigestCallback,
         &SSLClientSocketOpenSSL::SSLContext::PrivateKeyMaxSignatureLenCallback,
         &SSLClientSocketOpenSSL::SSLContext::PrivateKeySignCallback,
         &SSLClientSocketOpenSSL::SSLContext::PrivateKeySignCompleteCallback,
@@ -432,11 +426,6 @@
   context->session_cache()->Flush();
 }
 
-// static
-uint16 SSLClientSocket::GetMaxSupportedSSLVersion() {
-  return SSL_PROTOCOL_VERSION_TLS1_2;
-}
-
 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
     scoped_ptr<ClientSocketHandle> transport_socket,
     const HostPortPair& host_and_port,
@@ -883,10 +872,10 @@
   STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
   DCHECK(ciphers);
   // See SSLConfig::disabled_cipher_suites for description of the suites
-  // disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256
+  // disabled by default. Note that SHA256 and SHA384 only select HMAC-SHA256
   // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384
   // as the handshake hash.
-  std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK");
+  std::string command("DEFAULT:!SHA256:-SHA384:!AESGCM+AES256:!aPSK");
   // Walk through all the installed ciphers, seeing if any need to be
   // appended to the cipher removal |command|.
   for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
@@ -911,8 +900,15 @@
      }
   }
 
-  if (!ssl_config_.enable_deprecated_cipher_suites)
+  if (!ssl_config_.enable_deprecated_cipher_suites) {
     command.append(":!RC4");
+  } else {
+    // Add TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 under a fallback. This is
+    // believed to work around a bug in some out-of-date Microsoft IIS servers
+    // which cause them to require the version downgrade
+    // (https://crbug.com/433406).
+    command.append(":ECDHE-RSA-AES256-SHA384");
+  }
 
   // Disable ECDSA cipher suites on platforms that do not support ECDSA
   // signed certificates, as servers may use the presence of such
@@ -945,10 +941,12 @@
       enabled_ciphers_vector.push_back(id);
     }
 
-    std::vector<uint8_t> wire_protos =
-        SerializeNextProtos(ssl_config_.next_protos,
-                            HasCipherAdequateForHTTP2(enabled_ciphers_vector) &&
-                                IsTLSVersionAdequateForHTTP2(ssl_config_));
+    NextProtoVector next_protos = ssl_config_.next_protos;
+    if (!HasCipherAdequateForHTTP2(enabled_ciphers_vector) ||
+        !IsTLSVersionAdequateForHTTP2(ssl_config_)) {
+      DisableHTTP2(&next_protos);
+    }
+    std::vector<uint8_t> wire_protos = SerializeNextProtos(next_protos);
     SSL_set_alpn_protos(ssl_, wire_protos.empty() ? NULL : &wire_protos[0],
                         wire_protos.size());
   }
@@ -1820,7 +1818,35 @@
     }
 
     SSL_set_private_key_method(ssl_, &SSLContext::kPrivateKeyMethod);
-#endif
+
+    std::vector<SSLPrivateKey::Hash> digest_prefs =
+        private_key_->GetDigestPreferences();
+
+    size_t digests_len = digest_prefs.size();
+    std::vector<int> digests;
+    for (size_t i = 0; i < digests_len; i++) {
+      switch (digest_prefs[i]) {
+        case SSLPrivateKey::Hash::SHA1:
+          digests.push_back(NID_sha1);
+          break;
+        case SSLPrivateKey::Hash::SHA256:
+          digests.push_back(NID_sha256);
+          break;
+        case SSLPrivateKey::Hash::SHA384:
+          digests.push_back(NID_sha384);
+          break;
+        case SSLPrivateKey::Hash::SHA512:
+          digests.push_back(NID_sha512);
+          break;
+        case SSLPrivateKey::Hash::MD5_SHA1:
+          // MD5-SHA1 is not used in TLS 1.2.
+          break;
+      }
+    }
+
+    SSL_set_private_key_digest_prefs(ssl_, vector_as_array(&digests),
+                                     digests.size());
+#endif  // !OS_NACL
 
     int cert_count = 1 + sk_X509_num(chain.get());
     net_log_.AddEvent(NetLog::TYPE_SSL_CLIENT_CERT_PROVIDED,
@@ -2057,11 +2083,6 @@
   return EVP_PKEY_NONE;
 }
 
-int SSLClientSocketOpenSSL::PrivateKeySupportsDigestCallback(const EVP_MD* md) {
-  SSLPrivateKey::Hash hash;
-  return EVP_MDToPrivateKeyHash(md, &hash) && private_key_->SupportsHash(hash);
-}
-
 size_t SSLClientSocketOpenSSL::PrivateKeyMaxSignatureLenCallback() {
   return private_key_->GetMaxSignatureLengthInBytes();
 }
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index c8478901..228214b4 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -191,7 +191,6 @@
 
   // Callbacks for operations with the private key.
   int PrivateKeyTypeCallback();
-  int PrivateKeySupportsDigestCallback(const EVP_MD* md);
   size_t PrivateKeyMaxSignatureLenCallback();
   ssl_private_key_result_t PrivateKeySignCallback(uint8_t* out,
                                                   size_t* out_len,
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 77a0aab7..bb94cac 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -42,21 +42,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
-#if !defined(USE_OPENSSL)
-#include <pk11pub.h>
-#include "crypto/nss_util.h"
-
-#if !defined(CKM_AES_GCM)
-#define CKM_AES_GCM 0x00001087
-#endif
-
-#if !defined(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-#endif
-
-//-----------------------------------------------------------------------------
-
 using testing::_;
 using testing::Return;
 using testing::Truly;
@@ -961,18 +946,6 @@
   scoped_ptr<ChannelIDService> channel_id_service_;
 };
 
-//-----------------------------------------------------------------------------
-
-bool SupportsAESGCM() {
-#if defined(USE_OPENSSL)
-  return true;
-#else
-  crypto::EnsureNSSInit();
-  return PK11_TokenExists(CKM_AES_GCM) &&
-         PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256);
-#endif
-}
-
 }  // namespace
 
 TEST_F(SSLClientSocketTest, Connect) {
@@ -2373,7 +2346,7 @@
   next_protos.push_back(kProtoHTTP11);
   next_protos.push_back(kProtoSPDY31);
   static std::vector<uint8_t> serialized =
-      SSLClientSocket::SerializeNextProtos(next_protos, true);
+      SSLClientSocket::SerializeNextProtos(next_protos);
   ASSERT_EQ(18u, serialized.size());
   EXPECT_EQ(8, serialized[0]);  // length("http/1.1")
   EXPECT_EQ('h', serialized[1]);
@@ -3159,11 +3132,6 @@
 }
 
 TEST_F(SSLClientSocketFalseStartTest, FalseStartEnabled) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   // False Start requires NPN/ALPN, ECDHE, and an AEAD.
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
@@ -3179,11 +3147,6 @@
 
 // Test that False Start is disabled without NPN.
 TEST_F(SSLClientSocketFalseStartTest, NoNPN) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
       SpawnedTestServer::SSLOptions::KEY_EXCHANGE_ECDHE_RSA;
@@ -3197,11 +3160,6 @@
 
 // Test that False Start is disabled with plain RSA ciphers.
 TEST_F(SSLClientSocketFalseStartTest, RSA) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
       SpawnedTestServer::SSLOptions::KEY_EXCHANGE_RSA;
@@ -3216,11 +3174,6 @@
 
 // Test that False Start is disabled with DHE_RSA ciphers.
 TEST_F(SSLClientSocketFalseStartTest, DHE_RSA) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
       SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
@@ -3247,11 +3200,6 @@
 
 // Test that sessions are resumable after receiving the server Finished message.
 TEST_F(SSLClientSocketFalseStartTest, SessionResumption) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   // Start a server.
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
@@ -3285,11 +3233,6 @@
 // Test that False Started sessions are not resumable before receiving the
 // server Finished message.
 TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinished) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   // Start a server.
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
@@ -3348,11 +3291,6 @@
 // Test that False Started sessions are not resumable if the server Finished
 // message was bad.
 TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBadFinished) {
-  if (!SupportsAESGCM()) {
-    LOG(WARNING) << "Skipping test because AES-GCM is not supported.";
-    return;
-  }
-
   // Start a server.
   SpawnedTestServer::SSLOptions server_options;
   server_options.key_exchanges =
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index b99f834..24b3090 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -52,17 +52,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
-#if !defined(USE_OPENSSL)
-#include <pk11pub.h>
-
-#if !defined(CKM_AES_GCM)
-#define CKM_AES_GCM 0x00001087
-#endif
-#if !defined(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)
-#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
-#endif
-#endif
-
 namespace net {
 
 namespace {
@@ -412,14 +401,7 @@
   bool is_aead;
   SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, cipher_suite);
   EXPECT_STREQ("ECDHE_RSA", key_exchange);
-#if defined(USE_OPENSSL)
-  bool supports_aead = true;
-#else
-  bool supports_aead =
-      PK11_TokenExists(CKM_AES_GCM) &&
-      PK11_TokenExists(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256);
-#endif
-  EXPECT_TRUE(!supports_aead || is_aead);
+  EXPECT_TRUE(is_aead);
 }
 
 TEST_F(SSLServerSocketTest, DataTransfer) {
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index fc7da41..b14475cd4e 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -235,14 +235,14 @@
   // We grab an extra reference because there is an IO operation in progress.
   // Balanced in ReadDelegate::OnObjectSignaled().
   AddRef();
-  read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
+  read_watcher_.StartWatchingOnce(read_overlapped_.hEvent, &reader_);
 }
 
 void TCPSocketWin::Core::WatchForWrite() {
   // We grab an extra reference because there is an IO operation in progress.
   // Balanced in WriteDelegate::OnObjectSignaled().
   AddRef();
-  write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
+  write_watcher_.StartWatchingOnce(write_overlapped_.hEvent, &writer_);
 }
 
 void TCPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
@@ -402,7 +402,7 @@
   if (result == ERR_IO_PENDING) {
     // Start watching.
     WSAEventSelect(socket_, accept_event_, FD_ACCEPT);
-    accept_watcher_.StartWatching(accept_event_, this);
+    accept_watcher_.StartWatchingOnce(accept_event_, this);
 
     accept_socket_ = socket;
     accept_address_ = address;
@@ -772,7 +772,7 @@
 
     // Start watching the next FD_ACCEPT event.
     WSAEventSelect(socket_, accept_event_, FD_ACCEPT);
-    accept_watcher_.StartWatching(accept_event_, this);
+    accept_watcher_.StartWatchingOnce(accept_event_, this);
   }
 }
 
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index bf28b45..6cf1d737 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -541,6 +541,13 @@
   NOTREACHED();
 }
 
+bool SpdyHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+  if (!spdy_session_)
+    return false;
+
+  return spdy_session_->GetPeerAddress(endpoint) == OK;
+}
+
 void SpdyHttpStream::Drain(HttpNetworkSession* session) {
   NOTREACHED();
   Close(false);
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 97bd72b..b51869c2 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -78,6 +78,7 @@
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
   void GetSSLInfo(SSLInfo* ssl_info) override;
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   void Drain(HttpNetworkSession* session) override;
   void SetPriority(RequestPriority priority) override;
 
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 283c157..8755cc0 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -477,7 +477,7 @@
   DCHECK(next_proto_is_spdy(protocol)) << "Invalid protocol: " << protocol;
 
   storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver));
-  storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier).Pass());
+  storage_.set_cert_verifier(make_scoped_ptr(new MockCertVerifier));
   storage_.set_transport_security_state(
       make_scoped_ptr(new TransportSecurityState));
   storage_.set_proxy_service(ProxyService::CreateDirect());
@@ -486,8 +486,7 @@
       HttpAuthHandlerFactory::CreateDefault(host_resolver()));
   storage_.set_http_server_properties(
       scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl()));
-  storage_.set_job_factory(
-      make_scoped_ptr(new URLRequestJobFactoryImpl()).Pass());
+  storage_.set_job_factory(make_scoped_ptr(new URLRequestJobFactoryImpl()));
   HttpNetworkSession::Params params;
   params.client_socket_factory = &socket_factory_;
   params.host_resolver = host_resolver();
@@ -505,10 +504,8 @@
       new HttpNetworkSession(params));
   SpdySessionPoolPeer pool_peer(network_session->spdy_session_pool());
   pool_peer.SetEnableSendingInitialData(false);
-  storage_.set_http_transaction_factory(
-      make_scoped_ptr(new HttpCache(network_session.get(),
-                                    HttpCache::DefaultBackend::InMemory(0)))
-          .Pass());
+  storage_.set_http_transaction_factory(make_scoped_ptr(new HttpCache(
+      network_session.get(), HttpCache::DefaultBackend::InMemory(0))));
 }
 
 SpdyURLRequestContext::~SpdyURLRequestContext() {
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc
index a539440..412bf00 100644
--- a/net/ssl/ssl_config.cc
+++ b/net/ssl/ssl_config.cc
@@ -5,13 +5,14 @@
 #include "net/ssl/ssl_config.h"
 
 #include "net/cert/cert_verifier.h"
-#include "net/socket/ssl_client_socket.h"
 
 namespace net {
 
-const uint16 kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1;
+const uint16_t kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1;
 
-const uint16 kDefaultSSLVersionFallbackMin = SSL_PROTOCOL_VERSION_TLS1_1;
+const uint16_t kDefaultSSLVersionMax = SSL_PROTOCOL_VERSION_TLS1_2;
+
+const uint16_t kDefaultSSLVersionFallbackMin = SSL_PROTOCOL_VERSION_TLS1_1;
 
 SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
 
@@ -21,7 +22,7 @@
     : rev_checking_enabled(false),
       rev_checking_required_local_anchors(false),
       version_min(kDefaultSSLVersionMin),
-      version_max(SSLClientSocket::GetMaxSupportedSSLVersion()),
+      version_max(kDefaultSSLVersionMax),
       version_fallback_min(kDefaultSSLVersionFallbackMin),
       enable_deprecated_cipher_suites(false),
       channel_id_enabled(true),
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
index 6b3919bbe..f1c70bb 100644
--- a/net/ssl/ssl_config.h
+++ b/net/ssl/ssl_config.h
@@ -5,7 +5,8 @@
 #ifndef NET_SSL_SSL_CONFIG_H_
 #define NET_SSL_SSL_CONFIG_H_
 
-#include "base/basictypes.h"
+#include <stdint.h>
+
 #include "base/memory/ref_counted.h"
 #include "net/base/net_export.h"
 #include "net/cert/x509_certificate.h"
@@ -27,13 +28,13 @@
 };
 
 // Default minimum protocol version.
-NET_EXPORT extern const uint16 kDefaultSSLVersionMin;
+NET_EXPORT extern const uint16_t kDefaultSSLVersionMin;
 
-// For maximum supported protocol version, use
-// SSLClientSocket::GetMaxSupportedSSLVersion().
+// Default maximum protocol version.
+NET_EXPORT extern const uint16_t kDefaultSSLVersionMax;
 
 // Default minimum protocol version that it's acceptable to fallback to.
-NET_EXPORT extern const uint16 kDefaultSSLVersionFallbackMin;
+NET_EXPORT extern const uint16_t kDefaultSSLVersionFallbackMin;
 
 // A collection of SSL-related configuration settings.
 struct NET_EXPORT SSLConfig {
diff --git a/net/ssl/ssl_platform_key_android.cc b/net/ssl/ssl_platform_key_android.cc
index c918f360..773844a 100644
--- a/net/ssl/ssl_platform_key_android.cc
+++ b/net/ssl/ssl_platform_key_android.cc
@@ -29,7 +29,13 @@
 
   SSLPrivateKey::Type GetType() override { return type_; }
 
-  bool SupportsHash(SSLPrivateKey::Hash hash) override { return true; }
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+    static const SSLPrivateKey::Hash kHashes[] = {
+        SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+        SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
+    return std::vector<SSLPrivateKey::Hash>(kHashes,
+                                            kHashes + arraysize(kHashes));
+  }
 
   size_t GetMaxSignatureLengthInBytes() override {
     return EVP_PKEY_size(key_.get());
diff --git a/net/ssl/ssl_platform_key_mac.cc b/net/ssl/ssl_platform_key_mac.cc
index 2f2974c..0eb787a 100644
--- a/net/ssl/ssl_platform_key_mac.cc
+++ b/net/ssl/ssl_platform_key_mac.cc
@@ -102,7 +102,13 @@
     }
   }
 
-  bool SupportsHash(SSLPrivateKey::Hash hash) override { return true; }
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+    static const SSLPrivateKey::Hash kHashes[] = {
+        SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+        SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
+    return std::vector<SSLPrivateKey::Hash>(kHashes,
+                                            kHashes + arraysize(kHashes));
+  }
 
   size_t GetMaxSignatureLengthInBytes() override {
     if (cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) {
diff --git a/net/ssl/ssl_platform_key_nss.cc b/net/ssl/ssl_platform_key_nss.cc
index 22a6eec..2533210 100644
--- a/net/ssl/ssl_platform_key_nss.cc
+++ b/net/ssl/ssl_platform_key_nss.cc
@@ -44,7 +44,13 @@
 
   SSLPrivateKey::Type GetType() override { return type_; }
 
-  bool SupportsHash(SSLPrivateKey::Hash hash) override { return true; }
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+    static const SSLPrivateKey::Hash kHashes[] = {
+        SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+        SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
+    return std::vector<SSLPrivateKey::Hash>(kHashes,
+                                            kHashes + arraysize(kHashes));
+  }
 
   size_t GetMaxSignatureLengthInBytes() override {
     int len = PK11_SignatureLen(key_.get());
diff --git a/net/ssl/ssl_platform_key_win.cc b/net/ssl/ssl_platform_key_win.cc
index 5bd9955..1cb846b8 100644
--- a/net/ssl/ssl_platform_key_win.cc
+++ b/net/ssl/ssl_platform_key_win.cc
@@ -81,11 +81,14 @@
 
   SSLPrivateKey::Type GetType() override { return SSLPrivateKey::Type::RSA; }
 
-  bool SupportsHash(SSLPrivateKey::Hash hash) override {
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
     // If the key is in CAPI, assume conservatively that the CAPI service
     // provider may only be able to sign pre-TLS-1.2 and SHA-1 hashes.
-    return hash == SSLPrivateKey::Hash::MD5_SHA1 ||
-           hash == SSLPrivateKey::Hash::SHA1;
+    static const SSLPrivateKey::Hash kHashes[] = {
+        SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512,
+        SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256};
+    return std::vector<SSLPrivateKey::Hash>(kHashes,
+                                            kHashes + arraysize(kHashes));
   }
 
   size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
@@ -175,20 +178,23 @@
 
   SSLPrivateKey::Type GetType() override { return type_; }
 
-  bool SupportsHash(SSLPrivateKey::Hash hash) override {
-    // If the key is a 1024-bit RSA, assume conservatively that it may only be
-    // able to sign SHA-1 hashes. This is the case for older Estonian ID cards
-    // that have 1024-bit RSA keys. (For an RSA key, the maximum signature
-    // length is the size of the modulus in bytes.)
-    //
-    // CNG does provide NCryptIsAlgSupported and NCryptEnumAlgorithms functions,
-    // however they seem to both return NTE_NOT_SUPPORTED when querying the
-    // NCRYPT_PROV_HANDLE at the key's NCRYPT_PROVIDER_HANDLE_PROPERTY.
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
+    // If this is an under 1024-bit RSA key, conservatively prefer to sign
+    // SHA-1 hashes. Older Estonian ID cards can only sign SHA-1 hashes.
+    // However, if the server doesn't advertise SHA-1, the remaining hashes
+    // might still be supported.
     if (type_ == SSLPrivateKey::Type::RSA && max_length_ <= 1024 / 8) {
-      return hash == SSLPrivateKey::Hash::MD5_SHA1 ||
-             hash == SSLPrivateKey::Hash::SHA1;
+      static const SSLPrivateKey::Hash kHashesSpecial[] = {
+          SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512,
+          SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256};
+      return std::vector<SSLPrivateKey::Hash>(
+          kHashesSpecial, kHashesSpecial + arraysize(kHashesSpecial));
     }
-    return true;
+    static const SSLPrivateKey::Hash kHashes[] = {
+        SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
+        SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
+    return std::vector<SSLPrivateKey::Hash>(kHashes,
+                                            kHashes + arraysize(kHashes));
   }
 
   size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
diff --git a/net/ssl/ssl_private_key.h b/net/ssl/ssl_private_key.h
index a2e5c35..d1aa099 100644
--- a/net/ssl/ssl_private_key.h
+++ b/net/ssl/ssl_private_key.h
@@ -46,8 +46,8 @@
   // BoringSSL.
   virtual Type GetType() = 0;
 
-  // Returns true if the key supports signing hashes of type |hash|.
-  virtual bool SupportsHash(Hash hash) = 0;
+  // Returns the digests that are supported by the key in decreasing preference.
+  virtual std::vector<SSLPrivateKey::Hash> GetDigestPreferences() = 0;
 
   // Returns the maximum size of a signature, in bytes. For an RSA key, this
   // must be the size of the modulus.
diff --git a/net/ssl/threaded_ssl_private_key.cc b/net/ssl/threaded_ssl_private_key.cc
index da81bdf..f395518 100644
--- a/net/ssl/threaded_ssl_private_key.cc
+++ b/net/ssl/threaded_ssl_private_key.cc
@@ -62,8 +62,8 @@
   return core_->delegate()->GetType();
 }
 
-bool ThreadedSSLPrivateKey::SupportsHash(SSLPrivateKey::Hash hash) {
-  return core_->delegate()->SupportsHash(hash);
+std::vector<SSLPrivateKey::Hash> ThreadedSSLPrivateKey::GetDigestPreferences() {
+  return core_->delegate()->GetDigestPreferences();
 }
 
 size_t ThreadedSSLPrivateKey::GetMaxSignatureLengthInBytes() {
diff --git a/net/ssl/threaded_ssl_private_key.h b/net/ssl/threaded_ssl_private_key.h
index 9c364dd..afee103 100644
--- a/net/ssl/threaded_ssl_private_key.h
+++ b/net/ssl/threaded_ssl_private_key.h
@@ -35,7 +35,7 @@
     // These methods behave as those of the same name on SSLPrivateKey. They
     // must be callable on any thread.
     virtual Type GetType() = 0;
-    virtual bool SupportsHash(Hash hash) = 0;
+    virtual std::vector<SSLPrivateKey::Hash> GetDigestPreferences() = 0;
     virtual size_t GetMaxSignatureLengthInBytes() = 0;
 
     // Signs |input| as a digest of type |hash|. On sucess it returns OK and
@@ -56,7 +56,7 @@
 
   // SSLPrivateKey implementation.
   Type GetType() override;
-  bool SupportsHash(Hash hash) override;
+  std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override;
   size_t GetMaxSignatureLengthInBytes() override;
   void SignDigest(Hash hash,
                   const base::StringPiece& input,
diff --git a/net/test/embedded_test_server/stream_listen_socket.cc b/net/test/embedded_test_server/stream_listen_socket.cc
index 1056983a..897b23b 100644
--- a/net/test/embedded_test_server/stream_listen_socket.cc
+++ b/net/test/embedded_test_server/stream_listen_socket.cc
@@ -228,7 +228,7 @@
 void StreamListenSocket::WatchSocket(WaitState state) {
 #if defined(OS_WIN)
   WSAEventSelect(socket_, socket_event_, FD_ACCEPT | FD_CLOSE | FD_READ);
-  watcher_.StartWatching(socket_event_, this);
+  watcher_.StartWatchingOnce(socket_event_, this);
 #elif defined(OS_POSIX)
   // Implicitly calls StartWatchingFileDescriptor().
   base::MessageLoopForIO::current()->WatchFileDescriptor(
@@ -264,7 +264,7 @@
     return;
   }
   // The object was reset by WSAEnumNetworkEvents.  Watch for the next signal.
-  watcher_.StartWatching(object, this);
+  watcher_.StartWatchingOnce(object, this);
 
   if (ev.lNetworkEvents == 0) {
     // Occasionally the event is set even though there is no new data.
diff --git a/net/test/run_all_unittests.cc b/net/test/run_all_unittests.cc
index 7da7991..535fa07a0 100644
--- a/net/test/run_all_unittests.cc
+++ b/net/test/run_all_unittests.cc
@@ -18,6 +18,9 @@
 #include "base/test/test_ui_thread_android.h"
 #include "net/android/dummy_spnego_authenticator.h"
 #include "net/android/net_jni_registrar.h"
+#endif
+
+#if defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
 #include "url/android/url_jni_registrar.h"
 #endif
 
@@ -34,12 +37,14 @@
 
 #if defined(OS_ANDROID)
   const base::android::RegistrationMethod kNetTestRegisteredMethods[] = {
-      {"DummySpnegoAuthenticator",
-       net::android::DummySpnegoAuthenticator::RegisterJni},
-      {"NetAndroid", net::android::RegisterJni},
-      {"TestFileUtil", base::RegisterContentUriTestUtils},
-      {"TestUiThreadAndroid", base::RegisterTestUiThreadAndroid},
-      {"UrlAndroid", url::android::RegisterJni},
+    {"DummySpnegoAuthenticator",
+     net::android::DummySpnegoAuthenticator::RegisterJni},
+    {"NetAndroid", net::android::RegisterJni},
+    {"TestFileUtil", base::RegisterContentUriTestUtils},
+    {"TestUiThreadAndroid", base::RegisterTestUiThreadAndroid},
+#if defined(USE_ICU_ALTERNATIVES_ON_ANDROID)
+    {"UrlAndroid", url::android::RegisterJni},
+#endif
   };
 
   // Register JNI bindings for android. Doing it early as the test suite setup
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index 9b62d963..0361df62 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -15,6 +15,7 @@
 #include "net/quic/quic_connection_helper.h"
 #include "net/quic/quic_default_packet_writer.h"
 #include "net/quic/quic_flags.h"
+#include "net/quic/quic_packet_reader.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_server_id.h"
 #include "net/quic/spdy_utils.h"
@@ -135,8 +136,10 @@
   }
 
   socket_.swap(socket);
-  packet_reader_.reset(new QuicPacketReader(socket_.get(), this,
-                                            BoundNetLog()));
+  packet_reader_.reset(new QuicPacketReader(
+      socket_.get(), &clock_, this, kQuicYieldAfterPacketsRead,
+      QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds),
+      BoundNetLog()));
 
   if (socket != nullptr) {
     socket->Close();
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index 65c6d19..f9c1d20 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -133,14 +133,14 @@
   // We grab an extra reference because there is an IO operation in progress.
   // Balanced in ReadDelegate::OnObjectSignaled().
   AddRef();
-  read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
+  read_watcher_.StartWatchingOnce(read_overlapped_.hEvent, &reader_);
 }
 
 void UDPSocketWin::Core::WatchForWrite() {
   // We grab an extra reference because there is an IO operation in progress.
   // Balanced in WriteDelegate::OnObjectSignaled().
   AddRef();
-  write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
+  write_watcher_.StartWatchingOnce(write_overlapped_.hEvent, &writer_);
 }
 
 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
@@ -669,7 +669,7 @@
   if (read_write_watcher_.IsWatching())
     return;
   bool watched =
-      read_write_watcher_.StartWatching(read_write_event_.Get(), this);
+      read_write_watcher_.StartWatchingOnce(read_write_event_.Get(), this);
   DCHECK(watched);
 }
 
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index cfacae0..03f3f02 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -400,6 +400,13 @@
   *load_timing_info = load_timing_info_;
 }
 
+bool URLRequest::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  if (!job_)
+    return false;
+
+  return job_->GetRemoteEndpoint(endpoint);
+}
+
 bool URLRequest::GetResponseCookies(ResponseCookies* cookies) {
   DCHECK(job_.get());
   return job_->GetResponseCookies(cookies);
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 6e126c3..9209697 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -455,6 +455,18 @@
   // non-cached HTTP responses.
   void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
 
+  // Gets the remote endpoint of the most recent socket that the network stack
+  // used to make this request.
+  //
+  // Note that GetSocketAddress returns the |socket_address| field from
+  // HttpResponseInfo, which is only populated once the response headers are
+  // received, and can return cached values for cache revalidation requests.
+  // GetRemoteEndpoint will only return addresses from the current request.
+  //
+  // Returns true and fills in |endpoint| if the endpoint is available; returns
+  // false and leaves |endpoint| unchanged if it is unavailable.
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const;
+
   // Returns the cookie values included in the response, if the request is one
   // that can have cookies.  Returns true if the request is a cookie-bearing
   // type, false otherwise.  This method may only be called once the
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 233c047..e2c77e9 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -270,10 +270,8 @@
       new ContainerURLRequestContext(file_task_runner_));
   URLRequestContextStorage* storage = context->storage();
 
-  storage->set_http_user_agent_settings(
-      make_scoped_ptr(
-          new StaticHttpUserAgentSettings(accept_language_, user_agent_))
-          .Pass());
+  storage->set_http_user_agent_settings(make_scoped_ptr(
+      new StaticHttpUserAgentSettings(accept_language_, user_agent_)));
 
   if (!network_delegate_)
     network_delegate_.reset(new BasicNetworkDelegate);
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 386b270d..c317469 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -1092,6 +1092,13 @@
     load_timing_info->receive_headers_end = receive_headers_end_;
 }
 
+bool URLRequestHttpJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  if (!transaction_)
+    return false;
+
+  return transaction_->GetRemoteEndpoint(endpoint);
+}
+
 bool URLRequestHttpJob::GetResponseCookies(std::vector<std::string>* cookies) {
   DCHECK(transaction_.get());
 
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index f72cb15..4ee4440 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -118,6 +118,7 @@
   bool GetCharset(std::string* charset) override;
   void GetResponseInfo(HttpResponseInfo* info) override;
   void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) const override;
   bool GetResponseCookies(std::vector<std::string>* cookies) override;
   int GetResponseCode() const override;
   Filter* SetupFilter() const override;
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index 43b7e2b..dca3e8e9 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -149,6 +149,8 @@
             request->GetTotalSentBytes());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             request->GetTotalReceivedBytes());
+  EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             network_delegate_.total_network_bytes_received());
 }
@@ -178,6 +180,8 @@
             request->GetTotalSentBytes());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             request->GetTotalReceivedBytes());
+  EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             network_delegate_.total_network_bytes_received());
 }
@@ -209,6 +213,8 @@
             request->GetTotalSentBytes());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             request->GetTotalReceivedBytes());
+  EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             network_delegate_.total_network_bytes_received());
 }
@@ -241,6 +247,8 @@
             request->GetTotalSentBytes());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             request->GetTotalReceivedBytes());
+  EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             network_delegate_.total_network_bytes_received());
 }
@@ -291,6 +299,9 @@
   EXPECT_EQ(CountReadBytes(final_reads, arraysize(final_reads)),
             request->GetTotalReceivedBytes());
   // Should include the redirect as well as the final response.
+  EXPECT_EQ(CountWriteBytes(redirect_writes, arraysize(redirect_writes)) +
+                CountWriteBytes(final_writes, arraysize(final_writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(redirect_reads, arraysize(redirect_reads)) +
                 CountReadBytes(final_reads, arraysize(final_reads)),
             network_delegate_.total_network_bytes_received());
@@ -320,6 +331,8 @@
             request->GetTotalSentBytes());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             request->GetTotalReceivedBytes());
+  EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+            network_delegate_.total_network_bytes_sent());
   EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
             network_delegate_.total_network_bytes_received());
 }
@@ -730,6 +743,8 @@
 
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {}
 
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; }
+
   void Drain(HttpNetworkSession* session) override {}
 
   void SetPriority(RequestPriority priority) override {}
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 5adda9ae..f23a3bbd 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -73,6 +73,7 @@
       expected_content_size_(-1),
       network_delegate_(network_delegate),
       last_notified_total_received_bytes_(0),
+      last_notified_total_sent_bytes_(0),
       weak_factory_(this) {
   base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
   if (power_monitor)
@@ -177,6 +178,10 @@
   // Only certain request types return more than just request start times.
 }
 
+bool URLRequestJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
+  return false;
+}
+
 bool URLRequestJob::GetResponseCookies(std::vector<std::string>* cookies) {
   return false;
 }
@@ -948,6 +953,7 @@
   if (!request_ || !network_delegate_)
     return;
 
+  // Report any new received bytes.
   int64_t total_received_bytes = GetTotalReceivedBytes();
   DCHECK_GE(total_received_bytes, last_notified_total_received_bytes_);
   if (total_received_bytes > last_notified_total_received_bytes_) {
@@ -955,6 +961,15 @@
         *request_, total_received_bytes - last_notified_total_received_bytes_);
   }
   last_notified_total_received_bytes_ = total_received_bytes;
+
+  // Report any new sent bytes.
+  int64_t total_sent_bytes = GetTotalSentBytes();
+  DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_);
+  if (total_sent_bytes > last_notified_total_sent_bytes_) {
+    network_delegate_->NotifyNetworkBytesSent(
+        *request_, total_sent_bytes - last_notified_total_sent_bytes_);
+  }
+  last_notified_total_sent_bytes_ = total_sent_bytes;
 }
 
 }  // namespace net
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 8524bf0..82b13633c 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -138,6 +138,11 @@
   // for more information on the difference.
   virtual void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
 
+  // Gets the remote endpoint that the network stack is currently fetching the
+  // URL from. Returns true and fills in |endpoint| if it is available; returns
+  // false and leaves |endpoint| unchanged if it is unavailable.
+  virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) const;
+
   // Returns the cookie values included in the response, if applicable.
   // Returns true if applicable.
   // NOTE: This removes the cookies from the job, so it will only return
@@ -402,10 +407,9 @@
   // |location| and |http_status_code|.
   RedirectInfo ComputeRedirectInfo(const GURL& location, int http_status_code);
 
-  // Notify the network delegate that more bytes have been received over the
-  // network, if bytes have been received since the previous notification.
-  // TODO(sclittle): Have this method also notify about sent bytes once
-  // URLRequestJob::GetTotalSentBytes has been implemented (crbug.com/518897).
+  // Notify the network delegate that more bytes have been received or sent over
+  // the network, if bytes have been received or sent since the previous
+  // notification.
   void MaybeNotifyNetworkBytes();
 
   // Indicates that the job is done producing data, either it has completed
@@ -452,6 +456,11 @@
   // newly received since the last notification.
   int64_t last_notified_total_received_bytes_;
 
+  // The value from GetTotalSentBytes() the last time MaybeNotifyNetworkBytes()
+  // was called. Used to calculate how bytes have been newly sent since the last
+  // notification.
+  int64_t last_notified_total_sent_bytes_;
+
   base::WeakPtrFactory<URLRequestJob> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(URLRequestJob);
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index af8d139..efcc759 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -123,14 +123,12 @@
                              base::WorkerPool::GetTaskRunner(true))));
   }
   if (!http_user_agent_settings()) {
-    context_storage_.set_http_user_agent_settings(
-        make_scoped_ptr(
-            new StaticHttpUserAgentSettings("en-us,fr", std::string()))
-            .Pass());
+    context_storage_.set_http_user_agent_settings(make_scoped_ptr(
+        new StaticHttpUserAgentSettings("en-us,fr", std::string())));
   }
   if (!job_factory()) {
     context_storage_.set_job_factory(
-        make_scoped_ptr(new URLRequestJobFactoryImpl()).Pass());
+        make_scoped_ptr(new URLRequestJobFactoryImpl()));
   }
 }
 
@@ -330,6 +328,7 @@
       before_send_headers_count_(0),
       headers_received_count_(0),
       total_network_bytes_received_(0),
+      total_network_bytes_sent_(0),
       has_load_timing_info_before_redirect_(false),
       has_load_timing_info_before_auth_(false),
       can_access_files_(true),
@@ -512,6 +511,12 @@
   total_network_bytes_received_ += bytes_received;
 }
 
+void TestNetworkDelegate::OnNetworkBytesSent(const URLRequest& request,
+                                             int64_t bytes_sent) {
+  event_order_[request.identifier()] += "OnNetworkBytesSent\n";
+  total_network_bytes_sent_ += bytes_sent;
+}
+
 void TestNetworkDelegate::OnCompleted(URLRequest* request, bool started) {
   int req_id = request->identifier();
   InitRequestStatesIfNew(req_id);
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 924635ee1a..09d44df 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -289,6 +289,7 @@
   int64_t total_network_bytes_received() const {
     return total_network_bytes_received_;
   }
+  int64_t total_network_bytes_sent() const { return total_network_bytes_sent_; }
 
   // Last observed proxy in proxy header sent callback.
   HostPortPair last_observed_proxy() {
@@ -322,6 +323,8 @@
   void OnResponseStarted(URLRequest* request) override;
   void OnNetworkBytesReceived(const URLRequest& request,
                               int64_t bytes_received) override;
+  void OnNetworkBytesSent(const URLRequest& request,
+                          int64_t bytes_sent) override;
   void OnCompleted(URLRequest* request, bool started) override;
   void OnURLRequestDestroyed(URLRequest* request) override;
   void OnPACScriptError(int line_number, const base::string16& error) override;
@@ -363,6 +366,7 @@
   int before_send_headers_count_;
   int headers_received_count_;
   int64_t total_network_bytes_received_;
+  int64_t total_network_bytes_sent_;
   // Last observed proxy in before proxy header sent callback.
   HostPortPair last_observed_proxy_;
 
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index e8f9668..87ad8eb 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -79,9 +79,11 @@
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/url_request/url_request_failed_job.h"
 #include "net/url_request/data_protocol_handler.h"
 #include "net/url_request/static_http_user_agent_settings.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
 #include "net/url_request/url_request_http_job.h"
 #include "net/url_request/url_request_intercepting_job_factory.h"
 #include "net/url_request/url_request_interceptor.h"
@@ -269,6 +271,8 @@
 
   void Suspend() { ProcessPowerEvent(SUSPEND_EVENT); }
 
+  void Resume() { ProcessPowerEvent(RESUME_EVENT); }
+
   bool IsOnBatteryPowerImpl() override { return false; }
 
  private:
@@ -2718,6 +2722,35 @@
   }
 }
 
+// Tests that a request is cancelled while entering suspend mode. Uses mocks
+// rather than a spawned test server because the connection used to talk to
+// the test server is affected by entering suspend mode on Android.
+TEST_F(URLRequestTest, CancelOnSuspend) {
+  TestPowerMonitorSource* power_monitor_source = new TestPowerMonitorSource();
+  base::PowerMonitor power_monitor(make_scoped_ptr(power_monitor_source));
+
+  URLRequestFailedJob::AddUrlHandler();
+
+  TestDelegate d;
+  // Request that just hangs.
+  GURL url(URLRequestFailedJob::GetMockHttpUrl(ERR_IO_PENDING));
+  scoped_ptr<URLRequest> r(
+      default_context_.CreateRequest(url, DEFAULT_PRIORITY, &d));
+  r->Start();
+
+  power_monitor_source->Suspend();
+  // Wait for the suspend notification to cause the request to fail.
+  base::RunLoop().Run();
+  EXPECT_EQ(URLRequestStatus::CANCELED, r->status().status());
+  EXPECT_TRUE(d.request_failed());
+  EXPECT_EQ(1, default_network_delegate_.completed_requests());
+
+  URLRequestFilter::GetInstance()->ClearHandlers();
+
+  // Shouldn't be needed, but just in case.
+  power_monitor_source->Resume();
+}
+
 // FixedDateNetworkDelegate swaps out the server's HTTP Date response header
 // value for the |fixed_date| argument given to the constructor.
 class FixedDateNetworkDelegate : public TestNetworkDelegate {
@@ -3914,27 +3947,6 @@
   }
 }
 
-// Tests that a request is cancelled while entering suspend mode.
-TEST_F(URLRequestTestHTTP, CancelOnSuspend) {
-  TestPowerMonitorSource* power_monitor_source = new TestPowerMonitorSource();
-  base::PowerMonitor power_monitor(make_scoped_ptr(power_monitor_source));
-  ASSERT_TRUE(test_server_.Start());
-
-  TestDelegate d;
-  // Request that won't complete any time soon.
-  GURL url(test_server_.GetURL("slow?600"));
-  scoped_ptr<URLRequest> r(
-      default_context_.CreateRequest(url, DEFAULT_PRIORITY, &d));
-  r->Start();
-
-  power_monitor_source->Suspend();
-  // Wait for the suspend notification to cause the request to fail.
-  base::RunLoop().Run();
-  EXPECT_EQ(URLRequestStatus::CANCELED, r->status().status());
-  EXPECT_TRUE(d.request_failed());
-  EXPECT_EQ(1, default_network_delegate_.completed_requests());
-}
-
 TEST_F(URLRequestTestHTTP, GetTest_NoCache) {
   ASSERT_TRUE(test_server_.Start());
 
@@ -7669,12 +7681,7 @@
   // No version downgrade should have been necessary.
   EXPECT_FALSE(r->ssl_info().connection_status &
                SSL_CONNECTION_VERSION_FALLBACK);
-  int expected_version = SSL_CONNECTION_VERSION_TLS1_2;
-  if (SSLClientSocket::GetMaxSupportedSSLVersion() <
-      SSL_PROTOCOL_VERSION_TLS1_2) {
-    expected_version = SSL_CONNECTION_VERSION_TLS1_1;
-  }
-  EXPECT_EQ(expected_version,
+  EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_2,
             SSLConnectionStatusToVersion(r->ssl_info().connection_status));
 
   TestNetLogEntry::List entries;
@@ -8346,11 +8353,6 @@
 
 // Tests the TLS 1.1 fallback.
 TEST_F(HTTPSFallbackTest, TLSv1_1Fallback) {
-  if (SSLClientSocket::GetMaxSupportedSSLVersion() <
-      SSL_PROTOCOL_VERSION_TLS1_2) {
-    return;
-  }
-
   SpawnedTestServer::SSLOptions ssl_options(
       SpawnedTestServer::SSLOptions::CERT_OK);
   ssl_options.tls_intolerant =
@@ -8362,11 +8364,6 @@
 
 // Tests that the TLS 1.1 fallback triggers on closed connections.
 TEST_F(HTTPSFallbackTest, TLSv1_1FallbackClosed) {
-  if (SSLClientSocket::GetMaxSupportedSSLVersion() <
-      SSL_PROTOCOL_VERSION_TLS1_2) {
-    return;
-  }
-
   SpawnedTestServer::SSLOptions ssl_options(
       SpawnedTestServer::SSLOptions::CERT_OK);
   ssl_options.tls_intolerant =
@@ -8383,11 +8380,6 @@
 #if !defined(OS_ANDROID)
 // Tests fallback to TLS 1.1 on connection reset.
 TEST_F(HTTPSFallbackTest, TLSv1_1FallbackReset) {
-  if (SSLClientSocket::GetMaxSupportedSSLVersion() <
-      SSL_PROTOCOL_VERSION_TLS1_2) {
-    return;
-  }
-
   SpawnedTestServer::SSLOptions ssl_options(
       SpawnedTestServer::SSLOptions::CERT_OK);
   ssl_options.tls_intolerant =
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index d359406..a909892 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -431,6 +431,13 @@
   parser()->GetSSLCertRequestInfo(cert_request_info);
 }
 
+bool WebSocketBasicHandshakeStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
+  if (!state_.connection() || !state_.connection()->socket())
+    return false;
+
+  return state_.connection()->socket()->GetPeerAddress(endpoint) == OK;
+}
+
 void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) {
   HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
   drainer->Start(session);
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h
index 7f03fb11..1984f3c 100644
--- a/net/websockets/websocket_basic_handshake_stream.h
+++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -62,6 +62,7 @@
   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override;
   void GetSSLInfo(SSLInfo* ssl_info) override;
   void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override;
+  bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   void Drain(HttpNetworkSession* session) override;
   void SetPriority(RequestPriority priority) override;
   UploadProgress GetUploadProgress() const override;
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn
index dc3f2e2f..2a982027 100644
--- a/ppapi/BUILD.gn
+++ b/ppapi/BUILD.gn
@@ -218,8 +218,16 @@
       } else {
         suffix = "newlib"
       }
+
+      # The CPU names used in tests/ppapi_nacl_tests_newlib.nmf
+      # are the ones used in GYP (x32 for x86).
+      if (target_cpu == "x86") {
+        nmf_cpu = "x32"
+      } else {
+        nmf_cpu = target_cpu
+      }
       outputs = [
-        "${root_build_dir}/{{source_name_part}}_${suffix}_${target_cpu}.nexe",
+        "${root_build_dir}/{{source_name_part}}_${suffix}_${nmf_cpu}.nexe",
       ]
       deps = [
         ":ppapi_nacl_tests",
@@ -270,7 +278,9 @@
       deps = [
         ":nacl_tests_copy",
       ]
-      data_deps = [ ":nacl_tests_copy" ]
+      data_deps = [
+        ":nacl_tests_copy",
+      ]
     }
   }
 
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 55e1ff2..ea7ccbb 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -513,6 +513,8 @@
     #
     'test_nacl_source_files': [
       # Test cases (PLEASE KEEP THIS SECTION IN ALPHABETICAL ORDER)
+      'tests/test_nacl_irt_stack_alignment.cc',
+      'tests/test_nacl_irt_stack_alignment.h',
       'tests/test_tcp_server_socket_private_disallowed.cc',
       'tests/test_tcp_socket_private_disallowed.cc',
       'tests/test_udp_socket_private_disallowed.cc',
diff --git a/ppapi/tests/test_flash_fullscreen.cc b/ppapi/tests/test_flash_fullscreen.cc
index 4d17f19d..fe43796 100644
--- a/ppapi/tests/test_flash_fullscreen.cc
+++ b/ppapi/tests/test_flash_fullscreen.cc
@@ -10,6 +10,7 @@
 
 #include "ppapi/c/private/ppb_flash_fullscreen.h"
 #include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/input_event.h"
 #include "ppapi/cpp/instance.h"
 #include "ppapi/cpp/module.h"
 #include "ppapi/cpp/point.h"
@@ -66,30 +67,27 @@
   if (screen_mode_.IsFullscreen())
     return ReportError("IsFullscreen() at start", true);
 
+  // This is only allowed within a contet of a user gesture (e.g. mouse click).
+  if (screen_mode_.SetFullscreen(true))
+    return ReportError("SetFullscreen(true) outside of user gesture", true);
+
   // 1. Switch to fullscreen.
   // The transition is asynchronous and ends at the next DidChangeView().
   // No graphics devices can be bound while in transition.
   fullscreen_pending_ = true;
-  if (!screen_mode_.SetFullscreen(true))
-    return ReportError("SetFullscreen(true) in normal", false);
-  pp::Graphics2D graphics2d_fullscreen(instance_, pp::Size(10, 10), false);
-  if (graphics2d_fullscreen.is_null())
-    return "Failed to create graphics2d_fullscreen";
-  // The out-of-process proxy is asynchronous, so testing for the following
-  // conditions is flaky and can only be done reliably in-process.
-  if (!testing_interface_->IsOutOfProcess()) {
-    if (instance_->BindGraphics(graphics2d_fullscreen))
-      return ReportError("BindGraphics() in fullscreen transition", true);
-    if (screen_mode_.IsFullscreen())
-      return ReportError("IsFullscreen() in fullscreen transtion", true);
-  }
-
+  instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+  SimulateUserGesture();
   // DidChangeView() will call the callback once in fullscreen mode.
   fullscreen_event_.Wait();
+  if (GotError())
+    return Error();
   if (fullscreen_pending_)
     return "fullscreen_pending_ has not been reset";
   if (!screen_mode_.IsFullscreen())
     return ReportError("IsFullscreen() in fullscreen", false);
+  pp::Graphics2D graphics2d_fullscreen(instance_, pp::Size(10, 10), false);
+  if (graphics2d_fullscreen.is_null())
+    return "Failed to create graphics2d_fullscreen";
   if (!instance_->BindGraphics(graphics2d_fullscreen))
     return ReportError("BindGraphics() in fullscreen", false);
 
@@ -137,6 +135,8 @@
 void TestFlashFullscreen::DidChangeView(const pp::View& view) {
   pp::Rect position = view.GetRect();
   pp::Rect clip = view.GetClipRect();
+  if (normal_position_.IsEmpty())
+    normal_position_ = view.GetRect();
   if (fullscreen_pending_ && IsFullscreenView(position, clip, screen_size_)) {
     fullscreen_pending_ = false;
     fullscreen_event_.Signal();
@@ -147,3 +147,58 @@
       normal_event_.Signal();
   }
 }
+
+void TestFlashFullscreen::SimulateUserGesture() {
+  pp::Point plugin_center(
+      normal_position_.x() + normal_position_.width() / 2,
+      normal_position_.y() + normal_position_.height() / 2);
+  pp::Point mouse_movement;
+  pp::MouseInputEvent input_event(
+      instance_,
+      PP_INPUTEVENT_TYPE_MOUSEDOWN,
+      0,  // time_stamp
+      0,  // modifiers
+      PP_INPUTEVENT_MOUSEBUTTON_LEFT,
+      plugin_center,
+      1,  // click_count
+      mouse_movement);
+
+  testing_interface_->SimulateInputEvent(instance_->pp_instance(),
+                                         input_event.pp_resource());
+}
+
+bool TestFlashFullscreen::GotError() {
+  return !error_.empty();
+}
+
+std::string TestFlashFullscreen::Error() {
+  std::string last_error = error_;
+  error_.clear();
+  return last_error;
+}
+
+void TestFlashFullscreen::FailFullscreenTest(const std::string& error) {
+  error_ = error;
+  fullscreen_event_.Signal();
+}
+
+bool TestFlashFullscreen::HandleInputEvent(const pp::InputEvent& event) {
+  if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
+      event.GetType() != PP_INPUTEVENT_TYPE_MOUSEUP) {
+    return false;
+  }
+
+  instance_->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE);
+  if (screen_mode_.IsFullscreen()) {
+    FailFullscreenTest(
+        ReportError("IsFullscreen() before fullscreen transition", true));
+    return false;
+  }
+  if (!screen_mode_.SetFullscreen(true)) {
+    FailFullscreenTest(
+        ReportError("SetFullscreen(true) in normal", false));
+    return false;
+  }
+  // DidChangeView() will complete the transition to fullscreen.
+  return false;
+}
diff --git a/ppapi/tests/test_flash_fullscreen.h b/ppapi/tests/test_flash_fullscreen.h
index d9f742f0..7ee22d8 100644
--- a/ppapi/tests/test_flash_fullscreen.h
+++ b/ppapi/tests/test_flash_fullscreen.h
@@ -24,13 +24,21 @@
   virtual bool Init();
   virtual void RunTests(const std::string& filter);
   virtual void DidChangeView(const pp::View& view);
+  bool HandleInputEvent(const pp::InputEvent& event) override;
 
  private:
   std::string TestGetScreenSize();
   std::string TestNormalToFullscreenToNormal();
+  void SimulateUserGesture();
+  bool GotError();
+  std::string Error();
+  void FailFullscreenTest(const std::string& error);
+
+  std::string error_;
 
   pp::FlashFullscreen screen_mode_;
   pp::Size screen_size_;
+  pp::Rect normal_position_;
 
   bool fullscreen_pending_;
   bool normal_pending_;
diff --git a/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc b/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc
index 0e37339..7c61bea6 100644
--- a/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc
+++ b/ppapi/tests/test_flash_fullscreen_for_browser_ui.cc
@@ -17,6 +17,7 @@
       screen_mode_(instance),
       view_change_event_(instance->pp_instance()),
       num_trigger_events_(0),
+      request_fullscreen_(false),
       callback_factory_(this) {
   // This plugin should not be removed after this TestCase passes because
   // browser UI testing requires it to remain and to be interactive.
@@ -38,15 +39,28 @@
   if (screen_mode_.IsFullscreen())
     return ReportError("IsFullscreen() at start", true);
 
+  // This is only allowed within a contet of a user gesture (e.g. mouse click).
+  if (screen_mode_.SetFullscreen(true))
+    return ReportError("SetFullscreen(true) outside of user gesture", true);
+
+  // Trigger another call to SetFullscreen(true) from HandleInputEvent().
+  // The transition is asynchronous and ends at the next DidChangeView().
   view_change_event_.Reset();
-  if (!screen_mode_.SetFullscreen(true))
-    return ReportError("SetFullscreen(true) in normal", false);
+  request_fullscreen_ = true;
+  instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+  SimulateUserGesture();
   // DidChangeView() will call the callback once in fullscreen mode.
   view_change_event_.Wait();
+  if (GotError())
+    return Error();
 
   if (!screen_mode_.IsFullscreen())
     return ReportError("IsFullscreen() in fullscreen", false);
 
+  compositor_ = pp::Compositor(instance_);
+  instance_->BindGraphics(compositor_);
+  color_layer_ = compositor_.AddLayer();
+
   const int32_t result =
       instance_->RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
                                              PP_INPUTEVENT_CLASS_KEYBOARD);
@@ -57,22 +71,76 @@
 }
 
 void TestFlashFullscreenForBrowserUI::DidChangeView(const pp::View& view) {
-  compositor_ = pp::Compositor(instance_);
-  instance_->BindGraphics(compositor_);
   layer_size_ = view.GetRect().size();
-  color_layer_ = compositor_.AddLayer();
-  Paint(PP_OK);
+  if (normal_position_.IsEmpty())
+    normal_position_ = view.GetRect();
 
+  if (!compositor_.is_null())
+    Paint(PP_OK);
+
+  view_change_event_.Signal();
+}
+
+void TestFlashFullscreenForBrowserUI::SimulateUserGesture() {
+  pp::Point plugin_center(
+      normal_position_.x() + normal_position_.width() / 2,
+      normal_position_.y() + normal_position_.height() / 2);
+  pp::Point mouse_movement;
+  pp::MouseInputEvent input_event(
+      instance_,
+      PP_INPUTEVENT_TYPE_MOUSEDOWN,
+      0,  // time_stamp
+      0,  // modifiers
+      PP_INPUTEVENT_MOUSEBUTTON_LEFT,
+      plugin_center,
+      1,  // click_count
+      mouse_movement);
+
+  testing_interface_->SimulateInputEvent(instance_->pp_instance(),
+                                         input_event.pp_resource());
+}
+
+bool TestFlashFullscreenForBrowserUI::GotError() {
+  return !error_.empty();
+}
+
+std::string TestFlashFullscreenForBrowserUI::Error() {
+  std::string last_error = error_;
+  error_.clear();
+  return last_error;
+}
+
+void TestFlashFullscreenForBrowserUI::FailFullscreenTest(
+    const std::string& error) {
+  error_ = error;
   view_change_event_.Signal();
 }
 
 bool TestFlashFullscreenForBrowserUI::HandleInputEvent(
     const pp::InputEvent& event) {
   if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
+      event.GetType() != PP_INPUTEVENT_TYPE_MOUSEUP &&
       event.GetType() != PP_INPUTEVENT_TYPE_CHAR) {
     return false;
   }
 
+  if (request_fullscreen_) {
+    instance_->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE);
+    if (screen_mode_.IsFullscreen()) {
+      FailFullscreenTest(
+          ReportError("IsFullscreen() before fullscreen transition", true));
+      return false;
+    }
+    request_fullscreen_ = false;
+    if (!screen_mode_.SetFullscreen(true)) {
+      FailFullscreenTest(
+          ReportError("SetFullscreen(true) in normal", false));
+      return false;
+    }
+    // DidChangeView() will complete the transition to fullscreen.
+    return false;
+  }
+
   ++num_trigger_events_;
 
   return true;
diff --git a/ppapi/tests/test_flash_fullscreen_for_browser_ui.h b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
index 0ae3741..de5d2e6 100644
--- a/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
+++ b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
@@ -40,6 +40,12 @@
  private:
   std::string TestEnterFullscreen();
   void Paint(int32_t last_compositor_result);
+  void SimulateUserGesture();
+  bool GotError();
+  std::string Error();
+  void FailFullscreenTest(const std::string& error);
+
+  std::string error_;
 
   pp::FlashFullscreen screen_mode_;
   NestedEvent view_change_event_;
@@ -47,8 +53,10 @@
   pp::Compositor compositor_;
   pp::Size layer_size_;
   pp::CompositorLayer color_layer_;
+  pp::Rect normal_position_;
 
   int num_trigger_events_;
+  bool request_fullscreen_;
 
   pp::CompletionCallbackFactory<TestFlashFullscreenForBrowserUI>
       callback_factory_;
diff --git a/ppapi/tests/test_nacl_irt_stack_alignment.cc b/ppapi/tests/test_nacl_irt_stack_alignment.cc
new file mode 100644
index 0000000..3766d4d
--- /dev/null
+++ b/ppapi/tests/test_nacl_irt_stack_alignment.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2015 The Chromium Authors. 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/tests/test_nacl_irt_stack_alignment.h"
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/tests/testing_instance.h"
+
+// This whole test is really only meant for x86-32 NaCl.
+//
+// This is a regression test for the IRT code being sensitive to stack
+// alignment.  The de jure ABI is that the stack should be aligned to
+// 16 bytes at call sites.  However, the de facto ABI is that the IRT
+// worked in the past when called with misaligned stack.  NaCl code is
+// now compiled to expect the proper 16-byte alignment, but the IRT
+// code must remain compatible with old binaries that failed to do so.
+
+#if defined(__i386__)
+
+REGISTER_TEST_CASE(NaClIRTStackAlignment);
+
+bool TestNaClIRTStackAlignment::Init() {
+  var_interface_ = static_cast<const PPB_Var*>(
+      pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
+  return var_interface_ && CheckTestingInterface();
+}
+
+void TestNaClIRTStackAlignment::RunTests(const std::string& filter) {
+  RUN_TEST(MisalignedCallVarAddRef, filter);
+}
+
+// This calls the given function with the stack explicitly misaligned.
+// If the function (in the IRT) was compiled wrongly, it will crash.
+void MisalignedCall(void (*func)(PP_Var), const PP_Var* arg)
+    asm("MisalignedCall") __attribute__((regparm(2)));
+
+// regparm(2) means: First argument in %eax, second argument in %edx.
+// Writing this with an inline asm would require explaining all the
+// call-clobbers register behavior in the asm clobber list, which is a
+// lot with all the SSE and FPU state.  It's far simpler just to make
+// it a function call the compiler knows is a function call, and then
+// write the function itself in pure assembly.
+asm("MisalignedCall:\n"
+    // Use an SSE register to copy the 16 bytes of memory.
+    // Note this instruction does not care about alignment.
+    // The pointer is not necessarily aligned to 16 bytes.
+    "movups (%edx), %xmm0\n"
+    // Set up a frame so we can recover the stack pointer after alignment.
+    "push %ebp\n"
+    "mov %esp, %ebp\n"
+    // Align the stack properly to 16 bytes.
+    "andl $-16, %esp\n"
+    // Now make space for the 16 bytes of argument data,
+    // plus another 4 bytes so the stack pointer is misaligned.
+    "subl $20, %esp\n"
+    // Copy the argument onto the (misaligned) top of stack.
+    "movups %xmm0, (%esp)\n"
+    // Now call into the IRT, and hilarity ensues.
+    "naclcall %eax\n"
+    // Standard epilogue.
+    "mov %ebp, %esp\n"
+    "pop %ebp\n"
+    "naclret");
+
+std::string TestNaClIRTStackAlignment::TestMisalignedCallVarAddRef() {
+  PP_Var var;
+  var.type = PP_VARTYPE_INT32;
+  var.padding = 0;
+  var.value.as_int = 23;
+
+  ASSERT_EQ(sizeof(var), static_cast<size_t>(16));
+
+  // This will crash if the test fails.
+  MisalignedCall(var_interface_->AddRef, &var);
+  MisalignedCall(var_interface_->Release, &var);
+
+  PASS();
+}
+
+#endif  // defined(__i386__)
diff --git a/ppapi/tests/test_nacl_irt_stack_alignment.h b/ppapi/tests/test_nacl_irt_stack_alignment.h
new file mode 100644
index 0000000..61de76f
--- /dev/null
+++ b/ppapi/tests/test_nacl_irt_stack_alignment.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2015 The Chromium Authors. 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_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_
+#define PPAPI_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_
+
+#include <string>
+
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/tests/test_case.h"
+
+class TestNaClIRTStackAlignment : public TestCase {
+ public:
+  explicit TestNaClIRTStackAlignment(TestingInstance* instance)
+      : TestCase(instance) {}
+
+ private:
+  // TestCase implementation.
+  virtual bool Init();
+  virtual void RunTests(const std::string& filter);
+
+  std::string TestMisalignedCallVarAddRef();
+
+  // Used by the tests that access the C API directly.
+  const PPB_Var* var_interface_;
+};
+
+#endif  // PPAPI_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
index 28c9e09..b140fe47 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -301,11 +301,14 @@
     public void onDestroy() {
         super.onDestroy();
         JniInterface.disconnectFromHost();
+        mAccountSwitcher.destroy();
     }
 
     /** Called when a child Activity exits and sends a result back to this Activity. */
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mAccountSwitcher.onActivityResult(requestCode, resultCode, data);
+
         if (requestCode == OAuthTokenFetcher.REQUEST_CODE_RECOVER_FROM_OAUTH_ERROR) {
             if (resultCode == RESULT_OK) {
                 // User gave OAuth permission to this app (or recovered from any OAuth failure),
@@ -338,6 +341,8 @@
             mRefreshButton.setEnabled(false);
         }
 
+        ChromotingUtil.tintMenuIcons(this, menu);
+
         return super.onCreateOptionsMenu(menu);
     }
 
diff --git a/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java
new file mode 100644
index 0000000..a094cbec
--- /dev/null
+++ b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java
@@ -0,0 +1,33 @@
+// Copyright 2015 The Chromium 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.chromoting;
+
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.Menu;
+
+/** Utility methods for chromoting code. */
+public abstract class ChromotingUtil {
+    /**
+     * Tints all icons of a toolbar menu so they have the same color as the 'back' navigation icon
+     * and the three-dots overflow icon.
+     * @param context Context for getting theme and resource information.
+     * @param menu Menu with icons to be tinted.
+     */
+    public static void tintMenuIcons(Context context, Menu menu) {
+        TypedValue typedValue = new TypedValue();
+        context.getTheme().resolveAttribute(R.attr.colorControlNormal, typedValue, true);
+        int color = context.getResources().getColor(typedValue.resourceId);
+        int items = menu.size();
+        for (int i = 0; i < items; i++) {
+            Drawable icon = menu.getItem(i).getIcon();
+            if (icon != null) {
+                icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
+            }
+        }
+    }
+}
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
index e6be7c49..52098fd 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -129,6 +129,8 @@
         MenuItem item = menu.findItem(R.id.actionbar_cardboard);
         item.setVisible(enableCardboard);
 
+        ChromotingUtil.tintMenuIcons(this, menu);
+
         return super.onCreateOptionsMenu(menu);
     }
 
diff --git a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcher.java b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcher.java
index 5efccca..c422a27c 100644
--- a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcher.java
+++ b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcher.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chromoting.accountswitcher;
 
+import android.content.Intent;
 import android.view.View;
 
 /** Common interface for account-switcher implementations. */
@@ -72,4 +73,16 @@
      * that a valid account is selected, or that the list is empty.
      */
     void reloadAccounts();
+
+    /**
+     * This should be called from the controlling activity's onActivityResult() method. It allows
+     * the account-switcher implementation to launch a child Activity and handle the result.
+     */
+    void onActivityResult(int requestCode, int resultCode, Intent data);
+
+    /**
+     * Releases any resources used by the account-switcher. Should be called by the activity's
+     * onDestroy() method.
+     */
+    void destroy();
 }
diff --git a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherBasic.java b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherBasic.java
index 74ed6371..33b44932 100644
--- a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherBasic.java
+++ b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherBasic.java
@@ -7,6 +7,7 @@
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.Context;
+import android.content.Intent;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.LinearLayout;
@@ -112,4 +113,12 @@
 
         mCallback.onAccountSelected(mSelectedAccount);
     }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+    }
+
+    @Override
+    public void destroy() {
+    }
 }
diff --git a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherFactory.java b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherFactory.java
index ab7af74..4e6f276 100644
--- a/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherFactory.java
+++ b/remoting/android/java/src/org/chromium/chromoting/accountswitcher/AccountSwitcherFactory.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chromoting.accountswitcher;
 
-import android.content.Context;
+import android.app.Activity;
 
 /**
  * Factory class for creating AccountSwitcher implementations. This enables official builds of
@@ -28,12 +28,12 @@
      * Factory method to create an AccountSwitcher. This method returns the public implementation,
      * but it can be overridden to provide an alternative account-switcher implementation. This is
      * called during the Activity's onCreate() handler.
-     * @param context Context used for UI operations.
+     * @param activity Activity used for UI operations.
      * @param callback Callback for receiving notifications from the account-switcher.
      */
-    public AccountSwitcher createAccountSwitcher(Context context,
+    public AccountSwitcher createAccountSwitcher(Activity activity,
             AccountSwitcher.Callback callback) {
-        return new AccountSwitcherBasic(context, callback);
+        return new AccountSwitcherBasic(activity, callback);
     }
 
     /**
diff --git a/remoting/codec/video_encoder_helper.cc b/remoting/codec/video_encoder_helper.cc
index 5310d01..288ec72a 100644
--- a/remoting/codec/video_encoder_helper.cc
+++ b/remoting/codec/video_encoder_helper.cc
@@ -57,8 +57,7 @@
     }
   }
 
-  // Store the capture time and frame DPI.
-  packet->set_capture_time_ms(frame.capture_time_ms());
+  // Store frame DPI.
   if (!frame.dpi().is_zero()) {
     packet->mutable_format()->set_x_dpi(frame.dpi().x());
     packet->mutable_format()->set_y_dpi(frame.dpi().y());
diff --git a/remoting/codec/video_encoder_helper_unittest.cc b/remoting/codec/video_encoder_helper_unittest.cc
index e464802..569ecac 100644
--- a/remoting/codec/video_encoder_helper_unittest.cc
+++ b/remoting/codec/video_encoder_helper_unittest.cc
@@ -36,7 +36,6 @@
   EXPECT_TRUE(packet->format().has_x_dpi());
   EXPECT_TRUE(packet->format().has_y_dpi());
 
-  EXPECT_TRUE(packet->has_capture_time_ms());
   EXPECT_EQ(1, packet->dirty_rects().size());
 
   ASSERT_TRUE(packet->has_use_desktop_shape());
diff --git a/remoting/codec/video_encoder_verbatim.cc b/remoting/codec/video_encoder_verbatim.cc
index 2948e3e..8d1befb 100644
--- a/remoting/codec/video_encoder_verbatim.cc
+++ b/remoting/codec/video_encoder_verbatim.cc
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/time/time.h"
 #include "remoting/base/util.h"
 #include "remoting/proto/video.pb.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
@@ -32,8 +31,6 @@
   if (frame.updated_region().is_empty())
     return nullptr;
 
-  base::Time encode_start_time = base::Time::Now();
-
   // Create a VideoPacket with common fields (e.g. DPI, rects, shape) set.
   scoped_ptr<VideoPacket> packet(helper_.CreateVideoPacket(frame));
   packet->mutable_format()->set_encoding(VideoPacketFormat::ENCODING_VERBATIM);
@@ -64,10 +61,6 @@
     }
   }
 
-  // Note the time taken to encode the pixel data.
-  packet->set_encode_time_ms(
-      (base::Time::Now() - encode_start_time).InMillisecondsRoundedUp());
-
   return packet.Pass();
 }
 
diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc
index 1fa19a4..0dcd456 100644
--- a/remoting/codec/video_encoder_vpx.cc
+++ b/remoting/codec/video_encoder_vpx.cc
@@ -270,8 +270,6 @@
   if (frame.updated_region().is_empty() && !encode_unchanged_frame_)
     return nullptr;
 
-  base::TimeTicks encode_start_time = base::TimeTicks::Now();
-
   // Create or reconfigure the codec to match the size of |frame|.
   if (!codec_ ||
       (image_ &&
@@ -296,7 +294,7 @@
   }
 
   // Do the actual encoding.
-  int timestamp = (encode_start_time - timestamp_base_).InMilliseconds();
+  int timestamp = (base::TimeTicks::Now() - timestamp_base_).InMilliseconds();
   vpx_codec_err_t ret = vpx_codec_encode(
       codec_.get(), image_.get(), timestamp, 1, 0, VPX_DL_REALTIME);
   DCHECK_EQ(ret, VPX_CODEC_OK)
@@ -341,10 +339,6 @@
     }
   }
 
-  // Note the time taken to encode the pixel data.
-  packet->set_encode_time_ms(
-      (base::TimeTicks::Now() - encode_start_time).InMillisecondsRoundedUp());
-
   return packet.Pass();
 }
 
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc
index 18b3c66..fb404e8 100644
--- a/remoting/host/client_session.cc
+++ b/remoting/host/client_session.cc
@@ -404,13 +404,14 @@
   event_handler_->OnSessionClosed(this);
 }
 
-void ClientSession::OnEventTimestamp(protocol::ConnectionToClient* connection,
-                                     int64 timestamp) {
+void ClientSession::OnInputEventReceived(
+    protocol::ConnectionToClient* connection,
+    int64_t event_timestamp) {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(connection_.get(), connection);
 
   if (video_frame_pump_.get())
-    video_frame_pump_->SetLatestEventTimestamp(timestamp);
+    video_frame_pump_->OnInputEventReceived(event_timestamp);
 }
 
 void ClientSession::OnRouteChange(
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h
index 7d344399..d41e83e 100644
--- a/remoting/host/client_session.h
+++ b/remoting/host/client_session.h
@@ -122,8 +122,8 @@
       protocol::ConnectionToClient* connection) override;
   void OnConnectionClosed(protocol::ConnectionToClient* connection,
                           protocol::ErrorCode error) override;
-  void OnEventTimestamp(protocol::ConnectionToClient* connection,
-                        int64 timestamp) override;
+  void OnInputEventReceived(protocol::ConnectionToClient* connection,
+                            int64_t timestamp) override;
   void OnRouteChange(protocol::ConnectionToClient* connection,
                      const std::string& channel_name,
                      const protocol::TransportRoute& route) override;
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index d244f1e..3c60ebe 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -15,6 +15,7 @@
 #include "base/time/time.h"
 #include "remoting/base/constants.h"
 #include "remoting/base/logging.h"
+#include "remoting/host/host_details.h"
 #include "remoting/host/server_log_entry_host.h"
 #include "remoting/signaling/iq_sender.h"
 #include "remoting/signaling/jid_util.h"
@@ -36,6 +37,8 @@
 const char kHeartbeatSignatureTag[] = "signature";
 const char kSequenceIdAttr[] = "sequence-id";
 const char kHostOfflineReasonAttr[] = "host-offline-reason";
+const char kHostOperatingSystemNameTag[] = "os-name";
+const char kHostOperatingSystemVersionTag[] = "os-version";
 
 const char kErrorTag[] = "error";
 const char kNotFoundTag[] = "item-not-found";
@@ -319,6 +322,19 @@
       QName(kChromotingXmlNamespace, kHostVersionTag)));
   version_tag->AddText(STRINGIZE(VERSION));
   heartbeat->AddElement(version_tag.release());
+  // If we have not recorded a heartbeat success, continue sending host OS info.
+  if (!heartbeat_succeeded_) {
+    // Append host OS name.
+    scoped_ptr<XmlElement> os_name_tag(new XmlElement(
+        QName(kChromotingXmlNamespace, kHostOperatingSystemNameTag)));
+    os_name_tag->AddText(GetHostOperatingSystemName());
+    heartbeat->AddElement(os_name_tag.release());
+    // Append host OS version.
+    scoped_ptr<XmlElement> os_version_tag(new XmlElement(
+        QName(kChromotingXmlNamespace, kHostOperatingSystemVersionTag)));
+    os_version_tag->AddText(GetHostOperatingSystemVersion());
+    heartbeat->AddElement(os_version_tag.release());
+  }
   // Append log message (which isn't signed).
   scoped_ptr<XmlElement> log(ServerLogEntry::MakeStanza());
   scoped_ptr<ServerLogEntry> log_entry(MakeLogEntryForHeartbeat());
diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc
index 35a9782..33ef1f4 100644
--- a/remoting/host/heartbeat_sender_unittest.cc
+++ b/remoting/host/heartbeat_sender_unittest.cc
@@ -69,7 +69,6 @@
   void SetUp() override {
     key_pair_ = RsaKeyPair::FromString(kTestRsaKeyPair);
     ASSERT_TRUE(key_pair_.get());
-
     EXPECT_CALL(signal_strategy_, GetState())
         .WillOnce(Return(SignalStrategy::DISCONNECTED));
     EXPECT_CALL(signal_strategy_, AddListener(NotNull()))
@@ -332,6 +331,39 @@
   base::RunLoop().RunUntilIdle();
 }
 
+// The first heartbeat should include host OS information.
+TEST_F(HeartbeatSenderTest, HostOSInfo) {
+  XmlElement* sent_iq = nullptr;
+  EXPECT_CALL(signal_strategy_, GetLocalJid())
+      .WillRepeatedly(Return(kTestJid));
+  EXPECT_CALL(signal_strategy_, GetNextId())
+      .WillOnce(Return(kStanzaId));
+  EXPECT_CALL(signal_strategy_, SendStanzaPtr(NotNull()))
+      .WillOnce(DoAll(SaveArg<0>(&sent_iq), Return(true)));
+  EXPECT_CALL(signal_strategy_, GetState())
+      .WillRepeatedly(Return(SignalStrategy::CONNECTED));
+
+  heartbeat_sender_->OnSignalStrategyStateChange(SignalStrategy::CONNECTED);
+  base::RunLoop().RunUntilIdle();
+
+  scoped_ptr<XmlElement> stanza(sent_iq);
+  ASSERT_TRUE(stanza != nullptr);
+
+  XmlElement* heartbeat_stanza =
+      stanza->FirstNamed(QName(kChromotingXmlNamespace, "heartbeat"));
+
+  std::string os_name =
+      heartbeat_stanza->TextNamed(QName(kChromotingXmlNamespace, "os-name"));
+  EXPECT_TRUE(!os_name.empty());
+
+  std::string os_version =
+      heartbeat_stanza->TextNamed(QName(kChromotingXmlNamespace, "os-version"));
+  EXPECT_TRUE(!os_version.empty());
+
+  heartbeat_sender_->OnSignalStrategyStateChange(SignalStrategy::DISCONNECTED);
+  base::RunLoop().RunUntilIdle();
+}
+
 // Validate a heartbeat stanza.
 void HeartbeatSenderTest::ValidateHeartbeatStanza(
     XmlElement* stanza,
diff --git a/remoting/host/host_details.cc b/remoting/host/host_details.cc
new file mode 100644
index 0000000..d9e792a
--- /dev/null
+++ b/remoting/host/host_details.cc
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/host_details.h"
+
+#include "base/sys_info.h"
+
+#if defined(OS_LINUX)
+#include "base/linux_util.h"
+#endif
+
+namespace remoting {
+
+// Get the host Operating System Name, removing the need to check for OS
+// definitions and keeps the keys used consistant.
+std::string GetHostOperatingSystemName() {
+#if defined(OS_WIN)
+  return "Windows";
+#elif defined(OS_MACOSX)
+  return "Mac";
+#elif defined(OS_CHROMEOS)
+  return "ChromeOS";
+#elif defined(OS_LINUX)
+  return "Linux";
+#endif
+}
+
+// Get the host Operating System Version, removing the need to check for OS
+// definitions and keeps the format used consistant.
+std::string GetHostOperatingSystemVersion() {
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+  return base::SysInfo::OperatingSystemVersion();
+#elif defined(OS_LINUX)
+  return base::GetLinuxDistro();
+#endif
+}
+
+}  // namespace remoting
diff --git a/remoting/host/host_details.h b/remoting/host/host_details.h
new file mode 100644
index 0000000..fdc010b
--- /dev/null
+++ b/remoting/host/host_details.h
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_HOST_DETAILS_H_
+#define REMOTING_HOST_HOST_DETAILS_H_
+
+#include <string>
+
+namespace remoting {
+
+// Returns the host OS name in a standard format for any build target.
+std::string GetHostOperatingSystemName();
+
+// Returns the host OS version in a standard format for any build target.
+std::string GetHostOperatingSystemVersion();
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_HOST_DETAILS_H_
diff --git a/remoting/host/linux/linux_me2me_host.py b/remoting/host/linux/linux_me2me_host.py
index 294985f..703c2c9 100755
--- a/remoting/host/linux/linux_me2me_host.py
+++ b/remoting/host/linux/linux_me2me_host.py
@@ -631,7 +631,10 @@
     paths_to_try = [ SCRIPT_DIR ]
   else:
     paths_to_try = map(lambda p: os.path.join(SCRIPT_DIR, p),
-                       [".", "../../../out/Debug", "../../../out/Release" ])
+                       [".",
+                        "../../../out/Debug",
+                        "../../../out/Default",
+                        "../../../out/Release"])
   for path in paths_to_try:
     exe_path = os.path.join(path, exe_name)
     if os.path.exists(exe_path):
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 88fed82..86bcc054 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -96,6 +96,7 @@
 #if defined(OS_LINUX)
 #include <gtk/gtk.h>
 #include <X11/Xlib.h>
+#include <base/linux_util.h>
 #include "remoting/host/audio_capturer_linux.h"
 #endif  // defined(OS_LINUX)
 
@@ -1615,6 +1616,10 @@
   // Continue windows, though these should not be used for the Me2Me case
   // (crbug.com/104377).
   gtk_init(nullptr, nullptr);
+
+  // Need to prime the host OS version value for linux to prevent IO on the
+  // network thread. base::GetLinuxDistro() caches the result.
+  base::GetLinuxDistro();
 #endif
 
   // Enable support for SSL server sockets, which must be done while still
diff --git a/remoting/host/server_log_entry_host.cc b/remoting/host/server_log_entry_host.cc
index 7c25865..f8644963 100644
--- a/remoting/host/server_log_entry_host.cc
+++ b/remoting/host/server_log_entry_host.cc
@@ -5,11 +5,9 @@
 #include "remoting/host/server_log_entry_host.h"
 
 #include "base/strings/stringize_macros.h"
-#include "base/sys_info.h"
+#include "remoting/host/host_details.h"
 #include "remoting/signaling/server_log_entry.h"
 
-using base::SysInfo;
-
 namespace remoting {
 
 namespace {
@@ -23,10 +21,7 @@
 const char kValueSessionStateClosed[] = "closed";
 
 const char kKeyOsName[] = "os-name";
-
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
 const char kKeyOsVersion[] = "os-version";
-#endif
 
 const char kKeyHostVersion[] = "host-version";
 
@@ -55,30 +50,10 @@
 }
 
 void AddHostFieldsToLogEntry(ServerLogEntry* entry) {
-#if defined(OS_WIN)
-  entry->Set(kKeyOsName, "Windows");
-#elif defined(OS_MACOSX)
-  entry->Set(kKeyOsName, "Mac");
-#elif defined(OS_CHROMEOS)
-  entry->Set(kKeyOsName, "ChromeOS");
-#elif defined(OS_LINUX)
-  entry->Set(kKeyOsName, "Linux");
-#endif
-
-  // SysInfo::OperatingSystemVersionNumbers is only defined for the following
-  // OSes: see base/sys_info_unittest.cc.
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
-  std::stringstream os_version;
-  int32 os_major_version = 0;
-  int32 os_minor_version = 0;
-  int32 os_bugfix_version = 0;
-  SysInfo::OperatingSystemVersionNumbers(&os_major_version, &os_minor_version,
-                                         &os_bugfix_version);
-  os_version << os_major_version << "." << os_minor_version << "."
-             << os_bugfix_version;
-  entry->Set(kKeyOsVersion, os_version.str());
-#endif
-
+  // TODO os name, os version, and version will be in the main message body,
+  // remove these fields at a later date to remove redundancy.
+  entry->Set(kKeyOsName, GetHostOperatingSystemName());
+  entry->Set(kKeyOsVersion, GetHostOperatingSystemVersion());
   entry->Set(kKeyHostVersion, STRINGIZE(VERSION));
   entry->AddCpuField();
 };
diff --git a/remoting/host/server_log_entry_host_unittest.cc b/remoting/host/server_log_entry_host_unittest.cc
index d249c03..7d69eec 100644
--- a/remoting/host/server_log_entry_host_unittest.cc
+++ b/remoting/host/server_log_entry_host_unittest.cc
@@ -62,6 +62,7 @@
   keys.insert("os-version");
 #elif defined(OS_LINUX)
   key_value_pairs["os-name"] = "Linux";
+  keys.insert("os-version");
 #endif
 
   // The check below will compile but fail if VERSION isn't defined (STRINGIZE
diff --git a/remoting/host/video_frame_pump.cc b/remoting/host/video_frame_pump.cc
index 37d9da7..58b72db 100644
--- a/remoting/host/video_frame_pump.cc
+++ b/remoting/host/video_frame_pump.cc
@@ -20,28 +20,6 @@
 
 namespace remoting {
 
-namespace {
-
-scoped_ptr<VideoPacket> EncodeFrame(VideoEncoder* encoder,
-                                    scoped_ptr<webrtc::DesktopFrame> frame) {
-  scoped_ptr<VideoPacket> packet;
-
-  // If |frame| is non-NULL then let the encoder process it.
-  if (frame) {
-    packet = encoder->Encode(*frame);
-  }
-
-  // If |frame| is NULL, or the encoder returned nothing, return an empty
-  // packet.
-  if (!packet) {
-    packet.reset(new VideoPacket());
-  }
-
-  return packet.Pass();
-}
-
-}  // namespace
-
 // Interval between empty keep-alive frames. These frames are sent only when the
 // stream is paused or inactive for some other reason (e.g. when blocked on
 // capturer). To prevent PseudoTCP from resetting congestion window this value
@@ -50,6 +28,16 @@
 
 static bool g_enable_timestamps = false;
 
+VideoFramePump::FrameTimestamps::FrameTimestamps() {}
+VideoFramePump::FrameTimestamps::~FrameTimestamps() {}
+
+VideoFramePump::PacketWithTimestamps::PacketWithTimestamps(
+    scoped_ptr<VideoPacket> packet,
+    scoped_ptr<FrameTimestamps> timestamps)
+    : packet(packet.Pass()), timestamps(timestamps.Pass()) {}
+
+VideoFramePump::PacketWithTimestamps::~PacketWithTimestamps() {}
+
 // static
 void VideoFramePump::EnableTimestampsForTests() {
   g_enable_timestamps = true;
@@ -72,7 +60,6 @@
           false),
       capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
                                     base::Unretained(this))),
-      latest_event_timestamp_(0),
       weak_factory_(this) {
   DCHECK(encoder_);
   DCHECK(video_stub_);
@@ -91,10 +78,13 @@
   capture_scheduler_.Pause(pause);
 }
 
-void VideoFramePump::SetLatestEventTimestamp(int64 latest_event_timestamp) {
+void VideoFramePump::OnInputEventReceived(int64_t event_timestamp) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  latest_event_timestamp_ = latest_event_timestamp;
+  if (!next_frame_timestamps_)
+    next_frame_timestamps_.reset(new FrameTimestamps());
+  next_frame_timestamps_->input_event_client_timestamp = event_timestamp;
+  next_frame_timestamps_->input_event_received_time = base::TimeTicks::Now();
 }
 
 void VideoFramePump::SetLosslessEncode(bool want_lossless) {
@@ -123,45 +113,126 @@
 
   capture_scheduler_.OnCaptureCompleted();
 
+  captured_frame_timestamps_->capture_ended_time = base::TimeTicks::Now();
+
   // Even when |frame| is nullptr we still need to post it to the encode thread
   // to make sure frames are freed in the same order they are received and
   // that we don't start capturing frame n+2 before frame n is freed.
   base::PostTaskAndReplyWithResult(
       encode_task_runner_.get(), FROM_HERE,
-      base::Bind(&EncodeFrame, encoder_.get(),
-                 base::Passed(make_scoped_ptr(frame))),
-      base::Bind(&VideoFramePump::SendEncodedFrame, weak_factory_.GetWeakPtr(),
-                 latest_event_timestamp_, base::TimeTicks::Now()));
+      base::Bind(&VideoFramePump::EncodeFrame, encoder_.get(),
+                 base::Passed(make_scoped_ptr(frame)),
+                 base::Passed(&captured_frame_timestamps_)),
+      base::Bind(&VideoFramePump::OnFrameEncoded, weak_factory_.GetWeakPtr()));
 }
 
 void VideoFramePump::CaptureNextFrame() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  // |next_frame_timestamps_| is not set if no input events were received since
+  // the previous frame. In that case create FrameTimestamps instance without
+  // setting |input_event_client_timestamp| and |input_event_received_time|.
+  if (!next_frame_timestamps_)
+    next_frame_timestamps_.reset(new FrameTimestamps());
+
+  captured_frame_timestamps_ = next_frame_timestamps_.Pass();
+  captured_frame_timestamps_->capture_started_time = base::TimeTicks::Now();
+
   capturer_->Capture(webrtc::DesktopRegion());
 }
 
-void VideoFramePump::SendEncodedFrame(int64 latest_event_timestamp,
-                                      base::TimeTicks timestamp,
-                                      scoped_ptr<VideoPacket> packet) {
+// static
+scoped_ptr<VideoFramePump::PacketWithTimestamps> VideoFramePump::EncodeFrame(
+    VideoEncoder* encoder,
+    scoped_ptr<webrtc::DesktopFrame> frame,
+    scoped_ptr<FrameTimestamps> timestamps) {
+  timestamps->encode_started_time = base::TimeTicks::Now();
+
+  scoped_ptr<VideoPacket> packet;
+  // If |frame| is non-NULL then let the encoder process it.
+  if (frame)
+    packet = encoder->Encode(*frame);
+
+  // If |frame| is NULL, or the encoder returned nothing, return an empty
+  // packet.
+  if (!packet)
+    packet.reset(new VideoPacket());
+
+  if (frame)
+    packet->set_capture_time_ms(frame->capture_time_ms());
+
+  timestamps->encode_ended_time = base::TimeTicks::Now();
+
+  return make_scoped_ptr(
+      new PacketWithTimestamps(packet.Pass(), timestamps.Pass()));
+}
+
+void VideoFramePump::OnFrameEncoded(scoped_ptr<PacketWithTimestamps> packet) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (g_enable_timestamps)
-    packet->set_timestamp(timestamp.ToInternalValue());
+  capture_scheduler_.OnFrameEncoded(packet->packet.get());
 
-  packet->set_latest_event_timestamp(latest_event_timestamp);
+  if (send_pending_) {
+    pending_packets_.push_back(packet.Pass());
+  } else {
+    SendPacket(packet.Pass());
+  }
+}
 
-  capture_scheduler_.OnFrameEncoded(packet.get());
+void VideoFramePump::SendPacket(scoped_ptr<PacketWithTimestamps> packet) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!send_pending_);
 
-  video_stub_->ProcessVideoPacket(packet.Pass(),
+  packet->timestamps->can_send_time = base::TimeTicks::Now();
+  UpdateFrameTimers(packet->packet.get(), packet->timestamps.get());
+
+  send_pending_ = true;
+  video_stub_->ProcessVideoPacket(packet->packet.Pass(),
                                   base::Bind(&VideoFramePump::OnVideoPacketSent,
                                              weak_factory_.GetWeakPtr()));
 }
 
+void VideoFramePump::UpdateFrameTimers(VideoPacket* packet,
+                                       FrameTimestamps* timestamps) {
+  if (g_enable_timestamps)
+    packet->set_timestamp(timestamps->capture_ended_time.ToInternalValue());
+
+
+  if (!timestamps->input_event_received_time.is_null()) {
+    packet->set_capture_pending_time_ms((timestamps->capture_started_time -
+                                         timestamps->input_event_received_time)
+                                            .InMilliseconds());
+    packet->set_latest_event_timestamp(
+        timestamps->input_event_client_timestamp);
+  }
+
+  packet->set_capture_overhead_time_ms(
+      (timestamps->capture_ended_time - timestamps->capture_started_time)
+          .InMilliseconds() -
+      packet->capture_time_ms());
+
+  packet->set_encode_pending_time_ms(
+      (timestamps->encode_started_time - timestamps->capture_ended_time)
+          .InMilliseconds());
+
+  packet->set_send_pending_time_ms(
+      (timestamps->can_send_time - timestamps->encode_ended_time)
+          .InMilliseconds());
+}
+
 void VideoFramePump::OnVideoPacketSent() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  send_pending_ = false;
   capture_scheduler_.OnFrameSent();
   keep_alive_timer_.Reset();
+
+  // Send next packet if any.
+  if (!pending_packets_.empty()) {
+    scoped_ptr<PacketWithTimestamps> next(pending_packets_.front());
+    pending_packets_.weak_erase(pending_packets_.begin());
+    SendPacket(next.Pass());
+  }
 }
 
 void VideoFramePump::SendKeepAlivePacket() {
diff --git a/remoting/host/video_frame_pump.h b/remoting/host/video_frame_pump.h
index 5bafa3e..f4542caf 100644
--- a/remoting/host/video_frame_pump.h
+++ b/remoting/host/video_frame_pump.h
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -82,9 +83,8 @@
   // only affects capture scheduling and does not stop/start the capturer.
   void Pause(bool pause);
 
-  // Updates event timestamp from the last event received from the client. This
-  // value is sent back to the client for roundtrip latency estimates.
-  void SetLatestEventTimestamp(int64 latest_event_timestamp);
+  // Called whenever input event is received.
+  void OnInputEventReceived(int64_t event_timestamp);
 
   // Sets whether the video encoder should be requested to encode losslessly,
   // or to use a lossless color space (typically requiring higher bandwidth).
@@ -96,6 +96,33 @@
   }
 
  private:
+  struct FrameTimestamps {
+    FrameTimestamps();
+    ~FrameTimestamps();
+
+    // The following two fields are set only for one frame after each incoming
+    // input event. |input_event_client_timestamp| is event timestamp
+    // received from the client. |input_event_received_time| is local time when
+    // the event was received.
+    int64_t input_event_client_timestamp = -1;
+    base::TimeTicks input_event_received_time;
+
+    base::TimeTicks capture_started_time;
+    base::TimeTicks capture_ended_time;
+    base::TimeTicks encode_started_time;
+    base::TimeTicks encode_ended_time;
+    base::TimeTicks can_send_time;
+  };
+
+  struct PacketWithTimestamps {
+    PacketWithTimestamps(scoped_ptr<VideoPacket> packet,
+                         scoped_ptr<FrameTimestamps> timestamps);
+    ~PacketWithTimestamps();
+
+    scoped_ptr<VideoPacket> packet;
+    scoped_ptr<FrameTimestamps> timestamps;
+  };
+
   // webrtc::DesktopCapturer::Callback interface.
   webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
   void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
@@ -103,10 +130,21 @@
   // Callback for CaptureScheduler.
   void CaptureNextFrame();
 
-  // Sends encoded frame
-  void SendEncodedFrame(int64 latest_event_timestamp,
-                        base::TimeTicks timestamp,
-                        scoped_ptr<VideoPacket> packet);
+  // Task running on the encoder thread to encode the |frame|.
+  static scoped_ptr<PacketWithTimestamps> EncodeFrame(
+      VideoEncoder* encoder,
+      scoped_ptr<webrtc::DesktopFrame> frame,
+      scoped_ptr<FrameTimestamps> timestamps);
+
+  // Task called when a frame has finished encoding.
+  void OnFrameEncoded(scoped_ptr<PacketWithTimestamps> packet);
+
+  // Sends |packet| to the client.
+  void SendPacket(scoped_ptr<PacketWithTimestamps> packet);
+
+  // Helper called from SendPacket() to calculate timing fields in the |packet|
+  // before sending it.
+  void UpdateFrameTimers(VideoPacket* packet, FrameTimestamps* timestamps);
 
   // Callback passed to |video_stub_|.
   void OnVideoPacketSent();
@@ -137,8 +175,15 @@
   // captured.
   CaptureScheduler capture_scheduler_;
 
-  // Number updated by the caller to trace performance.
-  int64 latest_event_timestamp_;
+  // Timestamps for the frame to be captured next.
+  scoped_ptr<FrameTimestamps> next_frame_timestamps_;
+
+  // Timestamps for the frame that's being captured.
+  scoped_ptr<FrameTimestamps> captured_frame_timestamps_;
+
+  bool send_pending_ = false;
+
+  ScopedVector<PacketWithTimestamps> pending_packets_;
 
   base::ThreadChecker thread_checker_;
 
diff --git a/remoting/host/win/worker_process_launcher.cc b/remoting/host/win/worker_process_launcher.cc
index 144be97..6daf02f 100644
--- a/remoting/host/win/worker_process_launcher.cc
+++ b/remoting/host/win/worker_process_launcher.cc
@@ -113,7 +113,7 @@
   DCHECK(!process_watcher_.GetWatchedObject());
   DCHECK(!worker_process_.IsValid());
 
-  if (!process_watcher_.StartWatching(worker_process.Get(), this)) {
+  if (!process_watcher_.StartWatchingOnce(worker_process.Get(), this)) {
     StopWorker();
     return;
   }
diff --git a/remoting/proto/video.proto b/remoting/proto/video.proto
index b2b12588..66e7ce2 100644
--- a/remoting/proto/video.proto
+++ b/remoting/proto/video.proto
@@ -71,6 +71,19 @@
 
   // Frame identifier used to match VideoFrame and VideoAck.
   optional int32 frame_id = 13;
+
+  // Time from when the last event was received until capturing has started.
+  optional int64 capture_pending_time_ms = 14;
+
+  // Total overhead time for IPC and threading when capturing frames.
+  optional int64 capture_overhead_time_ms = 15;
+
+  // Time between when the frame was captured and when encoder started encoding
+  // it.
+  optional int64 encode_pending_time_ms = 16;
+
+  // Time for which the frame is blocked until it's sent to the client.
+  optional int64 send_pending_time_ms = 17;
 }
 
 // VideoAck acknowledges that the frame in the VideoPacket with the same
diff --git a/remoting/protocol/connection_to_client.cc b/remoting/protocol/connection_to_client.cc
index fed09fbb..18943f4f 100644
--- a/remoting/protocol/connection_to_client.cc
+++ b/remoting/protocol/connection_to_client.cc
@@ -46,9 +46,9 @@
   session_->Close();
 }
 
-void ConnectionToClient::OnEventTimestamp(int64 sequence_number) {
+void ConnectionToClient::OnInputEventReceived(int64_t timestamp) {
   DCHECK(CalledOnValidThread());
-  handler_->OnEventTimestamp(this, sequence_number);
+  handler_->OnInputEventReceived(this, timestamp);
 }
 
 VideoStub* ConnectionToClient::video_stub() {
@@ -112,8 +112,8 @@
       event_dispatcher_.reset(new HostEventDispatcher());
       event_dispatcher_->Init(session_.get(), session_->config().event_config(),
                               this);
-      event_dispatcher_->set_event_timestamp_callback(base::Bind(
-          &ConnectionToClient::OnEventTimestamp, base::Unretained(this)));
+      event_dispatcher_->set_on_input_event_callback(base::Bind(
+          &ConnectionToClient::OnInputEventReceived, base::Unretained(this)));
 
       video_dispatcher_.reset(new HostVideoDispatcher());
       video_dispatcher_->Init(session_.get(), session_->config().video_config(),
diff --git a/remoting/protocol/connection_to_client.h b/remoting/protocol/connection_to_client.h
index 43c0b1af..2425546 100644
--- a/remoting/protocol/connection_to_client.h
+++ b/remoting/protocol/connection_to_client.h
@@ -52,9 +52,9 @@
     virtual void OnConnectionClosed(ConnectionToClient* connection,
                                     ErrorCode error) = 0;
 
-    // Called when sequence number is updated.
-    virtual void OnEventTimestamp(ConnectionToClient* connection,
-                                  int64 timestamp) = 0;
+    // Called when a new input event is received.
+    virtual void OnInputEventReceived(ConnectionToClient* connection,
+                                      int64_t timestamp) = 0;
 
     // Called on notification of a route change event, which happens when a
     // channel is connected.
@@ -83,7 +83,7 @@
 
   // Callback for HostEventDispatcher to be called with a timestamp for each
   // received event.
-  virtual void OnEventTimestamp(int64 timestamp);
+  virtual void OnInputEventReceived(int64_t timestamp);
 
   // Get the stubs used by the host to transmit messages to the client.
   // The stubs must not be accessed before OnConnectionAuthenticated(), or
diff --git a/remoting/protocol/host_event_dispatcher.cc b/remoting/protocol/host_event_dispatcher.cc
index 8006eac..f3fa8d9d 100644
--- a/remoting/protocol/host_event_dispatcher.cc
+++ b/remoting/protocol/host_event_dispatcher.cc
@@ -19,11 +19,9 @@
       input_stub_(nullptr),
       parser_(base::Bind(&HostEventDispatcher::OnMessageReceived,
                          base::Unretained(this)),
-              reader()) {
-}
+              reader()) {}
 
-HostEventDispatcher::~HostEventDispatcher() {
-}
+HostEventDispatcher::~HostEventDispatcher() {}
 
 void HostEventDispatcher::OnMessageReceived(scoped_ptr<EventMessage> message,
                                             const base::Closure& done_task) {
@@ -31,8 +29,8 @@
 
   base::ScopedClosureRunner done_runner(done_task);
 
-  if (message->has_timestamp() && !event_timestamp_callback_.is_null())
-    event_timestamp_callback_.Run(message->timestamp());
+  if (!on_input_event_callback_.is_null())
+    on_input_event_callback_.Run(message->timestamp());
 
   if (message->has_key_event()) {
     const KeyEvent& event = message->key_event();
diff --git a/remoting/protocol/host_event_dispatcher.h b/remoting/protocol/host_event_dispatcher.h
index 3f1bd88c..8fa3564 100644
--- a/remoting/protocol/host_event_dispatcher.h
+++ b/remoting/protocol/host_event_dispatcher.h
@@ -18,7 +18,7 @@
 // channel to InputStub.
 class HostEventDispatcher : public ChannelDispatcherBase {
  public:
-  typedef base::Callback<void(int64)> EventTimestampCallback;
+  typedef base::Callback<void(int64_t)> OnInputEventCallback;
 
   HostEventDispatcher();
   ~HostEventDispatcher() override;
@@ -30,8 +30,8 @@
 
   // Set callback to notify of each message's sequence number. The
   // callback cannot tear down this object.
-  void set_event_timestamp_callback(const EventTimestampCallback& value) {
-    event_timestamp_callback_ = value;
+  void set_on_input_event_callback(const OnInputEventCallback& value) {
+    on_input_event_callback_ = value;
   }
 
  private:
@@ -39,7 +39,7 @@
                          const base::Closure& done_task);
 
   InputStub* input_stub_;
-  EventTimestampCallback event_timestamp_callback_;
+  OnInputEventCallback on_input_event_callback_;
 
   ProtobufMessageParser<EventMessage> parser_;
 
diff --git a/remoting/protocol/performance_tracker.cc b/remoting/protocol/performance_tracker.cc
index 271336b5..283e59b0 100644
--- a/remoting/protocol/performance_tracker.cc
+++ b/remoting/protocol/performance_tracker.cc
@@ -20,6 +20,13 @@
 const char kVideoFrameRateHistogram[] = "Chromoting.Video.FrameRate";
 const char kVideoPacketRateHistogram[] = "Chromoting.Video.PacketRate";
 const char kVideoBandwidthHistogram[] = "Chromoting.Video.Bandwidth";
+const char kCapturePendingLatencyHistogram[] =
+    "Chromoting.Video.CapturePendingLatency";
+const char kCaptureOverheadHistogram[] = "Chromoting.Video.CaptureOverhead";
+const char kEncodePendingLatencyHistogram[] =
+    "Chromoting.Video.EncodePendingLatency";
+const char kSendPendingLatencyHistogram[] =
+    "Chromoting.Video.SendPendingLatency";
 
 // Custom count and custom time histograms are log-scaled by default. This
 // results in fine-grained buckets at lower values and wider-ranged buckets
@@ -54,6 +61,16 @@
 // boundary value, so set to 101.
 const int kMaxFramesPerSec = 101;
 
+
+void UpdateUmaEnumHistogramStub(const std::string& histogram_name,
+                                int64_t value,
+                                int histogram_max) {}
+
+void UpdateUmaCustomHistogramStub(const std::string& histogram_name,
+                                  int64_t value,
+                                  int histogram_min,
+                                  int histogram_max,
+                                  int histogram_buckets) {}
 }  // namespace
 
 namespace remoting {
@@ -69,7 +86,11 @@
       video_encode_ms_(kLatencySampleSize),
       video_decode_ms_(kLatencySampleSize),
       video_paint_ms_(kLatencySampleSize),
-      round_trip_ms_(kLatencySampleSize) {}
+      round_trip_ms_(kLatencySampleSize) {
+  uma_custom_counts_updater_ = base::Bind(&UpdateUmaCustomHistogramStub);
+  uma_custom_times_updater_ = base::Bind(&UpdateUmaCustomHistogramStub);
+  uma_enum_histogram_updater_ = base::Bind(&UpdateUmaEnumHistogramStub);
+}
 
 PerformanceTracker::~PerformanceTracker() {}
 
@@ -77,6 +98,10 @@
     UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback,
     UpdateUmaCustomHistogramCallback update_uma_custom_times_callback,
     UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback) {
+  DCHECK(!update_uma_custom_counts_callback.is_null());
+  DCHECK(!update_uma_custom_times_callback.is_null());
+  DCHECK(!update_uma_enum_histogram_callback.is_null());
+
   uma_custom_counts_updater_ = update_uma_custom_counts_callback;
   uma_custom_times_updater_ = update_uma_custom_times_callback;
   uma_enum_histogram_updater_ = update_uma_enum_histogram_callback;
@@ -105,11 +130,10 @@
 
     round_trip_ms_.Record(round_trip_latency.InMilliseconds());
 
-    if (!uma_custom_times_updater_.is_null())
-      uma_custom_times_updater_.Run(
-          kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(),
-          kLatencyHistogramMinMs, kLatencyHistogramMaxMs,
-          kLatencyHistogramBuckets);
+    uma_custom_times_updater_.Run(
+        kRoundTripLatencyHistogram, round_trip_latency.InMilliseconds(),
+        kLatencyHistogramMinMs, kLatencyHistogramMaxMs,
+        kLatencyHistogramBuckets);
   }
 
   // If the packet is empty, there are no other stats to update.
@@ -121,49 +145,71 @@
 
   if (packet.has_capture_time_ms()) {
     video_capture_ms_.Record(packet.capture_time_ms());
-    if (!uma_custom_times_updater_.is_null())
-      uma_custom_times_updater_.Run(
-          kVideoCaptureLatencyHistogram, packet.capture_time_ms(),
-          kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
-          kVideoActionsHistogramsBuckets);
+    uma_custom_times_updater_.Run(
+        kVideoCaptureLatencyHistogram, packet.capture_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
   }
 
   if (packet.has_encode_time_ms()) {
     video_encode_ms_.Record(packet.encode_time_ms());
-    if (!uma_custom_times_updater_.is_null())
-      uma_custom_times_updater_.Run(
-          kVideoEncodeLatencyHistogram, packet.encode_time_ms(),
-          kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
-          kVideoActionsHistogramsBuckets);
+    uma_custom_times_updater_.Run(
+        kVideoEncodeLatencyHistogram, packet.encode_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
+  }
+
+  if (packet.has_capture_pending_time_ms()) {
+    uma_custom_times_updater_.Run(
+        kCapturePendingLatencyHistogram, packet.capture_pending_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
+  }
+
+  if (packet.has_capture_overhead_time_ms()) {
+    uma_custom_times_updater_.Run(
+        kCaptureOverheadHistogram, packet.capture_overhead_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
+  }
+
+  if (packet.has_encode_pending_time_ms()) {
+    uma_custom_times_updater_.Run(
+        kEncodePendingLatencyHistogram, packet.encode_pending_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
+  }
+
+  if (packet.has_send_pending_time_ms()) {
+    uma_custom_times_updater_.Run(
+        kSendPendingLatencyHistogram, packet.send_pending_time_ms(),
+        kVideoActionsHistogramsMinMs, kVideoActionsHistogramsMaxMs,
+        kVideoActionsHistogramsBuckets);
   }
 }
 
 void PerformanceTracker::RecordDecodeTime(double value) {
   video_decode_ms_.Record(value);
-  if (!uma_custom_times_updater_.is_null())
-    uma_custom_times_updater_.Run(
-        kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs,
-        kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
+  uma_custom_times_updater_.Run(
+      kVideoDecodeLatencyHistogram, value, kVideoActionsHistogramsMinMs,
+      kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
 }
 
 void PerformanceTracker::RecordPaintTime(double value) {
   video_paint_ms_.Record(value);
-  if (!uma_custom_times_updater_.is_null())
-    uma_custom_times_updater_.Run(
-        kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs,
-        kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
+  uma_custom_times_updater_.Run(
+      kVideoPaintLatencyHistogram, value, kVideoActionsHistogramsMinMs,
+      kVideoActionsHistogramsMaxMs, kVideoActionsHistogramsBuckets);
 }
 
 void PerformanceTracker::UploadRateStatsToUma() {
-  if (!uma_enum_histogram_updater_.is_null()) {
-    uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram,
-                                    video_frame_rate(), kMaxFramesPerSec);
-    uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram,
-                                    video_packet_rate(), kMaxFramesPerSec);
-    uma_custom_counts_updater_.Run(
-        kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps,
-        kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets);
-  }
+  uma_enum_histogram_updater_.Run(kVideoFrameRateHistogram, video_frame_rate(),
+                                  kMaxFramesPerSec);
+  uma_enum_histogram_updater_.Run(kVideoPacketRateHistogram,
+                                  video_packet_rate(), kMaxFramesPerSec);
+  uma_custom_counts_updater_.Run(
+      kVideoBandwidthHistogram, video_bandwidth(), kBandwidthHistogramMinBps,
+      kBandwidthHistogramMaxBps, kBandwidthHistogramBuckets);
 }
 
 void PerformanceTracker::OnPauseStateChanged(bool paused) {
diff --git a/remoting/protocol/performance_tracker.h b/remoting/protocol/performance_tracker.h
index af9e4c7..f1d9aa02 100644
--- a/remoting/protocol/performance_tracker.h
+++ b/remoting/protocol/performance_tracker.h
@@ -22,7 +22,7 @@
  public:
   // Callback that updates UMA custom counts or custom times histograms.
   typedef base::Callback<void(const std::string& histogram_name,
-                              int64 value,
+                              int64_t value,
                               int histogram_min,
                               int histogram_max,
                               int histogram_buckets)>
@@ -30,7 +30,7 @@
 
   // Callback that updates UMA enumeration histograms.
   typedef base::Callback<
-      void(const std::string& histogram_name, int64 value, int histogram_max)>
+      void(const std::string& histogram_name, int64_t value, int histogram_max)>
       UpdateUmaEnumHistogramCallback;
 
   PerformanceTracker();
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index d37b575..ed5115f 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -81,8 +81,8 @@
                void(ConnectionToClient* connection));
   MOCK_METHOD2(OnConnectionClosed,
                void(ConnectionToClient* connection, ErrorCode error));
-  MOCK_METHOD2(OnEventTimestamp,
-               void(ConnectionToClient* connection, int64 timestamp));
+  MOCK_METHOD2(OnInputEventReceived,
+               void(ConnectionToClient* connection, int64_t timestamp));
   MOCK_METHOD3(OnRouteChange,
                void(ConnectionToClient* connection,
                     const std::string& channel_name,
diff --git a/remoting/remoting_android.gypi b/remoting/remoting_android.gypi
index 2f3f557..14ce25f 100644
--- a/remoting/remoting_android.gypi
+++ b/remoting/remoting_android.gypi
@@ -5,6 +5,17 @@
 {
   'conditions': [
     ['OS=="android"', {
+      'variables': {
+        # These hooks allow official builds to modify the remoting_apk target:
+        # Official build of remoting_apk pulls in extra code.
+        'remoting_apk_extra_dependencies%': [],
+        # A different ProGuard config for Google Play Services is needed since the one used by
+        # Chromium and Google Chrome strips out code that we need.
+        'remoting_android_google_play_services_javalib%': '../third_party/android_tools/android_tools.gyp:google_play_services_javalib',
+        # Allows official builds to define the ApplicationContext class differently, and provide
+        # different implementations of parts of the product.
+        'remoting_apk_java_in_dir%': 'android/apk',
+      },
       'targets': [
         {
           'target_name': 'remoting_jni_headers',
@@ -110,8 +121,8 @@
             '../third_party/android_tools/android_tools.gyp:android_support_v7_appcompat_javalib',
             '../third_party/android_tools/android_tools.gyp:android_support_v7_mediarouter_javalib',
             '../third_party/android_tools/android_tools.gyp:android_support_v13_javalib',
-            '../third_party/android_tools/android_tools.gyp:google_play_services_javalib',
             '../third_party/cardboard-java/cardboard.gyp:cardboard_jar',
+            '<(remoting_android_google_play_services_javalib)',
           ],
           'includes': [ '../build/java.gypi' ],
           'conditions' : [
@@ -131,13 +142,14 @@
             'remoting_apk_manifest',
             'remoting_client_jni',
             'remoting_android_client_java',
+            '<@(remoting_apk_extra_dependencies)',
           ],
           'variables': {
             'apk_name': '<!(python <(version_py_path) -f <(branding_path) -t "@APK_FILE_NAME@")',
             'android_app_version_name': '<(version_full)',
             'android_app_version_code': '<!(python tools/android_version.py <(android_app_version_name))',
             'android_manifest_path': '<(SHARED_INTERMEDIATE_DIR)/remoting/android/AndroidManifest.xml',
-            'java_in_dir': 'android/apk',
+            'java_in_dir': '<(remoting_apk_java_in_dir)',
             'native_lib_target': 'libremoting_client_jni',
           },
           'includes': [ '../build/java_apk.gypi' ],
diff --git a/remoting/remoting_host_srcs.gypi b/remoting/remoting_host_srcs.gypi
index a23c7ae..363a67d 100644
--- a/remoting/remoting_host_srcs.gypi
+++ b/remoting/remoting_host_srcs.gypi
@@ -114,6 +114,8 @@
       'host/host_config.cc',
       'host/host_config.h',
       'host/host_config_constants.cc',
+      'host/host_details.cc',
+      'host/host_details.h',
       'host/host_event_logger.h',
       'host/host_event_logger_posix.cc',
       'host/host_event_logger_win.cc',
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd
index 38c35fc..59fb1d3 100644
--- a/remoting/resources/remoting_strings.grd
+++ b/remoting/resources/remoting_strings.grd
@@ -453,6 +453,9 @@
       <message desc="Error displayed if the client plugin fails to load." name="IDS_ERROR_MISSING_PLUGIN">
         Some required components are missing. Please make sure you're running the latest version of Chrome and try again.
       </message>
+      <message desc="Error displayed if Native Client is not enabled." name="IDS_ERROR_NACL_DISABLED">
+        Some required components are missing. Please go to chrome://plugins and make sure Native Client is enabled.
+      </message>
       <message desc="Message shown if the user is not authorized to perform the requested action." name="IDS_ERROR_NOT_AUTHORIZED">
         You do not have permission to perform that action.
       </message>
diff --git a/remoting/tools/run_webapp_unittests.py b/remoting/tools/run_webapp_unittests.py
index bff7128..e9cfada 100755
--- a/remoting/tools/run_webapp_unittests.py
+++ b/remoting/tools/run_webapp_unittests.py
@@ -27,12 +27,12 @@
   return chrome_path
 
 
-def BuildTestPageUri(opt_module=None, opt_coverage=False):
+def BuildTestPageUri(build_path, opt_module=None, opt_coverage=False):
   """Builds the Uri for the test page with params."""
   script_path = os.path.dirname(__file__)
 
   test_page_path = os.path.join(script_path,
-      '../../out/Debug/remoting/unittests/unittests.html')
+      '../../' + build_path + '/remoting/unittests/unittests.html')
   test_page_path = 'file://' + os.path.abspath(test_page_path)
 
   test_page_params = {}
@@ -45,7 +45,7 @@
   return '"' + test_page_path + '"'
 
 
-def BuildCommandLine(chrome_path, opt_module, opt_coverage):
+def BuildCommandLine(chrome_path, build_path, opt_module, opt_coverage):
   """Builds the command line to execute."""
   command = []
   command.append('"' + chrome_path + '"')
@@ -53,7 +53,7 @@
   # The flag |--allow-file-access-from-files| is required so that we can open
   # JavaScript files using XHR and instrument them for code coverage.
   command.append(' --allow-file-access-from-files')
-  test_page_path = BuildTestPageUri(opt_module, opt_coverage)
+  test_page_path = BuildTestPageUri(build_path, opt_module, opt_coverage)
   command.append(test_page_path)
   return ' '.join(command)
 
@@ -67,9 +67,16 @@
     help='The path of the chrome binary to run the test.',
     default=chrome_path)
   parser.add_argument(
-    '--module', help='only run tests that belongs to MODULE')
+    '--module',
+    help='only run tests that belongs to MODULE')
   parser.add_argument(
-    '--coverage', help='run the test with code coverage', action='store_true')
+    '--coverage',
+    help='run the test with code coverage',
+    action='store_true')
+  parser.add_argument(
+    '--build-path',
+    help='The output build path for remoting. (out/Debug)',
+    default='out/Debug')
 
   return parser.parse_args(sys.argv[1:])
 
@@ -84,7 +91,11 @@
     print 'binary to run the test.'
     return 1
 
-  command_line = BuildCommandLine(args.chrome_path, args.module, args.coverage)
+  command_line = BuildCommandLine(
+      args.chrome_path,
+      args.build_path,
+      args.module,
+      args.coverage)
   os.system(command_line)
   return 0
 
diff --git a/remoting/webapp/base/js/base.js b/remoting/webapp/base/js/base.js
index f8c7cc7b..6f11278 100644
--- a/remoting/webapp/base/js/base.js
+++ b/remoting/webapp/base/js/base.js
@@ -415,6 +415,30 @@
 };
 
 /**
+ * Creates a promise that will be rejected if it is not fulfilled within a
+ * certain timeframe.
+ *
+ * This function creates a result promise |R|.  If |promise| is fulfilled
+ * (i.e. resolved or rejected) within |delay| milliseconds, then |R|
+ * is resolved or rejected, respectively.  Otherwise, |R| is rejected with
+ * |opt_defaultError|.
+ *
+ * @param {!Promise<T>} promise The promise to wrap.
+ * @param {number} delay The number of milliseconds to wait.
+ * @param {*=} opt_defaultError The default error used to reject the promise.
+ * @return {!Promise<T>} A new promise.
+ * @template T
+ */
+base.Promise.rejectAfterTimeout = function(promise, delay, opt_defaultError) {
+  return Promise.race([
+    promise,
+    base.Promise.sleep(delay).then(function() {
+      return Promise.reject(opt_defaultError);
+    })
+  ]);
+};
+
+/**
  * Converts a |method| with callbacks into a Promise.
  *
  * @param {Function} method
@@ -825,3 +849,15 @@
     appWindow.outerBounds.top = Math.round((screenHeight - height) / 2);
   }
 };
+
+/**
+ * @return {boolean} Whether NaCL is enabled in chrome://plugins.
+ */
+base.isNaclEnabled = function() {
+  for (var i = 0; i < navigator.mimeTypes.length; i++) {
+    if (navigator.mimeTypes.item(i).type == 'application/x-pnacl') {
+      return true;
+    }
+  }
+  return false;
+};
diff --git a/remoting/webapp/base/js/chromoting_event.js b/remoting/webapp/base/js/chromoting_event.js
index 72652f5..d7acb72 100644
--- a/remoting/webapp/base/js/chromoting_event.js
+++ b/remoting/webapp/base/js/chromoting_event.js
@@ -43,6 +43,10 @@
   this.browser_version;
   /** @private {string} */
   this.webapp_version;
+  /** @type {remoting.ChromotingEvent.Os} */
+  this.host_os;
+  /** @type {string} */
+  this.host_os_version;
   /** @type {string} */
   this.host_version;
   /** @private {string} */
@@ -167,6 +171,7 @@
 
 /** @enum {number} */
 remoting.ChromotingEvent.Os = {
+  UNKNOWN: 0,
   LINUX: 1,
   CHROMEOS: 2,
   MAC: 3,
@@ -176,6 +181,34 @@
   IOS: 7
 };
 
+/**
+ * Convert the OS type String into the enum value.
+ *
+ * @param {string} type
+ * @return {remoting.ChromotingEvent.Os}
+ */
+remoting.ChromotingEvent.toOs = function(type) {
+  type = type.toLowerCase();
+  switch (type) {
+    case 'linux':
+      return remoting.ChromotingEvent.Os.LINUX;
+    case 'chromeos':
+      return remoting.ChromotingEvent.Os.CHROMEOS;
+    case 'mac':
+      return remoting.ChromotingEvent.Os.MAC
+    case 'windows':
+      return remoting.ChromotingEvent.Os.WINDOWS;
+    case 'other':
+      return remoting.ChromotingEvent.Os.OTHER;
+    case 'android':
+      return remoting.ChromotingEvent.Os.ANDROID;
+    case 'ios':
+      return remoting.ChromotingEvent.Os.IOS;
+    default:
+      return remoting.ChromotingEvent.Os.UNKNOWN;
+  }
+}
+
 /** @enum {number} */
 remoting.ChromotingEvent.SessionState = {
   UNKNOWN: 1, // deprecated.
@@ -227,7 +260,8 @@
   HOST_OVERLOAD: 11,
   P2P_FAILURE: 12,
   UNEXPECTED: 13,
-  CLIENT_SUSPENDED: 14
+  CLIENT_SUSPENDED: 14,
+  NACL_DISABLED: 15,
 };
 
 /** @enum {number} */
diff --git a/remoting/webapp/base/js/client_plugin.js b/remoting/webapp/base/js/client_plugin.js
index cb6b070..df96b85 100644
--- a/remoting/webapp/base/js/client_plugin.js
+++ b/remoting/webapp/base/js/client_plugin.js
@@ -34,9 +34,10 @@
 remoting.ClientPlugin.prototype.element = function() {};
 
 /**
- * @param {function(boolean):void} onDone Completion callback.
+ * @return {Promise<void>}  A promise that will resolve when the plugin is
+ *     initialized or reject if it fails.
  */
-remoting.ClientPlugin.prototype.initialize = function(onDone) {};
+remoting.ClientPlugin.prototype.initialize = function() {};
 
 /**
  * @param {remoting.Host} host The host to connect to.
diff --git a/remoting/webapp/base/js/client_plugin_impl.js b/remoting/webapp/base/js/client_plugin_impl.js
index 80df124..892de83 100644
--- a/remoting/webapp/base/js/client_plugin_impl.js
+++ b/remoting/webapp/base/js/client_plugin_impl.js
@@ -68,8 +68,8 @@
   this.hostCapabilities_ = null;
   /** @private {boolean} */
   this.helloReceived_ = false;
-  /** @private {function(boolean)|null} */
-  this.onInitializedCallback_ = null;
+  /** @private {base.Deferred} */
+  this.onInitializedDeferred_ = null;
   /** @private {function(string, string):void} */
   this.onPairingComplete_ = function(clientId, sharedSecret) {};
   /** @private {remoting.ClientSession.PerfStats} */
@@ -77,12 +77,12 @@
 
   /** @type {remoting.ClientPluginImpl} */
   var that = this;
-  this.plugin_.addEventListener('message',
-        /** @param {Event} event Message event from the plugin. */
-        function(event) {
-          that.handleMessage_(
-              /** @type {remoting.ClientPluginMessage} */ (event.data));
-        }, false);
+
+  this.eventHooks_ = new base.Disposables(
+    new base.DomEventHook(
+      this.plugin_, 'message', this.handleMessage_.bind(this), false),
+    new base.DomEventHook(
+      this.plugin_, 'crash', this.onPluginCrashed_.bind(this), false));
 
   /** @private */
   this.hostDesktop_ = new remoting.ClientPlugin.HostDesktopImpl(
@@ -113,7 +113,7 @@
   plugin.height = '0';
   plugin.tabIndex = 0;  // Required, otherwise focus() doesn't work.
   return plugin;
-}
+};
 
 /**
  * @param {remoting.ClientPlugin.ConnectionEventHandler} handler
@@ -148,11 +148,12 @@
 };
 
 /**
- * @param {string|remoting.ClientPluginMessage}
- *    rawMessage Message from the plugin.
+ * @param {Event} event Message from the plugin.
  * @private
  */
-remoting.ClientPluginImpl.prototype.handleMessage_ = function(rawMessage) {
+remoting.ClientPluginImpl.prototype.handleMessage_ = function(event) {
+  var rawMessage =
+      /** @type {remoting.ClientPluginMessage|string} */ (event.data);
   var message =
       /** @type {remoting.ClientPluginMessage} */
       ((typeof(rawMessage) == 'string') ? base.jsonParseSafe(rawMessage)
@@ -167,7 +168,16 @@
   } catch(/** @type {*} */ e) {
     console.error(e);
   }
-}
+};
+
+/** @private */
+remoting.ClientPluginImpl.prototype.onPluginCrashed_ = function(event) {
+  // This should only happen on assert() or exit() according to
+  // https://developer.chrome.com/native-client/devguide/coding/progress-events,
+  // which is extremely unlikely in retail builds.  So we just log it without
+  // propagating it to the UI.
+  console.error('Plugin crashed.');
+};
 
 /**
  * @param {remoting.ClientPluginMessage}
@@ -238,9 +248,9 @@
 
   if (message.method == 'hello') {
     this.helloReceived_ = true;
-    if (this.onInitializedCallback_ != null) {
-      this.onInitializedCallback_(true);
-      this.onInitializedCallback_ = null;
+    if (this.onInitializedDeferred_ != null) {
+      this.onInitializedDeferred_.resolve(true);
+      this.onInitializedDeferred_ = null;
     }
 
   } else if (message.method == 'onDesktopSize') {
@@ -336,6 +346,9 @@
  * Deletes the plugin.
  */
 remoting.ClientPluginImpl.prototype.dispose = function() {
+  base.dispose(this.eventHooks_);
+  this.eventHooks_ = null;
+
   if (this.plugin_) {
     this.plugin_.parentNode.removeChild(this.plugin_);
     this.plugin_ = null;
@@ -353,14 +366,28 @@
 };
 
 /**
- * @param {function(boolean): void} onDone
+ * @return {Promise}  A promise that resolves to true if the plugin initializes.
  */
-remoting.ClientPluginImpl.prototype.initialize = function(onDone) {
-  if (this.helloReceived_) {
-    onDone(true);
-  } else {
-    this.onInitializedCallback_ = onDone;
+remoting.ClientPluginImpl.prototype.initialize = function() {
+  // 99.9 percentile of plugin initialize time from our stats is 141 seconds.
+  var PLUGIN_INTIALIZE_TIMEOUT = 150 * 1000;
+
+  if (!base.isNaclEnabled()) {
+    return Promise.reject(new remoting.Error(remoting.Error.Tag.NACL_DISABLED));
   }
+
+  if (this.helloReceived_) {
+    return Promise.resolve(true);
+  }
+
+  if (!this.onInitializedDeferred_) {
+    this.onInitializedDeferred_ = new base.Deferred();
+  }
+
+  return base.Promise.rejectAfterTimeout(
+      this.onInitializedDeferred_.promise(),
+      PLUGIN_INTIALIZE_TIMEOUT,
+      new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
 };
 
 /**
diff --git a/remoting/webapp/base/js/client_session_factory.js b/remoting/webapp/base/js/client_session_factory.js
index 986466b..0dcadbd 100644
--- a/remoting/webapp/base/js/client_session_factory.js
+++ b/remoting/webapp/base/js/client_session_factory.js
@@ -54,7 +54,8 @@
   function OnError(/** !remoting.Error */ error) {
     logger.logSessionStateChange(
         remoting.ChromotingEvent.SessionState.CONNECTION_FAILED,
-        remoting.ChromotingEvent.ConnectionError.UNEXPECTED);
+        toConnectionError(error));
+
     base.dispose(signalStrategy);
     base.dispose(clientPlugin);
     throw error;
@@ -121,20 +122,24 @@
 function createPlugin(container, capabilities) {
   var plugin = remoting.ClientPlugin.factory.createPlugin(
       container, capabilities);
-  var deferred = new base.Deferred();
+  return plugin.initialize().then(function() {
+    return plugin;
+  });
+}
 
-  function onInitialized(/** boolean */ initialized) {
-    if (!initialized) {
-      console.error('ERROR: remoting plugin not loaded');
-      plugin.dispose();
-      deferred.reject(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
-      return;
+/**
+ * @param {remoting.Error} e
+ * @return {remoting.ChromotingEvent.ConnectionError}
+ */
+function toConnectionError(/** Error */ e) {
+  if (e instanceof remoting.Error) {
+    if (e.getTag() == remoting.Error.Tag.MISSING_PLUGIN) {
+      return remoting.ChromotingEvent.ConnectionError.MISSING_PLUGIN;
+    } else if (e.getTag() == remoting.Error.Tag.NACL_DISABLED) {
+      return remoting.ChromotingEvent.ConnectionError.NACL_DISABLED;
     }
-
-    deferred.resolve(plugin);
   }
-  plugin.initialize(onInitialized);
-  return deferred.promise();
+  return remoting.ChromotingEvent.ConnectionError.UNEXPECTED;
 }
 
 })();
diff --git a/remoting/webapp/base/js/error.js b/remoting/webapp/base/js/error.js
index 8e321c9..28d79c6 100644
--- a/remoting/webapp/base/js/error.js
+++ b/remoting/webapp/base/js/error.js
@@ -123,7 +123,8 @@
   REGISTRATION_FAILED: /*i18n-content*/ 'ERROR_HOST_REGISTRATION_FAILED',
   NOT_AUTHORIZED: /*i18n-content*/ 'ERROR_NOT_AUTHORIZED',
   // TODO(garykac): Move app-specific errors into separate location.
-  APP_NOT_AUTHORIZED: /*i18n-content*/ 'ERROR_APP_NOT_AUTHORIZED'
+  APP_NOT_AUTHORIZED: /*i18n-content*/ 'ERROR_APP_NOT_AUTHORIZED',
+  NACL_DISABLED: /*i18n-content*/ 'ERROR_NACL_DISABLED',
 };
 
 // A whole bunch of semi-redundant constants, mostly to reduce to size
diff --git a/remoting/webapp/base/js/host.js b/remoting/webapp/base/js/host.js
index 1a93bec..2c5529d 100644
--- a/remoting/webapp/base/js/host.js
+++ b/remoting/webapp/base/js/host.js
@@ -38,6 +38,10 @@
   this.publicKey = '';
   /** @type {string} */
   this.hostVersion = '';
+  /** @type {remoting.ChromotingEvent.Os} */
+  this.hostOS = remoting.ChromotingEvent.Os.UNKNOWN;
+  /** @type {string} */
+  this.hostOSVersion = '';
   /** @type {Array<string>} */
   this.tokenUrlPatterns = [];
   /** @type {string} */
diff --git a/remoting/webapp/base/js/host_options_unittest.js b/remoting/webapp/base/js/host_options_unittest.js
index a6b1d46..d5e5865 100644
--- a/remoting/webapp/base/js/host_options_unittest.js
+++ b/remoting/webapp/base/js/host_options_unittest.js
@@ -56,6 +56,7 @@
 QUnit.test('Saving and loading a host preserves the saved values',
   function(assert) {
     var options = new remoting.HostOptions('host-id');
+    var optionsLoaded = new remoting.HostOptions('host-id');
     options.setShrinkToFit(false);
     options.setResizeToClient(false);
     options.setDesktopScale(2);
@@ -67,18 +68,20 @@
     var optionsCopy = base.deepCopy(options);
 
     return options.save().then(function() {
-      return options.load();
+      return optionsLoaded.load();
     }).then(function() {
-      assert.deepEqual(optionsCopy, base.deepCopy(options));
+      assert.deepEqual(optionsCopy, base.deepCopy(optionsLoaded));
     });
 });
 
 QUnit.test('Saving a host ignores unset values',
   function(assert) {
     var options = new remoting.HostOptions('host-id');
+    options.setShrinkToFit(false);
     var optionsCopy = base.deepCopy(options);
+    var optionsEmpty = new remoting.HostOptions('host-id');
 
-    return options.save().then(function() {
+    return optionsEmpty.save().then(function() {
       return options.load();
     }).then(function() {
       assert.deepEqual(optionsCopy, base.deepCopy(options));
@@ -104,3 +107,16 @@
           assert.deepEqual(options1, options2);
         });
 });
+
+QUnit.test('New options are loaded and saved without updating the code',
+  function(assert) {
+    var options = new remoting.HostOptions('host-id');
+    var optionsLoaded = new remoting.HostOptions('host-id');
+    options['undefined-option'] = 42;
+
+    return options.save().then(function() {
+      return optionsLoaded.load();
+    }).then(function() {
+      assert.equal(optionsLoaded['undefined-option'], 42);
+    });
+});
diff --git a/remoting/webapp/base/js/log_to_server.js b/remoting/webapp/base/js/log_to_server.js
index c77cc98..d5819c0 100644
--- a/remoting/webapp/base/js/log_to_server.js
+++ b/remoting/webapp/base/js/log_to_server.js
@@ -196,8 +196,9 @@
           this.authTotalTime_) / 1000.0;
   entry.addSessionDuration(sessionDurationInSeconds);
   entry.addApplicationId();
-  // The host-version will be blank for logs before a session has been created.
-  // For example, the signal-strategy log-entries won't have host version info.
+  // The host-version/os/os-version will be blank for logs before a session has
+  // been created. For example, the signal-strategy log-entries won't have host
+  // version info.
   entry.addHostVersion(this.hostVersion_);
 
   // Send the stanza to the debug log.
@@ -288,3 +289,18 @@
 remoting.LogToServer.prototype.setHostVersion = function(hostVersion) {
   this.hostVersion_ = hostVersion;
 };
+
+/**
+ * Stub.
+ * @param {remoting.ChromotingEvent.Os} hostOS Type of the host OS for
+          current session.
+ * @return {void} Nothing.
+ */
+remoting.LogToServer.prototype.setHostOS = function(hostOS) {};
+
+/**
+ * Stub.
+ * @param {string} hostOSVersion Version of the host OS for current session.
+ * @return {void} Nothing.
+ */
+remoting.LogToServer.prototype.setHostOSVersion = function(hostOSVersion) {};
diff --git a/remoting/webapp/base/js/logger.js b/remoting/webapp/base/js/logger.js
index ab417c1..443e7e2b 100644
--- a/remoting/webapp/base/js/logger.js
+++ b/remoting/webapp/base/js/logger.js
@@ -28,6 +28,19 @@
 remoting.Logger.prototype.setHostVersion = function(hostVersion) {};
 
 /**
+ * @param {remoting.ChromotingEvent.Os} hostOS Type of the OS the host
+ *        for the current session.
+ * @return {void} Nothing.
+ */
+remoting.Logger.prototype.setHostOS = function(hostOS) {};
+
+/**
+ * @param {string} hostOSVersion Version of the host Os for current session.
+ * @return {void} Nothing.
+ */
+remoting.Logger.prototype.setHostOSVersion = function(hostOSVersion) {};
+
+/**
  * Set the connection type (direct, stun relay).
  *
  * @param {string} connectionType
@@ -79,4 +92,4 @@
 // to the server, in milliseconds.
 remoting.Logger.CONNECTION_STATS_ACCUMULATE_TIME = 60 * 1000;
 
-})();
\ No newline at end of file
+})();
diff --git a/remoting/webapp/base/js/server_log_entry.js b/remoting/webapp/base/js/server_log_entry.js
index 919ad58..2e5d856 100644
--- a/remoting/webapp/base/js/server_log_entry.js
+++ b/remoting/webapp/base/js/server_log_entry.js
@@ -428,6 +428,21 @@
 };
 
 /**
+ * Stub.
+ * @param {remoting.ChromotingEvent.Os} hostOS type of the host OS for current
+ *        session.
+ * @return {void} Nothing.
+ */
+remoting.ServerLogEntry.prototype.addHostOS = function(hostOS) {};
+
+/**
+ * Stub.
+ * @param {string} hostOSVersion Version of the host OS for current session.
+ * @return {void} Nothing.
+ */
+remoting.ServerLogEntry.prototype.addHostOSVersion = function(hostOSVersion) {};
+
+/**
  * Adds a field specifying the mode to this log entry.
  * @param {string} mode The current app mode (It2Me, Me2Me, AppRemoting).
  */
@@ -454,4 +469,4 @@
   }
   this.set_(remoting.ServerLogEntry.KEY_XMPP_ERROR_RAW_STANZA,
             xmppError.raw_stanza);
-};
\ No newline at end of file
+};
diff --git a/remoting/webapp/base/js/session_logger.js b/remoting/webapp/base/js/session_logger.js
index 40a594c9..508041e 100644
--- a/remoting/webapp/base/js/session_logger.js
+++ b/remoting/webapp/base/js/session_logger.js
@@ -43,6 +43,10 @@
   this.authTotalTime_ = 0;
   /** @private */
   this.hostVersion_ = '';
+  /** @private {remoting.ChromotingEvent.Os}*/
+  this.hostOS_ = remoting.ChromotingEvent.Os.UNKNOWN;
+  /** @private */
+  this.hostOSVersion_ = '';
 
   /** @private */
   this.mode_ = remoting.ChromotingEvent.Mode.ME2ME;
@@ -68,6 +72,16 @@
 };
 
 /** @override {remoting.Logger} */
+remoting.SessionLogger.prototype.setHostOS = function(hostOS) {
+  this.hostOS_ = hostOS;
+};
+
+/** @override {remoting.Logger} */
+remoting.SessionLogger.prototype.setHostOSVersion = function(hostOSVersion) {
+  this.hostOSVersion_ = hostOSVersion;
+};
+
+/** @override {remoting.Logger} */
 remoting.SessionLogger.prototype.setConnectionType = function(connectionType) {
   this.connectionType_ = toConnectionType(connectionType);
 };
@@ -237,6 +251,8 @@
     entry.connection_type = this.connectionType_;
   }
   entry.host_version = this.hostVersion_;
+  entry.host_os = this.hostOS_;
+  entry.host_os_version = this.hostOSVersion_;
 };
 
 /**
@@ -360,6 +376,8 @@
       return ConnectionError.CLIENT_SUSPENDED;
     case remoting.Error.Tag.UNEXPECTED:
       return ConnectionError.UNEXPECTED;
+    case remoting.Error.Tag.NACL_DISABLED:
+      return ConnectionError.NACL_DISABLED;
     default:
       throw new Error('Unknown error Tag : ' + error.getTag());
   }
@@ -419,4 +437,4 @@
   }
 }
 
-})();
\ No newline at end of file
+})();
diff --git a/remoting/webapp/base/js/session_logger_unittest.js b/remoting/webapp/base/js/session_logger_unittest.js
index 035c655..8bf4de8 100644
--- a/remoting/webapp/base/js/session_logger_unittest.js
+++ b/remoting/webapp/base/js/session_logger_unittest.js
@@ -81,6 +81,8 @@
   logger.setLogEntryMode(Event.Mode.ME2ME);
   logger.setConnectionType('stun');
   logger.setHostVersion('host_version');
+  logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+  logger.setHostOSVersion('host_os_version');
 
   logger.logClientSessionStateChange(
       remoting.ClientSession.State.FAILED,
@@ -102,6 +104,8 @@
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.STUN,
     host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version',
     session_id: sessionId
   });
 });
@@ -114,6 +118,8 @@
   logger.setLogEntryMode(Event.Mode.ME2ME);
   logger.setConnectionType('stun');
   logger.setHostVersion('host_version');
+  logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+  logger.setHostOSVersion('host_os_version');
 
   var xmppError = new remoting.ChromotingEvent.XmppError('<fake-stanza/>');
 
@@ -137,6 +143,8 @@
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.STUN,
     host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version',
     session_id: sessionId,
     xmpp_error: {
       raw_stanza: '<fake-stanza/>'
@@ -154,6 +162,8 @@
   logger.setLogEntryMode(Event.Mode.ME2ME);
   logger.setConnectionType('relay');
   logger.setHostVersion('host_version');
+  logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+  logger.setHostOSVersion('host_os_version');
   var oldSessionId = logger.getSessionId();
 
   // Expires the session id.
@@ -175,7 +185,9 @@
     role: Event.Role.CLIENT,
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.RELAY,
-    host_version: 'host_version'
+    host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version'
   });
 
   verifyEvent(assert, 1, {
@@ -189,7 +201,9 @@
     role: Event.Role.CLIENT,
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.RELAY,
-    host_version: 'host_version'
+    host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version'
   });
 
   verifyEvent(assert, 2, {
@@ -205,6 +219,8 @@
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.RELAY,
     host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version',
     session_id: newSessionId
   });
 });
@@ -219,6 +235,8 @@
   logger.setLogEntryMode(Event.Mode.ME2ME);
   logger.setConnectionType('direct');
   logger.setHostVersion('host_version');
+  logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+  logger.setHostOSVersion('host_os_version');
   logger.setAuthTotalTime(1000);
   clock.tick(2500);
 
@@ -239,6 +257,8 @@
     mode: Event.Mode.ME2ME,
     connection_type: Event.ConnectionType.DIRECT,
     host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version',
     session_id: logger.getSessionId(),
     session_duration: 1.5
   });
@@ -253,6 +273,8 @@
   logger.setLogEntryMode(Event.Mode.LGAPP);
   logger.setConnectionType('direct');
   logger.setHostVersion('host_version');
+  logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+  logger.setHostOSVersion('host_os_version');
 
   // Log the statistics.
   logger.logStatistics({
@@ -297,6 +319,8 @@
     mode: Event.Mode.LGAPP,
     connection_type: Event.ConnectionType.DIRECT,
     host_version: 'host_version',
+    host_os: remoting.ChromotingEvent.Os.OTHER,
+    host_os_version: 'host_os_version',
     session_id: logger.getSessionId(),
     video_bandwidth: 2.0,
     capture_latency: 2.0,
diff --git a/remoting/webapp/base/js/telemetry_event_writer_unittest.js b/remoting/webapp/base/js/telemetry_event_writer_unittest.js
index c7b14c93..9d5b926 100644
--- a/remoting/webapp/base/js/telemetry_event_writer_unittest.js
+++ b/remoting/webapp/base/js/telemetry_event_writer_unittest.js
@@ -40,6 +40,8 @@
     logger.setLogEntryMode(remoting.ChromotingEvent.Mode.ME2ME);
     logger.setConnectionType('stun');
     logger.setHostVersion('host_version');
+    logger.setHostOS(remoting.ChromotingEvent.Os.OTHER);
+    logger.setHostOSVersion('host_os_version');
   },
   afterEach: function() {
     base.dispose(service);
@@ -104,7 +106,9 @@
       role: Event.Role.CLIENT,
       mode: Event.Mode.ME2ME,
       connection_type: Event.ConnectionType.STUN,
-      host_version: 'host_version'
+      host_version: 'host_version',
+      host_os: remoting.ChromotingEvent.Os.OTHER,
+      host_os_version: 'host_os_version'
     });
   });
 });
@@ -129,7 +133,9 @@
       role: Event.Role.CLIENT,
       mode: Event.Mode.ME2ME,
       connection_type: Event.ConnectionType.STUN,
-      host_version: 'host_version'
+      host_version: 'host_version',
+      host_os: remoting.ChromotingEvent.Os.OTHER,
+      host_os_version: 'host_os_version'
     });
   });
 });
@@ -158,7 +164,9 @@
       role: Event.Role.CLIENT,
       mode: Event.Mode.ME2ME,
       connection_type: Event.ConnectionType.STUN,
-      host_version: 'host_version'
+      host_version: 'host_version',
+      host_os: remoting.ChromotingEvent.Os.OTHER,
+      host_os_version: 'host_os_version'
     });
   });
 });
diff --git a/remoting/webapp/crd/js/gcd_host_list_api.js b/remoting/webapp/crd/js/gcd_host_list_api.js
index 42c8234..3816f33 100644
--- a/remoting/webapp/crd/js/gcd_host_list_api.js
+++ b/remoting/webapp/crd/js/gcd_host_list_api.js
@@ -165,6 +165,9 @@
   host.publicKey = base.getStringAttr(baseState, '_publicKey');
   host.jabberId = base.getStringAttr(baseState, '_jabberId', '');
   host.hostVersion = base.getStringAttr(baseState, '_hostVersion', '');
+  host.hostOS = remoting.ChromotingEvent.toOs(
+      base.getStringAttr(baseState, '_hostOS', ''));
+  host.hostOSVersion = base.getStringAttr(baseState, '_hostOSVersion', '');
   var creationTimeMs = base.getNumberAttr(device, 'creationTimeMs', 0);
   if (creationTimeMs) {
     host.createdTime = new Date(creationTimeMs).toISOString();
diff --git a/remoting/webapp/crd/js/legacy_host_list_api.js b/remoting/webapp/crd/js/legacy_host_list_api.js
index d89b951..23bed0a7 100644
--- a/remoting/webapp/crd/js/legacy_host_list_api.js
+++ b/remoting/webapp/crd/js/legacy_host_list_api.js
@@ -143,6 +143,9 @@
           host.jabberId = base.getStringAttr(item, 'jabberId', '');
           host.publicKey = base.getStringAttr(item, 'publicKey', '');
           host.hostVersion = base.getStringAttr(item, 'hostVersion', '');
+          host.hostOS = remoting.ChromotingEvent.toOs(
+              base.getStringAttr(item, 'hostOS', ''));
+          host.hostOSVersion = base.getStringAttr(item, 'hostOSVersion', '');
           host.tokenUrlPatterns =
               base.getArrayAttr(item, 'tokenUrlPatterns', []);
           host.updatedTime = base.getStringAttr(item, 'updatedTime', '');
diff --git a/remoting/webapp/crd/js/me2me_activity.js b/remoting/webapp/crd/js/me2me_activity.js
index 5a35735..8d96f67 100644
--- a/remoting/webapp/crd/js/me2me_activity.js
+++ b/remoting/webapp/crd/js/me2me_activity.js
@@ -87,6 +87,8 @@
   var logger = remoting.SessionLogger.createForClient();
   logger.setEntryPoint(entryPoint);
   logger.setHostVersion(this.host_.hostVersion);
+  logger.setHostOS(this.host_.hostOS);
+  logger.setHostOSVersion(this.host_.hostOSVersion);
   logger.setLogEntryMode(Mode.ME2ME);
   return logger;
 };
diff --git a/remoting/webapp/crd/js/mock_client_plugin.js b/remoting/webapp/crd/js/mock_client_plugin.js
index 319fec1..1163f1ed 100644
--- a/remoting/webapp/crd/js/mock_client_plugin.js
+++ b/remoting/webapp/crd/js/mock_client_plugin.js
@@ -77,11 +77,13 @@
   return this.element_;
 };
 
-remoting.MockClientPlugin.prototype.initialize = function(onDone) {
-  var that = this;
-  Promise.resolve().then(function() {
-    onDone(that.mock$initializationResult);
-  });
+remoting.MockClientPlugin.prototype.initialize = function() {
+  if (this.mock$initializationResult) {
+    return Promise.resolve();
+  } else {
+    return Promise.reject(
+        new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
+  }
 };
 
 
diff --git a/remoting/webapp/files.gni b/remoting/webapp/files.gni
index 8a0e9e9..37042a9ae6 100644
--- a/remoting/webapp/files.gni
+++ b/remoting/webapp/files.gni
@@ -420,9 +420,6 @@
   "base/js/typecheck.js",
   "base/js/xhr.js",
   "base/js/xhr_event_writer.js",
-  "crd/js/host_installer.js",
-  "crd/js/host_session.js",
-  "crd/js/it2me_host_facade.js",
 ]
 
 #
diff --git a/sandbox/mac/pre_exec_delegate.cc b/sandbox/mac/pre_exec_delegate.cc
index c939e498..adf40a0d 100644
--- a/sandbox/mac/pre_exec_delegate.cc
+++ b/sandbox/mac/pre_exec_delegate.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "sandbox/mac/bootstrap_sandbox.h"
+#include "sandbox/mac/xpc.h"
 
 namespace sandbox {
 
@@ -20,15 +21,15 @@
       sandbox_server_bootstrap_name_ptr_(
           sandbox_server_bootstrap_name_.c_str()),
       sandbox_token_(sandbox_token),
-      is_yosemite_or_later_(base::mac::IsOSYosemiteOrLater()) {
+      is_yosemite_or_later_(base::mac::IsOSYosemiteOrLater()),
+      look_up_message_(CreateBootstrapLookUpMessage()) {
 }
 
 PreExecDelegate::~PreExecDelegate() {}
 
 void PreExecDelegate::RunAsyncSafe() {
   mach_port_t sandbox_server_port = MACH_PORT_NULL;
-  kern_return_t kr = bootstrap_look_up(bootstrap_port,
-      sandbox_server_bootstrap_name_ptr_, &sandbox_server_port);
+  kern_return_t kr = DoBootstrapLookUp(&sandbox_server_port);
   if (kr != KERN_SUCCESS)
     RAW_LOG(FATAL, "Failed to look up bootstrap sandbox server port.");
 
@@ -56,4 +57,49 @@
   }
 }
 
+xpc_object_t PreExecDelegate::CreateBootstrapLookUpMessage() {
+  if (is_yosemite_or_later_) {
+    xpc_object_t dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
+    xpc_dictionary_set_uint64(dictionary, "type", 7);
+    xpc_dictionary_set_uint64(dictionary, "handle", 0);
+    xpc_dictionary_set_string(dictionary, "name",
+        sandbox_server_bootstrap_name_ptr_);
+    xpc_dictionary_set_int64(dictionary, "targetpid", 0);
+    xpc_dictionary_set_uint64(dictionary, "flags", 0);
+    xpc_dictionary_set_uint64(dictionary, "subsystem", 5);
+    xpc_dictionary_set_uint64(dictionary, "routine", 207);
+    // Add a NULL port so that the slot in the dictionary is already
+    // allocated.
+    xpc_dictionary_set_mach_send(dictionary, "domain-port", MACH_PORT_NULL);
+    return dictionary;
+  }
+
+  return nullptr;
+}
+
+kern_return_t PreExecDelegate::DoBootstrapLookUp(mach_port_t* out_port) {
+  if (is_yosemite_or_later_) {
+    xpc_dictionary_set_mach_send(look_up_message_, "domain-port",
+        bootstrap_port);
+
+    // |pipe| cannot be created pre-fork() since the |bootstrap_port| will
+    // be invalidated. Deliberately leak |pipe| as well.
+    xpc_pipe_t pipe = xpc_pipe_create_from_port(bootstrap_port, 0);
+    xpc_object_t reply;
+    int rv = xpc_pipe_routine(pipe, look_up_message_, &reply);
+    if (rv != 0) {
+      return xpc_dictionary_get_int64(reply, "error");
+    } else {
+      xpc_object_t port_value = xpc_dictionary_get_value(reply, "port");
+      *out_port = xpc_mach_send_get_right(port_value);
+      return *out_port != MACH_PORT_NULL ? KERN_SUCCESS : KERN_INVALID_RIGHT;
+    }
+  } else {
+    // On non-XPC launchd systems, bootstrap_look_up() is MIG-based and
+    // generally safe.
+    return bootstrap_look_up(bootstrap_port,
+        sandbox_server_bootstrap_name_ptr_, out_port);
+  }
+}
+
 }  // namespace sandbox
diff --git a/sandbox/mac/pre_exec_delegate.h b/sandbox/mac/pre_exec_delegate.h
index 61a1655..b84082ea 100644
--- a/sandbox/mac/pre_exec_delegate.h
+++ b/sandbox/mac/pre_exec_delegate.h
@@ -6,6 +6,7 @@
 #define SANDBOX_MAC_PRE_EXEC_DELEGATE_H_
 
 #include "base/process/launch.h"
+#include "sandbox/mac/xpc.h"
 
 namespace sandbox {
 
@@ -24,11 +25,23 @@
   uint64_t sandbox_token() const { return sandbox_token_; }
 
  private:
+  // Allocates the bootstrap_look_up IPC message prior to fork().
+  xpc_object_t CreateBootstrapLookUpMessage();
+
+  // Performs a bootstrap_look_up(), either using the pre-allocated message
+  // or the normal routine, depending on the OS X system version.
+  kern_return_t DoBootstrapLookUp(mach_port_t* out_port);
+
   const std::string sandbox_server_bootstrap_name_;
   const char* const sandbox_server_bootstrap_name_ptr_;
   const uint64_t sandbox_token_;
   const bool is_yosemite_or_later_;
 
+  // If is_yosemite_or_later_, this field is used to hold the pre-allocated XPC
+  // object needed to interact with the bootstrap server in RunAsyncSafe().
+  // This is deliberately leaked in the fork()ed process.
+  xpc_object_t look_up_message_;
+
   DISALLOW_COPY_AND_ASSIGN(PreExecDelegate);
 };
 
diff --git a/sandbox/mac/xpc_private_stubs.sig b/sandbox/mac/xpc_private_stubs.sig
index 7ab2934..b8e1c50 100644
--- a/sandbox/mac/xpc_private_stubs.sig
+++ b/sandbox/mac/xpc_private_stubs.sig
@@ -10,6 +10,9 @@
 void xpc_dictionary_set_mach_send(xpc_object_t dictionary, const char* name, mach_port_t port);
 void xpc_dictionary_get_audit_token(xpc_object_t dictionary, audit_token_t* token);
 
+// Raw object getters.
+mach_port_t xpc_mach_send_get_right(xpc_object_t value);
+
 // Pipe methods.
 xpc_pipe_t xpc_pipe_create_from_port(mach_port_t port, int flags);
 int xpc_pipe_receive(mach_port_t port, xpc_object_t* message);
diff --git a/sandbox/mac/xpc_stubs_header.fragment b/sandbox/mac/xpc_stubs_header.fragment
index 4daa850..977ffe78 100644
--- a/sandbox/mac/xpc_stubs_header.fragment
+++ b/sandbox/mac/xpc_stubs_header.fragment
@@ -53,6 +53,10 @@
 XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2 void
 xpc_dictionary_set_uint64(xpc_object_t xdict, const char* key, uint64_t value);
 
+XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2
+void xpc_dictionary_set_string(xpc_object_t xdict, const char* key,
+                               const char* string);
+
 XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT xpc_object_t
 xpc_dictionary_create(const char* const* keys,
                       const xpc_object_t* values,
@@ -61,6 +65,9 @@
     xpc_object_t
     xpc_dictionary_create_reply(xpc_object_t original);
 
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL2
+xpc_object_t xpc_dictionary_get_value(xpc_object_t xdict, const char* key);
+
 XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT XPC_NONNULL1
 char* xpc_copy_description(xpc_object_t object);
 }  // extern "C"
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index ef74202b..af0d6bf 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -90,7 +90,7 @@
     PDF documents.
  */
 #define SK_SFNTLY_SUBSETTER \
-    "third_party/sfntly/cpp/src/sample/chromium/font_subsetter.h"
+    "third_party/sfntly/src/cpp/src/sample/chromium/font_subsetter.h"
 
 /*  To write debug messages to a console, skia will call SkDebugf(...) following
     printf conventions (e.g. const char* format, ...). If you want to redirect
diff --git a/skia/ext/SkTraceMemoryDump_chrome.cc b/skia/ext/SkTraceMemoryDump_chrome.cc
index a5309047..c4bda0cd 100644
--- a/skia/ext/SkTraceMemoryDump_chrome.cc
+++ b/skia/ext/SkTraceMemoryDump_chrome.cc
@@ -16,14 +16,20 @@
 }
 
 SkTraceMemoryDump_Chrome::SkTraceMemoryDump_Chrome(
+    base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
     base::trace_event::ProcessMemoryDump* process_memory_dump)
-    : SkTraceMemoryDump_Chrome("", process_memory_dump) {}
+    : SkTraceMemoryDump_Chrome("", level_of_detail, process_memory_dump) {}
 
 SkTraceMemoryDump_Chrome::SkTraceMemoryDump_Chrome(
-    const char* dump_name_prefix,
+    const std::string& dump_name_prefix,
+    base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
     base::trace_event::ProcessMemoryDump* process_memory_dump)
     : dump_name_prefix_(dump_name_prefix),
-      process_memory_dump_(process_memory_dump) {}
+      process_memory_dump_(process_memory_dump),
+      request_level_(
+          level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::LIGHT
+              ? SkTraceMemoryDump::kLight_LevelOfDetail
+              : SkTraceMemoryDump::kObjectsBreakdowns_LevelOfDetail) {}
 
 SkTraceMemoryDump_Chrome::~SkTraceMemoryDump_Chrome() {}
 
@@ -64,6 +70,11 @@
   DCHECK(dump);
 }
 
+SkTraceMemoryDump::LevelOfDetail SkTraceMemoryDump_Chrome::getRequestedDetails()
+    const {
+  return request_level_;
+}
+
 base::trace_event::MemoryAllocatorDump*
 SkTraceMemoryDump_Chrome::GetOrCreateAllocatorDump(const char* dumpName) {
   std::string name = dump_name_prefix_ + dumpName;
diff --git a/skia/ext/SkTraceMemoryDump_chrome.h b/skia/ext/SkTraceMemoryDump_chrome.h
index 749d99d..42a0e0e 100644
--- a/skia/ext/SkTraceMemoryDump_chrome.h
+++ b/skia/ext/SkTraceMemoryDump_chrome.h
@@ -7,7 +7,9 @@
 
 #include <string>
 
+#include "base/basictypes.h"
 #include "base/macros.h"
+#include "base/trace_event/memory_dump_request_args.h"
 #include "third_party/skia/include/core/SkTraceMemoryDump.h"
 
 namespace base {
@@ -19,17 +21,19 @@
 
 namespace skia {
 
-class SkTraceMemoryDump_Chrome : public SkTraceMemoryDump {
+class SK_API SkTraceMemoryDump_Chrome : public SkTraceMemoryDump {
  public:
   // This should never outlive the OnMemoryDump call since the
   // ProcessMemoryDump is valid only in that timeframe. Optional
   // |dump_name_prefix| argument specifies the prefix appended to the dump
   // name skia provides. By default it is taken as empty string.
   SkTraceMemoryDump_Chrome(
+      base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
       base::trace_event::ProcessMemoryDump* process_memory_dump);
 
   SkTraceMemoryDump_Chrome(
-      const char* dump_name_prefix,
+      const std::string& dump_name_prefix,
+      base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
       base::trace_event::ProcessMemoryDump* process_memory_dump);
 
   ~SkTraceMemoryDump_Chrome() override;
@@ -45,6 +49,7 @@
   void setDiscardableMemoryBacking(
       const char* dumpName,
       const SkDiscardableMemory& discardableMemoryObject) override;
+  LevelOfDetail getRequestedDetails() const override;
 
  protected:
   base::trace_event::ProcessMemoryDump* process_memory_dump() {
@@ -52,13 +57,16 @@
   }
 
  private:
+  // Helper to create allocator dumps.
+  base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
+      const char* dumpName);
+
   std::string dump_name_prefix_;
 
   base::trace_event::ProcessMemoryDump* process_memory_dump_;
 
-  // Helper to create allocator dumps.
-  base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
-      const char* dumpName);
+  // Stores the level of detail for the current dump.
+  LevelOfDetail request_level_;
 
   DISALLOW_COPY_AND_ASSIGN(SkTraceMemoryDump_Chrome);
 };
diff --git a/skia/ext/skia_memory_dump_provider.cc b/skia/ext/skia_memory_dump_provider.cc
index 59ff3c0..aaef11f 100644
--- a/skia/ext/skia_memory_dump_provider.cc
+++ b/skia/ext/skia_memory_dump_provider.cc
@@ -26,18 +26,8 @@
 bool SkiaMemoryDumpProvider::OnMemoryDump(
     const base::trace_event::MemoryDumpArgs& args,
     base::trace_event::ProcessMemoryDump* process_memory_dump) {
-  base::trace_event::MemoryAllocatorDump* font_mad =
-      process_memory_dump->CreateAllocatorDump("skia/sk_glyph_cache");
-  font_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
-                      base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-                      SkGraphics::GetFontCacheUsed());
-  font_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameObjectCount,
-                      base::trace_event::MemoryAllocatorDump::kUnitsObjects,
-                      SkGraphics::GetFontCacheCountUsed());
-
-  // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
-  // (crbug.com/499731).
-  SkTraceMemoryDump_Chrome skia_dumper(process_memory_dump);
+  SkTraceMemoryDump_Chrome skia_dumper(args.level_of_detail,
+                                       process_memory_dump);
   SkGraphics::DumpMemoryStatistics(&skia_dumper);
 
   return true;
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index 3594d96cfd..6206f37 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -14,6 +14,8 @@
     "blob/blob_data_item.h",
     "blob/blob_data_snapshot.cc",
     "blob/blob_data_snapshot.h",
+    "blob/blob_reader.cc",
+    "blob/blob_reader.h",
     "blob/blob_storage_context.cc",
     "blob/blob_storage_context.h",
     "blob/blob_url_request_job.cc",
@@ -28,6 +30,8 @@
     "blob/shareable_blob_data_item.h",
     "blob/shareable_file_reference.cc",
     "blob/shareable_file_reference.h",
+    "blob/upload_blob_element_reader.cc",
+    "blob/upload_blob_element_reader.h",
     "blob/view_blob_internals_job.cc",
     "blob/view_blob_internals_job.h",
     "database/database_quota_client.cc",
diff --git a/storage/browser/blob/blob_data_handle.cc b/storage/browser/blob/blob_data_handle.cc
index e3a4be94..3e864fa 100644
--- a/storage/browser/blob/blob_data_handle.cc
+++ b/storage/browser/blob/blob_data_handle.cc
@@ -8,38 +8,98 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/sequenced_task_runner.h"
+#include "base/task_runner.h"
+#include "base/time/time.h"
 #include "storage/browser/blob/blob_data_snapshot.h"
+#include "storage/browser/blob/blob_reader.h"
 #include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/fileapi/file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "url/gurl.h"
 
 namespace storage {
 
+namespace {
+
+class FileStreamReaderProviderImpl
+    : public BlobReader::FileStreamReaderProvider {
+ public:
+  FileStreamReaderProviderImpl(FileSystemContext* file_system_context)
+      : file_system_context_(file_system_context) {}
+  ~FileStreamReaderProviderImpl() override {}
+
+  scoped_ptr<FileStreamReader> CreateForLocalFile(
+      base::TaskRunner* task_runner,
+      const base::FilePath& file_path,
+      int64_t initial_offset,
+      const base::Time& expected_modification_time) override {
+    return make_scoped_ptr(FileStreamReader::CreateForLocalFile(
+        task_runner, file_path, initial_offset, expected_modification_time));
+  }
+
+  scoped_ptr<FileStreamReader> CreateFileStreamReader(
+      const GURL& filesystem_url,
+      int64_t offset,
+      int64_t max_bytes_to_read,
+      const base::Time& expected_modification_time) override {
+    return file_system_context_->CreateFileStreamReader(
+                                   storage::FileSystemURL(
+                                       file_system_context_->CrackURL(
+                                           filesystem_url)),
+                                   offset, max_bytes_to_read,
+                                   expected_modification_time)
+        .Pass();
+  }
+
+ private:
+  scoped_refptr<FileSystemContext> file_system_context_;
+  DISALLOW_COPY_AND_ASSIGN(FileStreamReaderProviderImpl);
+};
+
+}  // namespace
+
 BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared(
     const std::string& uuid,
-    BlobStorageContext* context,
-    base::SequencedTaskRunner* task_runner)
-    : uuid_(uuid), context_(context->AsWeakPtr()) {
+    const std::string& content_type,
+    const std::string& content_disposition,
+    BlobStorageContext* context)
+    : uuid_(uuid),
+      content_type_(content_type),
+      content_disposition_(content_disposition),
+      context_(context->AsWeakPtr()) {
   context_->IncrementBlobRefCount(uuid);
 }
 
+scoped_ptr<BlobReader> BlobDataHandle::CreateReader(
+    FileSystemContext* file_system_context,
+    base::SequencedTaskRunner* file_task_runner) const {
+  return scoped_ptr<BlobReader>(new BlobReader(
+      this, scoped_ptr<BlobReader::FileStreamReaderProvider>(
+                new FileStreamReaderProviderImpl(file_system_context)),
+      file_task_runner));
+}
+
 scoped_ptr<BlobDataSnapshot>
 BlobDataHandle::BlobDataHandleShared::CreateSnapshot() const {
   return context_->CreateSnapshot(uuid_).Pass();
 }
 
-const std::string& BlobDataHandle::BlobDataHandleShared::uuid() const {
-  return uuid_;
-}
-
 BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() {
   if (context_.get())
     context_->DecrementBlobRefCount(uuid_);
 }
 
 BlobDataHandle::BlobDataHandle(const std::string& uuid,
+                               const std::string& content_type,
+                               const std::string& content_disposition,
                                BlobStorageContext* context,
-                               base::SequencedTaskRunner* task_runner)
-    : io_task_runner_(task_runner),
-      shared_(new BlobDataHandleShared(uuid, context, task_runner)) {
+                               base::SequencedTaskRunner* io_task_runner)
+    : io_task_runner_(io_task_runner),
+      shared_(new BlobDataHandleShared(uuid,
+                                       content_type,
+                                       content_disposition,
+                                       context)) {
   DCHECK(io_task_runner_.get());
   DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
 }
@@ -62,7 +122,15 @@
 }
 
 const std::string& BlobDataHandle::uuid() const {
-  return shared_->uuid();
+  return shared_->uuid_;
+}
+
+const std::string& BlobDataHandle::content_type() const {
+  return shared_->content_type_;
+}
+
+const std::string& BlobDataHandle::content_disposition() const {
+  return shared_->content_disposition_;
 }
 
 }  // namespace storage
diff --git a/storage/browser/blob/blob_data_handle.h b/storage/browser/blob/blob_data_handle.h
index 30412415..8eba2c6 100644
--- a/storage/browser/blob/blob_data_handle.h
+++ b/storage/browser/blob/blob_data_handle.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/supports_user_data.h"
 #include "storage/browser/storage_browser_export.h"
@@ -19,7 +20,9 @@
 namespace storage {
 
 class BlobDataSnapshot;
+class BlobReader;
 class BlobStorageContext;
+class FileSystemContext;
 
 // BlobDataHandle ensures that the underlying blob (keyed by the uuid) remains
 // in the BlobStorageContext's collection while this object is alive. Anything
@@ -36,15 +39,25 @@
   BlobDataHandle(const BlobDataHandle& other);  // May be copied on any thread.
   ~BlobDataHandle() override;                   // May be deleted on any thread.
 
-  // A BlobDataSnapshot is used to read the data from the blob.  This object is
+  // A BlobReader is used to read the data from the blob.  This object is
   // intended to be transient and should not be stored for any extended period
   // of time.
+  scoped_ptr<BlobReader> CreateReader(
+      FileSystemContext* file_system_context,
+      base::SequencedTaskRunner* file_task_runner) const;
+
+  // May be accessed on any thread.
+  const std::string& uuid() const;
+  // May be accessed on any thread.
+  const std::string& content_type() const;
+  // May be accessed on any thread.
+  const std::string& content_disposition() const;
+
   // This call and the destruction of the returned snapshot must be called
   // on the IO thread.
+  // TODO(dmurph): Make this protected, where only the BlobReader can call it.
   scoped_ptr<BlobDataSnapshot> CreateSnapshot() const;
 
-  const std::string& uuid() const;  // May be accessed on any thread.
-
  private:
   // Internal class whose destructor is guarenteed to be called on the IO
   // thread.
@@ -52,11 +65,11 @@
       : public base::RefCountedThreadSafe<BlobDataHandleShared> {
    public:
     BlobDataHandleShared(const std::string& uuid,
-                         BlobStorageContext* context,
-                         base::SequencedTaskRunner* task_runner);
+                         const std::string& content_type,
+                         const std::string& content_disposition,
+                         BlobStorageContext* context);
 
     scoped_ptr<BlobDataSnapshot> CreateSnapshot() const;
-    const std::string& uuid() const;
 
    private:
     friend class base::DeleteHelper<BlobDataHandleShared>;
@@ -66,6 +79,8 @@
     virtual ~BlobDataHandleShared();
 
     const std::string uuid_;
+    const std::string content_type_;
+    const std::string content_disposition_;
     base::WeakPtr<BlobStorageContext> context_;
 
     DISALLOW_COPY_AND_ASSIGN(BlobDataHandleShared);
@@ -73,8 +88,10 @@
 
   friend class BlobStorageContext;
   BlobDataHandle(const std::string& uuid,
+                 const std::string& content_type,
+                 const std::string& content_disposition,
                  BlobStorageContext* context,
-                 base::SequencedTaskRunner* task_runner);
+                 base::SequencedTaskRunner* io_task_runner);
 
   scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
   scoped_refptr<BlobDataHandleShared> shared_;
diff --git a/storage/browser/blob/blob_data_snapshot.h b/storage/browser/blob/blob_data_snapshot.h
index f0d47227..01ea2ef2 100644
--- a/storage/browser/blob/blob_data_snapshot.h
+++ b/storage/browser/blob/blob_data_snapshot.h
@@ -53,6 +53,7 @@
   const std::string uuid_;
   const std::string content_type_;
   const std::string content_disposition_;
+
   // Non-const for constrution in BlobStorageContext
   std::vector<scoped_refptr<BlobDataItem>> items_;
 };
diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc
new file mode 100644
index 0000000..ccb4e55
--- /dev/null
+++ b/storage/browser/blob/blob_reader.cc
@@ -0,0 +1,568 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/blob/blob_reader.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/bind.h"
+#include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/disk_cache/disk_cache.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_data_snapshot.h"
+#include "storage/browser/fileapi/file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/common/data_element.h"
+
+namespace storage {
+namespace {
+bool IsFileType(DataElement::Type type) {
+  switch (type) {
+    case DataElement::TYPE_FILE:
+    case DataElement::TYPE_FILE_FILESYSTEM:
+      return true;
+    default:
+      return false;
+  }
+}
+}  // namespace
+
+BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {}
+
+BlobReader::BlobReader(
+    const BlobDataHandle* blob_handle,
+    scoped_ptr<FileStreamReaderProvider> file_stream_provider,
+    base::SequencedTaskRunner* file_task_runner)
+    : file_stream_provider_(file_stream_provider.Pass()),
+      file_task_runner_(file_task_runner),
+      net_error_(net::OK),
+      weak_factory_(this) {
+  if (blob_handle) {
+    blob_data_ = blob_handle->CreateSnapshot().Pass();
+  }
+}
+
+BlobReader::~BlobReader() {
+  STLDeleteValues(&index_to_reader_);
+}
+
+BlobReader::Status BlobReader::CalculateSize(
+    const net::CompletionCallback& done) {
+  DCHECK(!total_size_calculated_);
+  DCHECK(size_callback_.is_null());
+  if (!blob_data_.get()) {
+    return ReportError(net::ERR_FILE_NOT_FOUND);
+  }
+
+  net_error_ = net::OK;
+  total_size_ = 0;
+  const auto& items = blob_data_->items();
+  item_length_list_.resize(items.size());
+  pending_get_file_info_count_ = 0;
+  for (size_t i = 0; i < items.size(); ++i) {
+    const BlobDataItem& item = *items.at(i);
+    if (IsFileType(item.type())) {
+      ++pending_get_file_info_count_;
+      storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
+      if (!reader) {
+        return ReportError(net::ERR_FAILED);
+      }
+      int64_t length_output = reader->GetLength(base::Bind(
+          &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
+      if (length_output == net::ERR_IO_PENDING) {
+        continue;
+      }
+      if (length_output < 0) {
+        return ReportError(length_output);
+      }
+      // We got the length right away
+      --pending_get_file_info_count_;
+      uint64_t resolved_length;
+      if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
+        return ReportError(net::ERR_FILE_NOT_FOUND);
+      }
+      if (!AddItemLength(i, resolved_length)) {
+        return ReportError(net::ERR_FAILED);
+      }
+      continue;
+    }
+
+    if (!AddItemLength(i, item.length()))
+      return ReportError(net::ERR_FAILED);
+  }
+
+  if (pending_get_file_info_count_ == 0) {
+    DidCountSize();
+    return Status::DONE;
+  }
+  // Note: We only set the callback if we know that we're an async operation.
+  size_callback_ = done;
+  return Status::IO_PENDING;
+}
+
+BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) {
+  if (!blob_data_.get()) {
+    return ReportError(net::ERR_FILE_NOT_FOUND);
+  }
+  if (!total_size_calculated_) {
+    return ReportError(net::ERR_FAILED);
+  }
+  if (offset + length > total_size_) {
+    return ReportError(net::ERR_FILE_NOT_FOUND);
+  }
+  // Skip the initial items that are not in the range.
+  remaining_bytes_ = length;
+  const auto& items = blob_data_->items();
+  for (current_item_index_ = 0;
+       current_item_index_ < items.size() &&
+       offset >= item_length_list_[current_item_index_];
+       ++current_item_index_) {
+    offset -= item_length_list_[current_item_index_];
+  }
+
+  // Set the offset that need to jump to for the first item in the range.
+  current_item_offset_ = offset;
+  if (current_item_offset_ == 0)
+    return Status::DONE;
+
+  // Adjust the offset of the first stream if it is of file type.
+  const BlobDataItem& item = *items.at(current_item_index_);
+  if (IsFileType(item.type())) {
+    SetFileReaderAtIndex(current_item_index_,
+                         CreateFileStreamReader(item, offset));
+  }
+  return Status::DONE;
+}
+
+BlobReader::Status BlobReader::Read(net::IOBuffer* buffer,
+                                    size_t dest_size,
+                                    int* bytes_read,
+                                    net::CompletionCallback done) {
+  DCHECK(bytes_read);
+  DCHECK_GE(remaining_bytes_, 0ul);
+  DCHECK(read_callback_.is_null());
+
+  *bytes_read = 0;
+  if (!blob_data_.get()) {
+    return ReportError(net::ERR_FILE_NOT_FOUND);
+  }
+  if (!total_size_calculated_) {
+    return ReportError(net::ERR_FAILED);
+  }
+
+  // Bail out immediately if we encountered an error.
+  if (net_error_ != net::OK) {
+    return Status::NET_ERROR;
+  }
+
+  DCHECK_GE(dest_size, 0ul);
+  if (remaining_bytes_ < static_cast<uint64_t>(dest_size))
+    dest_size = static_cast<int>(remaining_bytes_);
+
+  // If we should copy zero bytes because |remaining_bytes_| is zero, short
+  // circuit here.
+  if (!dest_size) {
+    *bytes_read = 0;
+    return Status::DONE;
+  }
+
+  // Keep track of the buffer.
+  DCHECK(!read_buf_.get());
+  read_buf_ = new net::DrainableIOBuffer(buffer, dest_size);
+
+  Status status = ReadLoop(bytes_read);
+  if (status == Status::IO_PENDING)
+    read_callback_ = done;
+  return status;
+}
+
+void BlobReader::Kill() {
+  DeleteCurrentFileReader();
+  weak_factory_.InvalidateWeakPtrs();
+}
+
+bool BlobReader::IsInMemory() const {
+  if (!blob_data_.get()) {
+    return true;
+  }
+  for (const auto& item : blob_data_->items()) {
+    if (item->type() != DataElement::TYPE_BYTES) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void BlobReader::InvalidateCallbacksAndDone(int net_error,
+                                            net::CompletionCallback done) {
+  net_error_ = net_error;
+  weak_factory_.InvalidateWeakPtrs();
+  size_callback_.Reset();
+  read_callback_.Reset();
+  read_buf_ = nullptr;
+  done.Run(net_error);
+}
+
+BlobReader::Status BlobReader::ReportError(int net_error) {
+  net_error_ = net_error;
+  return Status::NET_ERROR;
+}
+
+bool BlobReader::AddItemLength(size_t index, uint64_t item_length) {
+  if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) {
+    return false;
+  }
+
+  // Cache the size and add it to the total size.
+  DCHECK_LT(index, item_length_list_.size());
+  item_length_list_[index] = item_length;
+  total_size_ += item_length;
+  return true;
+}
+
+bool BlobReader::ResolveFileItemLength(const BlobDataItem& item,
+                                       int64_t total_length,
+                                       uint64_t* output_length) {
+  DCHECK(IsFileType(item.type()));
+  DCHECK(output_length);
+  uint64_t file_length = total_length;
+  uint64_t item_offset = item.offset();
+  uint64_t item_length = item.length();
+  if (item_offset > file_length) {
+    return false;
+  }
+
+  uint64 max_length = file_length - item_offset;
+
+  // If item length is undefined, then we need to use the file size being
+  // resolved in the real time.
+  if (item_length == std::numeric_limits<uint64>::max()) {
+    item_length = max_length;
+  } else if (item_length > max_length) {
+    return false;
+  }
+
+  *output_length = item_length;
+  return true;
+}
+
+void BlobReader::DidGetFileItemLength(size_t index, int64_t result) {
+  // Do nothing if we have encountered an error.
+  if (net_error_)
+    return;
+
+  if (result == net::ERR_UPLOAD_FILE_CHANGED)
+    result = net::ERR_FILE_NOT_FOUND;
+  if (result < 0) {
+    InvalidateCallbacksAndDone(result, size_callback_);
+    return;
+  }
+
+  const auto& items = blob_data_->items();
+  DCHECK_LT(index, items.size());
+  const BlobDataItem& item = *items.at(index);
+  uint64_t length;
+  if (!ResolveFileItemLength(item, result, &length)) {
+    InvalidateCallbacksAndDone(net::ERR_FILE_NOT_FOUND, size_callback_);
+    return;
+  }
+  if (!AddItemLength(index, length)) {
+    InvalidateCallbacksAndDone(net::ERR_FAILED, size_callback_);
+    return;
+  }
+
+  if (--pending_get_file_info_count_ == 0)
+    DidCountSize();
+}
+
+void BlobReader::DidCountSize() {
+  DCHECK(!net_error_);
+  total_size_calculated_ = true;
+  remaining_bytes_ = total_size_;
+  // This is set only if we're async.
+  if (!size_callback_.is_null()) {
+    net::CompletionCallback done = size_callback_;
+    size_callback_.Reset();
+    done.Run(net::OK);
+  }
+}
+
+BlobReader::Status BlobReader::ReadLoop(int* bytes_read) {
+  // Read until we encounter an error or could not get the data immediately.
+  while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) {
+    Status read_status = ReadItem();
+    if (read_status == Status::DONE) {
+      continue;
+    }
+    return read_status;
+  }
+
+  *bytes_read = BytesReadCompleted();
+  return Status::DONE;
+}
+
+BlobReader::Status BlobReader::ReadItem() {
+  // Are we done with reading all the blob data?
+  if (remaining_bytes_ == 0)
+    return Status::DONE;
+
+  const auto& items = blob_data_->items();
+  // If we get to the last item but still expect something to read, bail out
+  // since something is wrong.
+  if (current_item_index_ >= items.size()) {
+    return ReportError(net::ERR_FAILED);
+  }
+
+  // Compute the bytes to read for current item.
+  int bytes_to_read = ComputeBytesToRead();
+
+  // If nothing to read for current item, advance to next item.
+  if (bytes_to_read == 0) {
+    AdvanceItem();
+    return Status::DONE;
+  }
+
+  // Do the reading.
+  const BlobDataItem& item = *items.at(current_item_index_);
+  if (item.type() == DataElement::TYPE_BYTES) {
+    ReadBytesItem(item, bytes_to_read);
+    return Status::DONE;
+  }
+  if (item.type() == DataElement::TYPE_DISK_CACHE_ENTRY)
+    return ReadDiskCacheEntryItem(item, bytes_to_read);
+  if (!IsFileType(item.type())) {
+    NOTREACHED();
+    return ReportError(net::ERR_FAILED);
+  }
+  storage::FileStreamReader* const reader =
+      GetOrCreateFileReaderAtIndex(current_item_index_);
+  if (!reader) {
+    return ReportError(net::ERR_FAILED);
+  }
+
+  return ReadFileItem(reader, bytes_to_read);
+}
+
+void BlobReader::AdvanceItem() {
+  // Close the file if the current item is a file.
+  DeleteCurrentFileReader();
+
+  // Advance to the next item.
+  current_item_index_++;
+  current_item_offset_ = 0;
+}
+
+void BlobReader::AdvanceBytesRead(int result) {
+  DCHECK_GT(result, 0);
+
+  // Do we finish reading the current item?
+  current_item_offset_ += result;
+  if (current_item_offset_ == item_length_list_[current_item_index_])
+    AdvanceItem();
+
+  // Subtract the remaining bytes.
+  remaining_bytes_ -= result;
+  DCHECK_GE(remaining_bytes_, 0ul);
+
+  // Adjust the read buffer.
+  read_buf_->DidConsume(result);
+  DCHECK_GE(read_buf_->BytesRemaining(), 0);
+}
+
+void BlobReader::ReadBytesItem(const BlobDataItem& item, int bytes_to_read) {
+  TRACE_EVENT1("Blob", "BlobReader::ReadBytesItem", "uuid", blob_data_->uuid());
+  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
+
+  memcpy(read_buf_->data(), item.bytes() + item.offset() + current_item_offset_,
+         bytes_to_read);
+
+  AdvanceBytesRead(bytes_to_read);
+}
+
+BlobReader::Status BlobReader::ReadFileItem(FileStreamReader* reader,
+                                            int bytes_to_read) {
+  DCHECK(!io_pending_)
+      << "Can't begin IO while another IO operation is pending.";
+  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
+  DCHECK(reader);
+  TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
+                           blob_data_->uuid());
+  const int result = reader->Read(
+      read_buf_.get(), bytes_to_read,
+      base::Bind(&BlobReader::DidReadFile, weak_factory_.GetWeakPtr()));
+  if (result >= 0) {
+    AdvanceBytesRead(result);
+    return Status::DONE;
+  }
+  if (result == net::ERR_IO_PENDING) {
+    io_pending_ = true;
+    return Status::IO_PENDING;
+  }
+  return ReportError(result);
+}
+
+void BlobReader::DidReadFile(int result) {
+  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
+                         blob_data_->uuid());
+  DidReadItem(result);
+}
+
+void BlobReader::ContinueAsyncReadLoop() {
+  int bytes_read = 0;
+  Status read_status = ReadLoop(&bytes_read);
+  switch (read_status) {
+    case Status::DONE: {
+      net::CompletionCallback done = read_callback_;
+      read_callback_.Reset();
+      done.Run(bytes_read);
+      return;
+    }
+    case Status::NET_ERROR:
+      InvalidateCallbacksAndDone(net_error_, read_callback_);
+      return;
+    case Status::IO_PENDING:
+      return;
+  }
+}
+
+void BlobReader::DeleteCurrentFileReader() {
+  SetFileReaderAtIndex(current_item_index_, scoped_ptr<FileStreamReader>());
+}
+
+BlobReader::Status BlobReader::ReadDiskCacheEntryItem(const BlobDataItem& item,
+                                                      int bytes_to_read) {
+  DCHECK(!io_pending_)
+      << "Can't begin IO while another IO operation is pending.";
+  TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadDiskCacheItem", this,
+                           "uuid", blob_data_->uuid());
+  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
+
+  const int result = item.disk_cache_entry()->ReadData(
+      item.disk_cache_stream_index(), current_item_offset_, read_buf_.get(),
+      bytes_to_read, base::Bind(&BlobReader::DidReadDiskCacheEntry,
+                                weak_factory_.GetWeakPtr()));
+  if (result >= 0) {
+    AdvanceBytesRead(result);
+    return Status::DONE;
+  }
+  if (result == net::ERR_IO_PENDING) {
+    io_pending_ = true;
+    return Status::IO_PENDING;
+  }
+  return ReportError(result);
+}
+
+void BlobReader::DidReadDiskCacheEntry(int result) {
+  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadDiskCacheItem", this, "uuid",
+                         blob_data_->uuid());
+  DidReadItem(result);
+}
+
+void BlobReader::DidReadItem(int result) {
+  DCHECK(io_pending_) << "Asynchronous IO completed while IO wasn't pending?";
+  io_pending_ = false;
+  if (result <= 0) {
+    InvalidateCallbacksAndDone(result, read_callback_);
+    return;
+  }
+  AdvanceBytesRead(result);
+  ContinueAsyncReadLoop();
+}
+
+int BlobReader::BytesReadCompleted() {
+  int bytes_read = read_buf_->BytesConsumed();
+  read_buf_ = nullptr;
+  return bytes_read;
+}
+
+int BlobReader::ComputeBytesToRead() const {
+  uint64_t current_item_length = item_length_list_[current_item_index_];
+
+  uint64_t item_remaining = current_item_length - current_item_offset_;
+  uint64_t buf_remaining = read_buf_->BytesRemaining();
+  uint64_t max_int_value = std::numeric_limits<int>::max();
+  // Here we make sure we don't overflow 'max int'.
+  uint64_t min = std::min(
+      std::min(std::min(item_remaining, buf_remaining), remaining_bytes_),
+      max_int_value);
+
+  return static_cast<int>(min);
+}
+
+FileStreamReader* BlobReader::GetOrCreateFileReaderAtIndex(size_t index) {
+  const auto& items = blob_data_->items();
+  DCHECK_LT(index, items.size());
+  const BlobDataItem& item = *items.at(index);
+  if (!IsFileType(item.type()))
+    return nullptr;
+  auto it = index_to_reader_.find(index);
+  if (it != index_to_reader_.end()) {
+    DCHECK(it->second);
+    return it->second;
+  }
+  scoped_ptr<FileStreamReader> reader = CreateFileStreamReader(item, 0);
+  FileStreamReader* ret_value = reader.get();
+  if (!ret_value)
+    return nullptr;
+  index_to_reader_[index] = reader.release();
+  return ret_value;
+}
+
+scoped_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
+    const BlobDataItem& item,
+    uint64_t additional_offset) {
+  DCHECK(IsFileType(item.type()));
+
+  switch (item.type()) {
+    case DataElement::TYPE_FILE:
+      return file_stream_provider_->CreateForLocalFile(
+                                      file_task_runner_.get(), item.path(),
+                                      item.offset() + additional_offset,
+                                      item.expected_modification_time())
+          .Pass();
+    case DataElement::TYPE_FILE_FILESYSTEM:
+      return file_stream_provider_
+          ->CreateFileStreamReader(
+              item.filesystem_url(), item.offset() + additional_offset,
+              item.length() == std::numeric_limits<uint64_t>::max()
+                  ? storage::kMaximumLength
+                  : item.length() - additional_offset,
+              item.expected_modification_time())
+          .Pass();
+    case DataElement::TYPE_BLOB:
+    case DataElement::TYPE_BYTES:
+    case DataElement::TYPE_DISK_CACHE_ENTRY:
+    case DataElement::TYPE_UNKNOWN:
+      break;
+  }
+
+  NOTREACHED();
+  return nullptr;
+}
+
+void BlobReader::SetFileReaderAtIndex(size_t index,
+                                      scoped_ptr<FileStreamReader> reader) {
+  auto found = index_to_reader_.find(current_item_index_);
+  if (found != index_to_reader_.end()) {
+    if (found->second) {
+      delete found->second;
+    }
+    if (!reader.get()) {
+      index_to_reader_.erase(found);
+      return;
+    }
+    found->second = reader.release();
+  } else if (reader.get()) {
+    index_to_reader_[current_item_index_] = reader.release();
+  }
+}
+
+}  // namespace storage
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h
new file mode 100644
index 0000000..54b262f
--- /dev/null
+++ b/storage/browser/blob/blob_reader.h
@@ -0,0 +1,190 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STORAGE_BROWSER_BLOB_BLOB_READER_H_
+#define STORAGE_BROWSER_BLOB_BLOB_READER_H_
+
+#include <stdint.h>
+#include <map>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/completion_callback.h"
+#include "storage/browser/storage_browser_export.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+class TaskRunner;
+class Time;
+}
+
+namespace net {
+class DrainableIOBuffer;
+class IOBuffer;
+}
+
+namespace storage {
+class BlobDataItem;
+class BlobDataHandle;
+class BlobDataSnapshot;
+class FileStreamReader;
+class FileSystemContext;
+
+// The blob reader is used to read a blob.  This can only be used in the browser
+// process, and we need to be on the IO thread.
+//  * There can only be one read happening at a time per reader.
+//  * If a status of Status::NET_ERROR is returned, that means there was an
+//    error and the net_error() variable contains the error code.
+// Use a BlobDataHandle to create an instance.
+class STORAGE_EXPORT BlobReader {
+ public:
+  class STORAGE_EXPORT FileStreamReaderProvider {
+   public:
+    virtual ~FileStreamReaderProvider();
+
+    virtual scoped_ptr<FileStreamReader> CreateForLocalFile(
+        base::TaskRunner* task_runner,
+        const base::FilePath& file_path,
+        int64_t initial_offset,
+        const base::Time& expected_modification_time) = 0;
+
+    virtual scoped_ptr<FileStreamReader> CreateFileStreamReader(
+        const GURL& filesystem_url,
+        int64_t offset,
+        int64_t max_bytes_to_read,
+        const base::Time& expected_modification_time) = 0;
+  };
+  enum class Status { NET_ERROR, IO_PENDING, DONE };
+  virtual ~BlobReader();
+
+  // This calculates the total size of the blob, and initializes the reading
+  // cursor.
+  //  * This should only be called once per reader.
+  //  * Status::Done means that the total_size() value is populated and you can
+  //    continue to SetReadRange or Read.
+  //  * The 'done' callback is only called if Status::IO_PENDING is returned.
+  //    The callback value contains the error code or net::OK. Please use the
+  //    total_size() value to query the blob size, as it's uint64_t.
+  Status CalculateSize(const net::CompletionCallback& done);
+
+  // Used to set the read position.
+  // * This should be called after CalculateSize and before Read.
+  // * Range can only be set once.
+  Status SetReadRange(uint64_t position, uint64_t length);
+
+  // Reads a portion of the data.
+  // * CalculateSize (and optionally SetReadRange) must be called beforehand.
+  // * bytes_read is populated only if Status::DONE is returned. Otherwise the
+  //   bytes read (or error code) is populated in the 'done' callback.
+  // * The done callback is only called if Status::IO_PENDING is returned.
+  // * This method can be called multiple times. A bytes_read value (either from
+  //   the callback for Status::IO_PENDING or the bytes_read value for
+  //   Status::DONE) of 0 means we're finished reading.
+  Status Read(net::IOBuffer* buffer,
+              size_t dest_size,
+              int* bytes_read,
+              net::CompletionCallback done);
+
+  // Kills reading and invalidates all callbacks. The reader cannot be used
+  // after this call.
+  void Kill();
+
+  // Returns if all of the blob's items are in memory.
+  bool IsInMemory() const;
+
+  // Returns the remaining bytes to be read in the blob. This is populated
+  // after CalculateSize, and is modified by SetReadRange.
+  uint64_t remaining_bytes() const { return remaining_bytes_; }
+
+  // Returns the net error code if there was an error. Defaults to net::OK.
+  int net_error() const { return net_error_; }
+
+  // Returns the total size of the blob. This is populated after CalculateSize
+  // is called.
+  uint64_t total_size() const { return total_size_; }
+
+ protected:
+  friend class BlobDataHandle;
+  friend class BlobReaderTest;
+
+  BlobReader(const BlobDataHandle* blob_handle,
+             scoped_ptr<FileStreamReaderProvider> file_stream_provider,
+             base::SequencedTaskRunner* file_task_runner);
+
+  bool total_size_calculated() const { return total_size_calculated_; }
+
+ private:
+  Status ReportError(int net_error);
+  void InvalidateCallbacksAndDone(int net_error, net::CompletionCallback done);
+
+  bool AddItemLength(size_t index, uint64_t length);
+  bool ResolveFileItemLength(const BlobDataItem& item,
+                             int64_t total_length,
+                             uint64_t* output_length);
+  void DidGetFileItemLength(size_t index, int64_t result);
+  void DidCountSize();
+
+  // For reading the blob.
+  // Returns if we're done, PENDING_IO if we're waiting on async.
+  Status ReadLoop(int* bytes_read);
+  // Called from asynchronously called methods to continue the read loop.
+  void ContinueAsyncReadLoop();
+  // PENDING_IO means we're waiting on async.
+  Status ReadItem();
+  void AdvanceItem();
+  void AdvanceBytesRead(int result);
+  void ReadBytesItem(const BlobDataItem& item, int bytes_to_read);
+  BlobReader::Status ReadFileItem(FileStreamReader* reader, int bytes_to_read);
+  void DidReadFile(int result);
+  void DeleteCurrentFileReader();
+  Status ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read);
+  void DidReadDiskCacheEntry(int result);
+  void DidReadItem(int result);
+  int ComputeBytesToRead() const;
+  int BytesReadCompleted();
+
+  // Returns a FileStreamReader for a blob item at |index|.
+  // If the item at |index| is not of file this returns NULL.
+  FileStreamReader* GetOrCreateFileReaderAtIndex(size_t index);
+  // If the reader is null, then this basically performs a delete operation.
+  void SetFileReaderAtIndex(size_t index, scoped_ptr<FileStreamReader> reader);
+  // Creates a FileStreamReader for the item with additional_offset.
+  scoped_ptr<FileStreamReader> CreateFileStreamReader(
+      const BlobDataItem& item,
+      uint64_t additional_offset);
+
+  scoped_ptr<BlobDataSnapshot> blob_data_;
+  scoped_ptr<FileStreamReaderProvider> file_stream_provider_;
+  scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
+
+  int net_error_;
+  bool item_list_populated_ = false;
+  std::vector<uint64_t> item_length_list_;
+
+  scoped_refptr<net::DrainableIOBuffer> read_buf_;
+
+  bool total_size_calculated_ = false;
+  uint64_t total_size_ = 0;
+  uint64_t remaining_bytes_ = 0;
+  size_t pending_get_file_info_count_ = 0;
+  std::map<size_t, FileStreamReader*> index_to_reader_;
+  size_t current_item_index_ = 0;
+  uint64_t current_item_offset_ = 0;
+
+  bool io_pending_ = false;
+
+  net::CompletionCallback size_callback_;
+  net::CompletionCallback read_callback_;
+
+  base::WeakPtrFactory<BlobReader> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(BlobReader);
+};
+
+}  // namespace storage
+#endif  // STORAGE_BROWSER_BLOB_BLOB_READER_H_
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index d08ccb3..7114696 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -77,9 +77,9 @@
   if (entry->flags & EXCEEDED_MEMORY)
     return result.Pass();
   DCHECK(!entry->IsBeingBuilt());
-  result.reset(
-      new BlobDataHandle(uuid, this,
-                         base::ThreadTaskRunnerHandle::Get().get()));
+  result.reset(new BlobDataHandle(uuid, entry->data->content_type(),
+                                  entry->data->content_disposition(), this,
+                                  base::ThreadTaskRunnerHandle::Get().get()));
   return result.Pass();
 }
 
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc
index f429020..6ec2fe5 100644
--- a/storage/browser/blob/blob_url_request_job.cc
+++ b/storage/browser/blob/blob_url_request_job.cc
@@ -31,6 +31,8 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_error_job.h"
 #include "net/url_request/url_request_status.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
 #include "storage/browser/fileapi/file_stream_reader.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
@@ -38,41 +40,24 @@
 
 namespace storage {
 
-namespace {
-
-bool IsFileType(DataElement::Type type) {
-  switch (type) {
-    case DataElement::TYPE_FILE:
-    case DataElement::TYPE_FILE_FILESYSTEM:
-      return true;
-    default:
-      return false;
-  }
-}
-
-}  // namespace
-
 BlobURLRequestJob::BlobURLRequestJob(
     net::URLRequest* request,
     net::NetworkDelegate* network_delegate,
-    scoped_ptr<BlobDataSnapshot> blob_data,
-    storage::FileSystemContext* file_system_context,
+    BlobDataHandle* blob_handle,
+    FileSystemContext* file_system_context,
     base::SingleThreadTaskRunner* file_task_runner)
     : net::URLRequestJob(request, network_delegate),
-      blob_data_(blob_data.Pass()),
-      file_system_context_(file_system_context),
-      file_task_runner_(file_task_runner),
-      total_size_(0),
-      remaining_bytes_(0),
-      pending_get_file_info_count_(0),
-      current_item_index_(0),
-      current_item_offset_(0),
       error_(false),
       byte_range_set_(false),
       weak_factory_(this) {
   TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest", this, "uuid",
-                           blob_data_ ? blob_data_->uuid() : "NotFound");
-  DCHECK(file_task_runner_.get());
+                           blob_handle ? blob_handle->uuid() : "NotFound");
+  DCHECK(file_task_runner);
+  if (blob_handle) {
+    blob_handle_.reset(new BlobDataHandle(*blob_handle));
+    blob_reader_ =
+        blob_handle_->CreateReader(file_system_context, file_task_runner);
+  }
 }
 
 void BlobURLRequestJob::Start() {
@@ -83,8 +68,9 @@
 }
 
 void BlobURLRequestJob::Kill() {
-  DeleteCurrentFileReader();
-
+  if (blob_reader_) {
+    blob_reader_->Kill();
+  }
   net::URLRequestJob::Kill();
   weak_factory_.InvalidateWeakPtrs();
 }
@@ -92,9 +78,10 @@
 bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest,
                                     int dest_size,
                                     int* bytes_read) {
+  TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadRawData", this, "uuid",
+                           blob_handle_ ? blob_handle_->uuid() : "NotFound");
   DCHECK_NE(dest_size, 0);
   DCHECK(bytes_read);
-  DCHECK_GE(remaining_bytes_, 0);
 
   // Bail out immediately if we encounter an error.
   if (error_) {
@@ -102,21 +89,27 @@
     return true;
   }
 
-  if (remaining_bytes_ < dest_size)
-    dest_size = static_cast<int>(remaining_bytes_);
+  BlobReader::Status read_status =
+      blob_reader_->Read(dest, dest_size, bytes_read,
+                         base::Bind(&BlobURLRequestJob::DidReadRawData,
+                                    weak_factory_.GetWeakPtr()));
 
-  // If we should copy zero bytes because |remaining_bytes_| is zero, short
-  // circuit here.
-  if (!dest_size) {
-    *bytes_read = 0;
-    return true;
+  switch (read_status) {
+    case BlobReader::Status::NET_ERROR:
+      NotifyFailure(blob_reader_->net_error());
+      TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
+                             blob_handle_ ? blob_handle_->uuid() : "NotFound");
+      return false;
+    case BlobReader::Status::IO_PENDING:
+      SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+      return false;
+    case BlobReader::Status::DONE:
+      TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
+                             blob_handle_ ? blob_handle_->uuid() : "NotFound");
+      return true;
   }
-
-  // Keep track of the buffer.
-  DCHECK(!read_buf_.get());
-  read_buf_ = new net::DrainableIOBuffer(dest, dest_size);
-
-  return ReadLoop(bytes_read);
+  NOTREACHED();
+  return true;
 }
 
 bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const {
@@ -159,13 +152,11 @@
 }
 
 BlobURLRequestJob::~BlobURLRequestJob() {
-  STLDeleteValues(&index_to_reader_);
   TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest", this, "uuid",
-                         blob_data_ ? blob_data_->uuid() : "NotFound");
+                         blob_handle_ ? blob_handle_->uuid() : "NotFound");
 }
 
 void BlobURLRequestJob::DidStart() {
-  current_file_chunk_number_ = 0;
   error_ = false;
 
   // We only support GET request per the spec.
@@ -175,379 +166,79 @@
   }
 
   // If the blob data is not present, bail out.
-  if (!blob_data_) {
+  if (!blob_handle_) {
     NotifyFailure(net::ERR_FILE_NOT_FOUND);
     return;
   }
 
-  CountSize();
-}
-
-bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) {
-  if (item_length > kint64max - total_size_) {
-    TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid",
-                           blob_data_->uuid());
-    NotifyFailure(net::ERR_FAILED);
-    return false;
-  }
-
-  // Cache the size and add it to the total size.
-  DCHECK_LT(index, item_length_list_.size());
-  item_length_list_[index] = item_length;
-  total_size_ += item_length;
-  return true;
-}
-
-bool BlobURLRequestJob::CountSize() {
   TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::CountSize", this, "uuid",
-                           blob_data_->uuid());
-  pending_get_file_info_count_ = 0;
-  total_size_ = 0;
-  const auto& items = blob_data_->items();
-  item_length_list_.resize(items.size());
-
-  for (size_t i = 0; i < items.size(); ++i) {
-    const BlobDataItem& item = *items.at(i);
-    if (IsFileType(item.type())) {
-      ++pending_get_file_info_count_;
-      storage::FileStreamReader* const reader = GetFileStreamReader(i);
-      if (!reader) {
-        NotifyFailure(net::ERR_FAILED);
-        return false;
-      }
-      if (!reader->GetLength(
-              base::Bind(&BlobURLRequestJob::DidGetFileItemLength,
-                         weak_factory_.GetWeakPtr(), i))) {
-        NotifyFailure(net::ERR_FILE_NOT_FOUND);
-        return false;
-      }
-      continue;
-    }
-
-    if (!AddItemLength(i, item.length()))
-      return false;
+                           blob_handle_->uuid());
+  BlobReader::Status size_status = blob_reader_->CalculateSize(base::Bind(
+      &BlobURLRequestJob::DidCalculateSize, weak_factory_.GetWeakPtr()));
+  switch (size_status) {
+    case BlobReader::Status::NET_ERROR:
+      NotifyFailure(blob_reader_->net_error());
+      return;
+    case BlobReader::Status::IO_PENDING:
+      SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+      return;
+    case BlobReader::Status::DONE:
+      DidCalculateSize(net::OK);
+      return;
   }
-
-  if (pending_get_file_info_count_ == 0)
-    DidCountSize(net::OK);
-
-  return true;
 }
 
-void BlobURLRequestJob::DidCountSize(int error) {
-  DCHECK(!error_);
+void BlobURLRequestJob::DidCalculateSize(int result) {
   TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid",
-                         blob_data_->uuid());
+                         blob_handle_->uuid());
+  // Clear the IO_PENDING status
+  SetStatus(net::URLRequestStatus());
 
-  // If an error occured, bail out.
-  if (error != net::OK) {
-    NotifyFailure(error);
+  if (result != net::OK) {
+    NotifyFailure(result);
     return;
   }
 
   // Apply the range requirement.
-  if (!byte_range_.ComputeBounds(total_size_)) {
+  if (!byte_range_.ComputeBounds(blob_reader_->total_size())) {
     NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
     return;
   }
 
-  remaining_bytes_ = base::checked_cast<int64>(
+  DCHECK_LE(byte_range_.first_byte_position(),
+            byte_range_.last_byte_position() + 1);
+  uint64_t length = base::checked_cast<uint64_t>(
       byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1);
-  DCHECK_GE(remaining_bytes_, 0);
 
-  // Do the seek at the beginning of the request.
-  if (byte_range_.first_byte_position())
-    Seek(byte_range_.first_byte_position());
+  if (byte_range_set_)
+    blob_reader_->SetReadRange(byte_range_.first_byte_position(), length);
 
-  NotifySuccess();
-}
-
-void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) {
-  // Do nothing if we have encountered an error.
-  if (error_)
-    return;
-
-  if (result == net::ERR_UPLOAD_FILE_CHANGED) {
-    NotifyFailure(net::ERR_FILE_NOT_FOUND);
-    return;
-  } else if (result < 0) {
-    NotifyFailure(result);
-    return;
-  }
-
-  const auto& items = blob_data_->items();
-  DCHECK_LT(index, items.size());
-  const BlobDataItem& item = *items.at(index);
-  DCHECK(IsFileType(item.type()));
-
-  uint64 file_length = result;
-  uint64 item_offset = item.offset();
-  uint64 item_length = item.length();
-
-  if (item_offset > file_length) {
-    NotifyFailure(net::ERR_FILE_NOT_FOUND);
-    return;
-  }
-
-  uint64 max_length = file_length - item_offset;
-
-  // If item length is undefined, then we need to use the file size being
-  // resolved in the real time.
-  if (item_length == std::numeric_limits<uint64>::max()) {
-    item_length = max_length;
-  } else if (item_length > max_length) {
-    NotifyFailure(net::ERR_FILE_NOT_FOUND);
-    return;
-  }
-
-  if (!AddItemLength(index, item_length))
-    return;
-
-  if (--pending_get_file_info_count_ == 0)
-    DidCountSize(net::OK);
-}
-
-void BlobURLRequestJob::Seek(int64 offset) {
-  // Skip the initial items that are not in the range.
-  const auto& items = blob_data_->items();
-  for (current_item_index_ = 0;
-       current_item_index_ < items.size() &&
-           offset >= item_length_list_[current_item_index_];
-       ++current_item_index_) {
-    offset -= item_length_list_[current_item_index_];
-  }
-
-  // Set the offset that need to jump to for the first item in the range.
-  current_item_offset_ = offset;
-
-  if (offset == 0)
-    return;
-
-  // Adjust the offset of the first stream if it is of file type.
-  const BlobDataItem& item = *items.at(current_item_index_);
-  if (IsFileType(item.type())) {
-    DeleteCurrentFileReader();
-    CreateFileStreamReader(current_item_index_, offset);
-  }
-}
-
-bool BlobURLRequestJob::ReadItem() {
-  // Are we done with reading all the blob data?
-  if (remaining_bytes_ == 0)
-    return true;
-
-  const auto& items = blob_data_->items();
-  // If we get to the last item but still expect something to read, bail out
-  // since something is wrong.
-  if (current_item_index_ >= items.size()) {
-    NotifyFailure(net::ERR_FAILED);
-    return false;
-  }
-
-  // Compute the bytes to read for current item.
-  int bytes_to_read = ComputeBytesToRead();
-
-  // If nothing to read for current item, advance to next item.
-  if (bytes_to_read == 0) {
-    AdvanceItem();
-    return true;
-  }
-
-  // Do the reading.
-  const BlobDataItem& item = *items.at(current_item_index_);
-  if (item.type() == DataElement::TYPE_BYTES)
-    return ReadBytesItem(item, bytes_to_read);
-  if (item.type() == DataElement::TYPE_DISK_CACHE_ENTRY)
-    return ReadDiskCacheEntryItem(item, bytes_to_read);
-  if (!IsFileType(item.type())) {
-    NOTREACHED();
-    return false;
-  }
-  storage::FileStreamReader* const reader =
-      GetFileStreamReader(current_item_index_);
-  if (!reader) {
-    NotifyFailure(net::ERR_FAILED);
-    return false;
-  }
-
-  return ReadFileItem(reader, bytes_to_read);
-}
-
-void BlobURLRequestJob::AdvanceItem() {
-  // Close the file if the current item is a file.
-  DeleteCurrentFileReader();
-
-  // Advance to the next item.
-  current_item_index_++;
-  current_item_offset_ = 0;
-}
-
-void BlobURLRequestJob::AdvanceBytesRead(int result) {
-  DCHECK_GT(result, 0);
-
-  // Do we finish reading the current item?
-  current_item_offset_ += result;
-  if (current_item_offset_ == item_length_list_[current_item_index_])
-    AdvanceItem();
-
-  // Subtract the remaining bytes.
-  remaining_bytes_ -= result;
-  DCHECK_GE(remaining_bytes_, 0);
-
-  // Adjust the read buffer.
-  read_buf_->DidConsume(result);
-  DCHECK_GE(read_buf_->BytesRemaining(), 0);
-}
-
-bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item,
-                                      int bytes_to_read) {
-  TRACE_EVENT1("Blob", "BlobRequest::ReadBytesItem", "uuid",
-               blob_data_->uuid());
-  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
-
-  memcpy(read_buf_->data(),
-         item.bytes() + item.offset() + current_item_offset_,
-         bytes_to_read);
-
-  AdvanceBytesRead(bytes_to_read);
-  return true;
-}
-
-bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader,
-                                     int bytes_to_read) {
-  DCHECK(!GetStatus().is_io_pending())
-      << "Can't begin IO while another IO operation is pending.";
-  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
-  DCHECK(reader);
-  int chunk_number = current_file_chunk_number_++;
-  TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
-                           blob_data_->uuid());
-  const int result =
-      reader->Read(read_buf_.get(), bytes_to_read,
-                   base::Bind(&BlobURLRequestJob::DidReadFile,
-                              weak_factory_.GetWeakPtr(), chunk_number));
-  if (result >= 0) {
-    AdvanceBytesRead(result);
-    return true;
-  }
-  if (result == net::ERR_IO_PENDING)
-    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
-  else
-    NotifyFailure(result);
-  return false;
-}
-
-void BlobURLRequestJob::DidReadFile(int chunk_number, int result) {
-  DCHECK(GetStatus().is_io_pending())
-      << "Asynchronous IO completed while IO wasn't pending?";
-  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
-                         blob_data_->uuid());
-  if (result <= 0) {
-    NotifyFailure(result);
-    return;
-  }
-  SetStatus(net::URLRequestStatus());  // Clear the IO_PENDING status
-
-  AdvanceBytesRead(result);
-
-  // Otherwise, continue the reading.
-  int bytes_read = 0;
-  if (ReadLoop(&bytes_read))
-    NotifyReadComplete(bytes_read);
-}
-
-void BlobURLRequestJob::DeleteCurrentFileReader() {
-  IndexToReaderMap::iterator found = index_to_reader_.find(current_item_index_);
-  if (found != index_to_reader_.end() && found->second) {
-    delete found->second;
-    index_to_reader_.erase(found);
-  }
-}
-
-bool BlobURLRequestJob::ReadDiskCacheEntryItem(const BlobDataItem& item,
-                                               int bytes_to_read) {
-  DCHECK(!GetStatus().is_io_pending())
-      << "Can't begin IO while another IO operation is pending.";
-  DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
-
-  const int result = item.disk_cache_entry()->ReadData(
-      item.disk_cache_stream_index(), current_item_offset_, read_buf_.get(),
-      bytes_to_read, base::Bind(&BlobURLRequestJob::DidReadDiskCacheEntry,
-                                weak_factory_.GetWeakPtr()));
-  if (result >= 0) {
-    AdvanceBytesRead(result);
-    return true;
-  }
-  if (result == net::ERR_IO_PENDING)
-    SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
-  else
-    NotifyFailure(result);
-  return false;
-}
-
-void BlobURLRequestJob::DidReadDiskCacheEntry(int result) {
-  DCHECK(GetStatus().is_io_pending())
-      << "Asynchronous IO completed while IO wasn't pending?";
-  if (result <= 0) {
-    NotifyFailure(result);
-    return;
-  }
-  SetStatus(net::URLRequestStatus());
-
-  AdvanceBytesRead(result);
-
-  int bytes_read = 0;
-  if (ReadLoop(&bytes_read))
-    NotifyReadComplete(bytes_read);
-}
-
-int BlobURLRequestJob::BytesReadCompleted() {
-  int bytes_read = read_buf_->BytesConsumed();
-  read_buf_ = NULL;
-  return bytes_read;
-}
-
-int BlobURLRequestJob::ComputeBytesToRead() const {
-  int64 current_item_length = item_length_list_[current_item_index_];
-
-  int64 item_remaining = current_item_length - current_item_offset_;
-  int64 buf_remaining = read_buf_->BytesRemaining();
-  int64 max_remaining = std::numeric_limits<int>::max();
-
-  int64 min = std::min(std::min(std::min(item_remaining,
-                                         buf_remaining),
-                                         remaining_bytes_),
-                                         max_remaining);
-
-  return static_cast<int>(min);
-}
-
-bool BlobURLRequestJob::ReadLoop(int* bytes_read) {
-  // Read until we encounter an error or could not get the data immediately.
-  while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) {
-    if (!ReadItem())
-      return false;
-  }
-
-  *bytes_read = BytesReadCompleted();
-  return true;
-}
-
-void BlobURLRequestJob::NotifySuccess() {
   net::HttpStatusCode status_code = net::HTTP_OK;
   if (byte_range_set_ && byte_range_.IsValid())
     status_code = net::HTTP_PARTIAL_CONTENT;
   HeadersCompleted(status_code);
 }
 
+void BlobURLRequestJob::DidReadRawData(int result) {
+  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
+                         blob_handle_ ? blob_handle_->uuid() : "NotFound");
+  if (result < 0) {
+    NotifyFailure(result);
+    return;
+  }
+  // Clear the IO_PENDING status
+  SetStatus(net::URLRequestStatus());
+  NotifyReadComplete(result);
+}
+
 void BlobURLRequestJob::NotifyFailure(int error_code) {
   error_ = true;
 
   // If we already return the headers on success, we can't change the headers
   // now. Instead, we just error out.
   if (response_info_) {
-    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
-                                     error_code));
+    NotifyDone(
+        net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code));
     return;
   }
 
@@ -582,10 +273,14 @@
   status.append("\0\0", 2);
   net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
 
+  set_expected_content_size(0);
+
   if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) {
+    set_expected_content_size(blob_reader_->remaining_bytes());
     std::string content_length_header(net::HttpRequestHeaders::kContentLength);
     content_length_header.append(": ");
-    content_length_header.append(base::Int64ToString(remaining_bytes_));
+    content_length_header.append(
+        base::Int64ToString(blob_reader_->remaining_bytes()));
     headers->AddHeader(content_length_header);
     if (status_code == net::HTTP_PARTIAL_CONTENT) {
       DCHECK(byte_range_set_);
@@ -593,21 +288,22 @@
       std::string content_range_header(net::HttpResponseHeaders::kContentRange);
       content_range_header.append(": bytes ");
       content_range_header.append(base::StringPrintf(
-          "%" PRId64 "-%" PRId64,
-          byte_range_.first_byte_position(), byte_range_.last_byte_position()));
+          "%" PRId64 "-%" PRId64, byte_range_.first_byte_position(),
+          byte_range_.last_byte_position()));
       content_range_header.append("/");
-      content_range_header.append(base::StringPrintf("%" PRId64, total_size_));
+      content_range_header.append(
+          base::StringPrintf("%" PRId64, blob_reader_->total_size()));
       headers->AddHeader(content_range_header);
     }
-    if (!blob_data_->content_type().empty()) {
+    if (!blob_handle_->content_type().empty()) {
       std::string content_type_header(net::HttpRequestHeaders::kContentType);
       content_type_header.append(": ");
-      content_type_header.append(blob_data_->content_type());
+      content_type_header.append(blob_handle_->content_type());
       headers->AddHeader(content_type_header);
     }
-    if (!blob_data_->content_disposition().empty()) {
+    if (!blob_handle_->content_disposition().empty()) {
       std::string content_disposition_header("Content-Disposition: ");
-      content_disposition_header.append(blob_data_->content_disposition());
+      content_disposition_header.append(blob_handle_->content_disposition());
       headers->AddHeader(content_disposition_header);
     }
   }
@@ -615,69 +311,7 @@
   response_info_.reset(new net::HttpResponseInfo());
   response_info_->headers = headers;
 
-  set_expected_content_size(remaining_bytes_);
-
   NotifyHeadersComplete();
 }
 
-FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) {
-  const auto& items = blob_data_->items();
-  DCHECK_LT(index, items.size());
-  const BlobDataItem& item = *items.at(index);
-  if (!IsFileType(item.type()))
-    return nullptr;
-  if (index_to_reader_.find(index) == index_to_reader_.end()) {
-    if (!CreateFileStreamReader(index, 0))
-      return nullptr;
-  }
-  DCHECK(index_to_reader_[index]);
-  return index_to_reader_[index];
-}
-
-bool BlobURLRequestJob::CreateFileStreamReader(size_t index,
-                                               int64 additional_offset) {
-  const auto& items = blob_data_->items();
-  DCHECK_LT(index, items.size());
-  const BlobDataItem& item = *items.at(index);
-  DCHECK(IsFileType(item.type()));
-  DCHECK_EQ(0U, index_to_reader_.count(index));
-
-  FileStreamReader* reader = nullptr;
-  switch (item.type()) {
-    case DataElement::TYPE_FILE:
-      reader = FileStreamReader::CreateForLocalFile(
-          file_task_runner_.get(), item.path(),
-          item.offset() + additional_offset, item.expected_modification_time());
-      DCHECK(reader);
-      index_to_reader_[index] = reader;
-      return true;
-
-    case DataElement::TYPE_FILE_FILESYSTEM:
-      reader = file_system_context_
-                   ->CreateFileStreamReader(
-                         storage::FileSystemURL(file_system_context_->CrackURL(
-                             item.filesystem_url())),
-                         item.offset() + additional_offset,
-                         item.length() == std::numeric_limits<uint64>::max()
-                             ? storage::kMaximumLength
-                             : item.length() - additional_offset,
-                         item.expected_modification_time())
-                   .release();
-      if (reader) {
-        index_to_reader_[index] = reader;
-        return true;
-      }
-
-      // The file stream reader may not be obtainable if the file is on an
-      // isolated file system, which has been unmounted.
-      return false;
-
-    default:
-      break;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
 }  // namespace storage
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h
index 74d07ad..21baa2c 100644
--- a/storage/browser/blob/blob_url_request_job.h
+++ b/storage/browser/blob/blob_url_request_job.h
@@ -13,7 +13,6 @@
 #include "net/http/http_byte_range.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_job.h"
-#include "storage/browser/blob/blob_data_snapshot.h"
 #include "storage/browser/storage_browser_export.h"
 
 namespace base {
@@ -27,6 +26,8 @@
 
 namespace storage {
 
+class BlobDataHandle;
+class BlobReader;
 class FileStreamReader;
 class FileSystemContext;
 
@@ -36,7 +37,7 @@
  public:
   BlobURLRequestJob(net::URLRequest* request,
                     net::NetworkDelegate* network_delegate,
-                    scoped_ptr<BlobDataSnapshot> blob_data,
+                    BlobDataHandle* blob_handle,
                     storage::FileSystemContext* file_system_context,
                     base::SingleThreadTaskRunner* resolving_thread_task_runner);
 
@@ -57,68 +58,20 @@
 
   // For preparing for read: get the size, apply the range and perform seek.
   void DidStart();
-  bool AddItemLength(size_t index, int64 item_length);
-  bool CountSize();
-  void DidCountSize(int error);
-  void DidGetFileItemLength(size_t index, int64 result);
-  void Seek(int64 offset);
+  void DidCalculateSize(int result);
+  void DidReadRawData(int result);
 
-  // For reading the blob.
-  bool ReadLoop(int* bytes_read);
-  bool ReadItem();
-  void AdvanceItem();
-  void AdvanceBytesRead(int result);
-  bool ReadBytesItem(const BlobDataItem& item, int bytes_to_read);
-
-  bool ReadFileItem(FileStreamReader* reader, int bytes_to_read);
-  void DidReadFile(int chunk_number, int result);
-  void DeleteCurrentFileReader();
-
-  bool ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read);
-  void DidReadDiskCacheEntry(int result);
-
-  int ComputeBytesToRead() const;
-  int BytesReadCompleted();
-
-  // These methods convert the result of blob data reading into response headers
-  // and pass it to URLRequestJob's NotifyDone() or NotifyHeadersComplete().
-  void NotifySuccess();
   void NotifyFailure(int);
   void HeadersCompleted(net::HttpStatusCode status_code);
 
-  // Returns a FileStreamReader for a blob item at |index|.
-  // If the item at |index| is not of file this returns NULL.
-  FileStreamReader* GetFileStreamReader(size_t index);
-
-  // Creates a FileStreamReader for the item at |index| with additional_offset.
-  // If failed, then returns false.
-  bool CreateFileStreamReader(size_t index, int64 additional_offset);
-
-  scoped_ptr<BlobDataSnapshot> blob_data_;
-
-  // Variables for controlling read from |blob_data_|.
-  scoped_refptr<storage::FileSystemContext> file_system_context_;
-  scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
-  std::vector<int64> item_length_list_;
-  int64 total_size_;
-  int64 remaining_bytes_;
-  int pending_get_file_info_count_;
-  IndexToReaderMap index_to_reader_;
-  size_t current_item_index_;
-  int64 current_item_offset_;
-
-  // Holds the buffer for read data with the IOBuffer interface.
-  scoped_refptr<net::DrainableIOBuffer> read_buf_;
-
   // Is set when NotifyFailure() is called and reset when DidStart is called.
   bool error_;
 
   bool byte_range_set_;
   net::HttpByteRange byte_range_;
 
-  // Used to create unique id's for tracing.
-  int current_file_chunk_number_;
-
+  scoped_ptr<BlobDataHandle> blob_handle_;
+  scoped_ptr<BlobReader> blob_reader_;
   scoped_ptr<net::HttpResponseInfo> response_info_;
 
   base::WeakPtrFactory<BlobURLRequestJob> weak_factory_;
diff --git a/storage/browser/blob/blob_url_request_job_factory.cc b/storage/browser/blob/blob_url_request_job_factory.cc
index feb5df0..5961697 100644
--- a/storage/browser/blob/blob_url_request_job_factory.cc
+++ b/storage/browser/blob/blob_url_request_job_factory.cc
@@ -19,10 +19,6 @@
 
 int kUserDataKey;  // The value is not important, the addr is a key.
 
-BlobDataHandle* GetRequestedBlobDataHandle(net::URLRequest* request) {
-  return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey));
-}
-
 }  // namespace
 
 // static
@@ -44,6 +40,12 @@
   request->SetUserData(&kUserDataKey, blob_data_handle.release());
 }
 
+// static
+BlobDataHandle* BlobProtocolHandler::GetRequestBlobDataHandle(
+    net::URLRequest* request) {
+  return static_cast<BlobDataHandle*>(request->GetUserData(&kUserDataKey));
+}
+
 BlobProtocolHandler::BlobProtocolHandler(
     BlobStorageContext* context,
     storage::FileSystemContext* file_system_context,
@@ -59,18 +61,16 @@
 
 net::URLRequestJob* BlobProtocolHandler::MaybeCreateJob(
     net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
-  return new storage::BlobURLRequestJob(request,
-                                        network_delegate,
-                                        LookupBlobData(request),
-                                        file_system_context_.get(),
-                                        file_task_runner_.get());
+  return new storage::BlobURLRequestJob(
+      request, network_delegate, LookupBlobHandle(request),
+      file_system_context_.get(), file_task_runner_.get());
 }
 
-scoped_ptr<BlobDataSnapshot> BlobProtocolHandler::LookupBlobData(
+BlobDataHandle* BlobProtocolHandler::LookupBlobHandle(
     net::URLRequest* request) const {
-  BlobDataHandle* blob_data_handle = GetRequestedBlobDataHandle(request);
+  BlobDataHandle* blob_data_handle = GetRequestBlobDataHandle(request);
   if (blob_data_handle)
-    return blob_data_handle->CreateSnapshot().Pass();
+    return blob_data_handle;
   if (!context_.get())
     return NULL;
 
@@ -83,12 +83,11 @@
     return NULL;
   std::string uuid = request->url().spec().substr(kPrefix.length());
   scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid);
-  scoped_ptr<BlobDataSnapshot> snapshot;
+  BlobDataHandle* handle_ptr = handle.get();
   if (handle) {
-    snapshot = handle->CreateSnapshot().Pass();
     SetRequestedBlobDataHandle(request, handle.Pass());
   }
-  return snapshot.Pass();
+  return handle_ptr;
 }
 
 }  // namespace storage
diff --git a/storage/browser/blob/blob_url_request_job_factory.h b/storage/browser/blob/blob_url_request_job_factory.h
index 7f7a5506..dcb2fd6 100644
--- a/storage/browser/blob/blob_url_request_job_factory.h
+++ b/storage/browser/blob/blob_url_request_job_factory.h
@@ -26,7 +26,6 @@
 
 namespace storage {
 
-class BlobDataSnapshot;
 class BlobDataHandle;
 class BlobStorageContext;
 
@@ -45,6 +44,9 @@
       net::URLRequest* request,
       scoped_ptr<BlobDataHandle> blob_data_handle);
 
+  // This gets the handle on the request if it exists.
+  static BlobDataHandle* GetRequestBlobDataHandle(net::URLRequest* request);
+
   BlobProtocolHandler(
       BlobStorageContext* context,
       storage::FileSystemContext* file_system_context,
@@ -56,7 +58,7 @@
       net::NetworkDelegate* network_delegate) const override;
 
  private:
-  scoped_ptr<BlobDataSnapshot> LookupBlobData(net::URLRequest* request) const;
+  BlobDataHandle* LookupBlobHandle(net::URLRequest* request) const;
 
   base::WeakPtr<BlobStorageContext> context_;
   const scoped_refptr<storage::FileSystemContext> file_system_context_;
diff --git a/storage/browser/blob/upload_blob_element_reader.cc b/storage/browser/blob/upload_blob_element_reader.cc
new file mode 100644
index 0000000..dd0058f3
--- /dev/null
+++ b/storage/browser/blob/upload_blob_element_reader.cc
@@ -0,0 +1,67 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "storage/browser/blob/upload_blob_element_reader.h"
+
+#include "net/base/net_errors.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
+
+namespace storage {
+
+UploadBlobElementReader::UploadBlobElementReader(
+    scoped_ptr<storage::BlobReader> reader,
+    scoped_ptr<BlobDataHandle> handle)
+    : reader_(reader.Pass()), handle_(handle.Pass()) {}
+
+UploadBlobElementReader::~UploadBlobElementReader() {}
+
+int UploadBlobElementReader::Init(const net::CompletionCallback& callback) {
+  BlobReader::Status status = reader_->CalculateSize(callback);
+  switch (status) {
+    case BlobReader::Status::NET_ERROR:
+      return reader_->net_error();
+    case BlobReader::Status::IO_PENDING:
+      return net::ERR_IO_PENDING;
+    case BlobReader::Status::DONE:
+      return net::OK;
+  }
+  NOTREACHED();
+  return net::ERR_FAILED;
+}
+
+uint64_t UploadBlobElementReader::GetContentLength() const {
+  return reader_->total_size();
+}
+
+uint64_t UploadBlobElementReader::BytesRemaining() const {
+  return reader_->remaining_bytes();
+}
+
+bool UploadBlobElementReader::IsInMemory() const {
+  return reader_->IsInMemory();
+}
+
+int UploadBlobElementReader::Read(net::IOBuffer* buf,
+                                  int buf_length,
+                                  const net::CompletionCallback& callback) {
+  int length = 0;
+  BlobReader::Status status = reader_->Read(buf, buf_length, &length, callback);
+  switch (status) {
+    case BlobReader::Status::NET_ERROR:
+      return reader_->net_error();
+    case BlobReader::Status::IO_PENDING:
+      return net::ERR_IO_PENDING;
+    case BlobReader::Status::DONE:
+      return length;
+  }
+  NOTREACHED();
+  return net::ERR_FAILED;
+}
+
+const std::string& UploadBlobElementReader::uuid() const {
+  return handle_->uuid();
+}
+
+}  // namespace storage
diff --git a/storage/browser/blob/upload_blob_element_reader.h b/storage/browser/blob/upload_blob_element_reader.h
new file mode 100644
index 0000000..72b7244
--- /dev/null
+++ b/storage/browser/blob/upload_blob_element_reader.h
@@ -0,0 +1,54 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
+#define STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/base/upload_element_reader.h"
+#include "storage/browser/storage_browser_export.h"
+
+namespace net {
+class IOBuffer;
+}
+
+namespace storage {
+class BlobDataHandle;
+class BlobReader;
+
+// This class is a wrapper around the BlobReader to make it conform
+// to the net::UploadElementReader interface, and it also holds around the
+// handle to the blob so it stays in memory while we read it.
+class STORAGE_EXPORT UploadBlobElementReader
+    : NON_EXPORTED_BASE(public net::UploadElementReader) {
+ public:
+  UploadBlobElementReader(scoped_ptr<BlobReader> reader,
+                          scoped_ptr<BlobDataHandle> handle);
+  ~UploadBlobElementReader() override;
+
+  int Init(const net::CompletionCallback& callback) override;
+
+  uint64_t GetContentLength() const override;
+
+  uint64_t BytesRemaining() const override;
+
+  bool IsInMemory() const override;
+
+  int Read(net::IOBuffer* buf,
+           int buf_length,
+           const net::CompletionCallback& callback) override;
+
+  const std::string& uuid() const;
+
+ private:
+  scoped_ptr<BlobReader> reader_;
+  scoped_ptr<BlobDataHandle> handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(UploadBlobElementReader);
+};
+
+}  // namespace storage
+#endif  // STORAGE_BROWSER_BLOB_UPLOAD_BLOB_ELEMENT_READER_H_
diff --git a/storage/storage_browser.gyp b/storage/storage_browser.gyp
index 6a8b749..de1d166 100644
--- a/storage/storage_browser.gyp
+++ b/storage/storage_browser.gyp
@@ -33,6 +33,8 @@
         'browser/blob/blob_data_item.h',
         'browser/blob/blob_data_snapshot.cc',
         'browser/blob/blob_data_snapshot.h',
+        'browser/blob/blob_reader.cc',
+        'browser/blob/blob_reader.h',
         'browser/blob/blob_storage_context.cc',
         'browser/blob/blob_storage_context.h',
         'browser/blob/blob_url_request_job.cc',
@@ -47,6 +49,9 @@
         'browser/blob/shareable_blob_data_item.h',
         'browser/blob/shareable_file_reference.cc',
         'browser/blob/shareable_file_reference.h',
+        'browser/blob/upload_blob_element_reader.h',
+        'browser/blob/upload_blob_element_reader.cc',
+        'browser/blob/view_blob_internals_job.h',
         'browser/blob/view_blob_internals_job.cc',
         'browser/blob/view_blob_internals_job.h',
         'browser/database/database_quota_client.cc',
diff --git a/sync/android/java/src/org/chromium/sync/signin/SystemAccountManagerDelegate.java b/sync/android/java/src/org/chromium/sync/signin/SystemAccountManagerDelegate.java
index 33b233c..07aabac 100644
--- a/sync/android/java/src/org/chromium/sync/signin/SystemAccountManagerDelegate.java
+++ b/sync/android/java/src/org/chromium/sync/signin/SystemAccountManagerDelegate.java
@@ -14,6 +14,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.StrictMode;
 import android.os.SystemClock;
 
 import org.chromium.base.ThreadUtils;
@@ -58,7 +59,14 @@
 
     @Override
     public void invalidateAuthToken(String accountType, String authToken) {
-        mAccountManager.invalidateAuthToken(accountType, authToken);
+        // Temporarily allowing disk access while fixing. TODO: http://crbug.com/535320
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+        StrictMode.allowThreadDiskReads();
+        try {
+            mAccountManager.invalidateAuthToken(accountType, authToken);
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
     }
 
     @Override
diff --git a/sync/test/local_sync_test_server.cc b/sync/test/local_sync_test_server.cc
index e8a10966..791fe09 100644
--- a/sync/test/local_sync_test_server.cc
+++ b/sync/test/local_sync_test_server.cc
@@ -36,7 +36,7 @@
   if (!LocalTestServer::AddCommandLineArguments(command_line))
     return false;
   if (xmpp_port_ != 0) {
-    std::string xmpp_port_str = base::IntToString(xmpp_port_);
+    std::string xmpp_port_str = base::UintToString(xmpp_port_);
     command_line->AppendArg("--xmpp-port=" + xmpp_port_str);
   }
   return true;
diff --git a/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java b/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java
index 78c571a4..c209ac7 100644
--- a/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java
+++ b/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java
@@ -148,13 +148,21 @@
             mTestClasses = testClasses;
         }
 
-        private void sendTestStatus(int status, String testClass, String testMethod) {
+        private void sendTestStatus(
+                int status, String testClass, String testMethod, String stackTrace) {
             Bundle statusBundle = new Bundle();
             statusBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_CLASS, testClass);
             statusBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_TEST, testMethod);
+            if (stackTrace != null) {
+                statusBundle.putString(InstrumentationTestRunner.REPORT_KEY_STACK, stackTrace);
+            }
             sendStatus(status, statusBundle);
         }
 
+        private void sendTestStatus(int status, String testClass, String testMethod) {
+            sendTestStatus(status, testClass, testMethod, null);
+        }
+
         /** Run the tests. */
         @Override
         public void run() {
@@ -188,9 +196,9 @@
                 });
                 r.registerCallback(new TestStatusReceiver.FailCallback() {
                     @Override
-                    public void testFailed(String testClass, String testMethod) {
+                    public void testFailed(String testClass, String testMethod, String stackTrace) {
                         sendTestStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_ERROR,
-                                testClass, testMethod);
+                                testClass, testMethod, stackTrace);
                         synchronized (statusLock) {
                             finished.put(testClass + "#" + testMethod,
                                     ResultsBundleGenerator.TestResult.FAILED);
diff --git a/testing/android/native_test/java/AndroidManifest.xml b/testing/android/native_test/java/AndroidManifest.xml
index a50ffcd..6de21b1 100644
--- a/testing/android/native_test/java/AndroidManifest.xml
+++ b/testing/android/native_test/java/AndroidManifest.xml
@@ -11,7 +11,6 @@
       android:versionName="1.0">
 
     <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.BLUETOOTH"/>
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
     <uses-permission android:name="android.permission.CAMERA" />
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java
index 62754181..13a8af8 100644
--- a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java
+++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java
@@ -21,6 +21,7 @@
 
     private boolean mFailed;
     private final TestStatusReporter mReporter;
+    private Throwable mThrowable;
 
     public TestStatusListener(Context context) {
         mReporter = new TestStatusReporter(context);
@@ -38,6 +39,7 @@
     public void addError(Test test, Throwable t) {
         Log.e(TAG, "Error while running " + test.toString(), t);
         mFailed = true;
+        mThrowable = t;
     }
 
     /** Called when a test has failed.
@@ -48,6 +50,7 @@
     public void addFailure(Test test, AssertionFailedError e) {
         Log.e(TAG, "Failure while running " + test.toString(), e);
         mFailed = true;
+        mThrowable = e;
     }
 
     /** Called when a test has started.
@@ -68,11 +71,14 @@
     public void endTest(Test test) {
         TestCase testCase = (TestCase) test;
         if (mFailed) {
-            mReporter.testFailed(testCase.getClass().getName(), testCase.getName());
+            String stackTrace = null;
+            if (mThrowable != null) {
+                stackTrace = Log.getStackTraceString(mThrowable);
+            }
+            mReporter.testFailed(testCase.getClass().getName(), testCase.getName(), stackTrace);
         } else {
             mReporter.testPassed(testCase.getClass().getName(), testCase.getName());
         }
         mReporter.stopHeartbeat();
     }
-
 }
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java
index 1f410a9..df61396 100644
--- a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java
+++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java
@@ -48,7 +48,7 @@
 
     /** A callback used when a test has failed. */
     public interface FailCallback {
-        void testFailed(String testClass, String testMethod);
+        void testFailed(String testClass, String testMethod, String stackTrace);
     }
 
     /** A callback used when a heartbeat is received. */
@@ -112,6 +112,7 @@
         int pid = intent.getIntExtra(TestStatusReporter.EXTRA_PID, 0);
         String testClass = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_CLASS);
         String testMethod = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_METHOD);
+        String stackTrace = intent.getStringExtra(TestStatusReporter.EXTRA_STACK_TRACE);
 
         switch (intent.getAction()) {
             case TestStatusReporter.ACTION_TEST_STARTED:
@@ -126,7 +127,7 @@
                 break;
             case TestStatusReporter.ACTION_TEST_FAILED:
                 for (FailCallback c : mFailCallbacks) {
-                    c.testFailed(testClass, testMethod);
+                    c.testFailed(testClass, testMethod, stackTrace);
                 }
                 break;
             case TestStatusReporter.ACTION_HEARTBEAT:
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java
index 85355f9..1d887008 100644
--- a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java
+++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java
@@ -36,6 +36,8 @@
             "org.chromium.test.reporter.TestStatusReporter.TEST_CLASS";
     public static final String EXTRA_TEST_METHOD =
             "org.chromium.test.reporter.TestStatusReporter.TEST_METHOD";
+    public static final String EXTRA_STACK_TRACE =
+            "org.chromium.test.reporter.TestStatusReporter.STACK_TRACE";
 
     public static final int HEARTBEAT_INTERVAL_MS = 5000;
 
@@ -70,18 +72,26 @@
         sendTestBroadcast(ACTION_TEST_PASSED, testClass, testMethod);
     }
 
-    public void testFailed(String testClass, String testMethod) {
-        sendTestBroadcast(ACTION_TEST_FAILED, testClass, testMethod);
+    public void testFailed(String testClass, String testMethod, String stackTrace) {
+        sendTestBroadcast(ACTION_TEST_FAILED, testClass, testMethod, stackTrace);
     }
 
-    private void sendTestBroadcast(String action, String testClass, String testMethod) {
+    private void sendTestBroadcast(
+            String action, String testClass, String testMethod, String stackTrace) {
         Intent i = new Intent(action);
         i.setType(DATA_TYPE_RESULT);
         i.putExtra(EXTRA_TEST_CLASS, testClass);
         i.putExtra(EXTRA_TEST_METHOD, testMethod);
+        if (stackTrace != null) {
+            i.putExtra(EXTRA_STACK_TRACE, stackTrace);
+        }
         mContext.sendBroadcast(i);
     }
 
+    private void sendTestBroadcast(String action, String testClass, String testMethod) {
+        sendTestBroadcast(action, testClass, testMethod, null);
+    }
+
     public void testRunStarted(int pid) {
         sendTestRunBroadcast(ACTION_TEST_RUN_STARTED, pid);
     }
@@ -100,5 +110,4 @@
     public void stopHeartbeat() {
         mKeepBeating.set(false);
     }
-
 }
diff --git a/testing/buildbot/chromium.webrtc.fyi.json b/testing/buildbot/chromium.webrtc.fyi.json
index c517634..9060c0c0 100644
--- a/testing/buildbot/chromium.webrtc.fyi.json
+++ b/testing/buildbot/chromium.webrtc.fyi.json
@@ -9,6 +9,120 @@
       "chrome_public_apk"
     ]
   },
+  "Android Tests (dbg) (J Nexus4)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Android Tests (dbg) (K Nexus5)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Android Tests (dbg) (L Nexus5)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Android Tests (dbg) (L Nexus6)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Android Tests (dbg) (L Nexus7.2)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Android Tests (dbg) (L Nexus9)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      }
+    ]
+  },
+  "Linux": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
   "Linux GN": {
     "additional_compile_targets": [
       "accessibility_unittests",
@@ -175,6 +289,42 @@
       "url_unittests"
     ]
   },
+  "Mac Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
   "Win GN": {
     "additional_compile_targets": [
       "accessibility_unittests",
@@ -282,5 +432,113 @@
       "views_unittests",
       "wm_unittests"
     ]
+  },
+  "Win10 Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Win7 Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "WinXP Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
   }
 }
diff --git a/testing/buildbot/chromium.webrtc.json b/testing/buildbot/chromium.webrtc.json
new file mode 100644
index 0000000..ebf9faa
--- /dev/null
+++ b/testing/buildbot/chromium.webrtc.json
@@ -0,0 +1,218 @@
+{
+  "Linux Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Mac Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Win10 Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Win7 Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "Win8 Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  },
+  "WinXP Tester": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gtest_filter=WebRtc*:Webrtc*:TabCapture*:*MediaStream*",
+          "--run-manual",
+          "--ui-test-action-max-timeout=350000",
+          "--test-launcher-jobs=1",
+          "--test-launcher-bot-mode",
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "browser_tests"
+      },
+      {
+        "args": [
+          "--gtest_filter=WebRtc*",
+          "--run-manual",
+          "--test-launcher-print-test-stdio=always",
+          "--test-launcher-bot-mode"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      }
+    ]
+  }
+}
diff --git a/testing/variations/fieldtrial_testing_config_android.json b/testing/variations/fieldtrial_testing_config_android.json
index 41a123a..308a285 100644
--- a/testing/variations/fieldtrial_testing_config_android.json
+++ b/testing/variations/fieldtrial_testing_config_android.json
@@ -4,6 +4,11 @@
             "group_name": "Disabled"
         }
     ],
+    "AutofillClassifier": [
+        {
+            "group_name": "Enabled"
+        }
+    ],
     "AutofillFieldMetadata": [
         {
             "group_name": "Enabled"
@@ -63,11 +68,6 @@
             "group_name": "Enabled"
         }
     ],
-    "DataReductionProxyUseDataSaverOnVPN": [
-        {
-            "group_name": "Enabled"
-        }
-    ],
     "DataReductionProxyUseQuic": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_chromeos.json b/testing/variations/fieldtrial_testing_config_chromeos.json
index 5e974a7b..5024199 100644
--- a/testing/variations/fieldtrial_testing_config_chromeos.json
+++ b/testing/variations/fieldtrial_testing_config_chromeos.json
@@ -1,4 +1,9 @@
 {
+    "AutofillClassifier": [
+        {
+            "group_name": "Enabled"
+        }
+    ],
     "AutofillFieldMetadata": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_linux.json b/testing/variations/fieldtrial_testing_config_linux.json
index 36d33c1c..a17455c 100644
--- a/testing/variations/fieldtrial_testing_config_linux.json
+++ b/testing/variations/fieldtrial_testing_config_linux.json
@@ -1,4 +1,9 @@
 {
+    "AutofillClassifier": [
+        {
+            "group_name": "Enabled"
+        }
+    ],
     "AutofillFieldMetadata": [
         {
             "group_name": "Enabled"
@@ -14,11 +19,6 @@
             "group_name": "Enabled"
         }
     ],
-    "DataReductionProxyUseDataSaverOnVPN": [
-        {
-            "group_name": "Enabled"
-        }
-    ],
     "EnableGoogleCachedCopyTextExperiment": [
         {
             "group_name": "Button"
diff --git a/testing/variations/fieldtrial_testing_config_mac.json b/testing/variations/fieldtrial_testing_config_mac.json
index dec8562a..c37390b 100644
--- a/testing/variations/fieldtrial_testing_config_mac.json
+++ b/testing/variations/fieldtrial_testing_config_mac.json
@@ -1,4 +1,9 @@
 {
+    "AutofillClassifier": [
+        {
+            "group_name": "Enabled"
+        }
+    ],
     "AutofillFieldMetadata": [
         {
             "group_name": "Enabled"
diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json
index cd0d1c1..0a4c712 100644
--- a/testing/variations/fieldtrial_testing_config_win.json
+++ b/testing/variations/fieldtrial_testing_config_win.json
@@ -1,4 +1,9 @@
 {
+    "AutofillClassifier": [
+        {
+            "group_name": "Enabled"
+        }
+    ],
     "AutofillFieldMetadata": [
         {
             "group_name": "Enabled"
diff --git a/third_party/WebKit/LayoutTests/MSANExpectations b/third_party/WebKit/LayoutTests/MSANExpectations
index b89f68e2..cf3b0b6 100644
--- a/third_party/WebKit/LayoutTests/MSANExpectations
+++ b/third_party/WebKit/LayoutTests/MSANExpectations
@@ -60,17 +60,6 @@
 crbug.com/522376 [ Linux ] virtual/gpu/fast/canvas/canvas-incremental-repaint.html [ Crash ]
 crbug.com/522376 [ Linux ] virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow.html [ Crash ]
 
-# These tests may require more time to execute
-crbug.com/536293 [ Linux ] virtual/gpu/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html [ Timeout ]
-crbug.com/536293 [ Linux ] virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html [ Timeout ]
-crbug.com/536293 [ Linux ] virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-webp.html [ Timeout ]
-crbug.com/536293 [ Linux ] virtual/gpu/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-webp.html [ Timeout ]
-crbug.com/536293 [ Linux ] fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html [ Timeout ]
-crbug.com/536293 [ Linux ] fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html [ Timeout ]
-crbug.com/536293 [ Linux ] virtual/display_list_2d_canvas/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html [ Timeout ]
-crbug.com/536293 [ Linux ] virtual/gpu/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html [ Timeout ]
-crbug.com/536293 [ Linux ] fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-webp.html [ Timeout ]
-
 # Flaky under MSAN (hang forever)
 crbug.com/456525 [ Linux ] inspector/sources/debugger [ Skip ]
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 70dc3d4e..d805932 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -40,6 +40,8 @@
 
 crbug.com/536138 virtual/spv2/paint/invalidation/repaint-subsequence-on-ancestor-clip-change.html [ ImageOnlyFailure ]
 
+crbug.com/537172 [ SnowLeopard XP ] virtual/spv2/paint/invalidation/spv2/background-image-paint-invalidation.html [ ImageOnlyFailure ]
+
 crbug.com/504613 crbug.com/524248 paint/images/image-backgrounds-not-antialiased.html [ Skip ]
 crbug.com/504613 crbug.com/524248 virtual/spv2/paint/images/image-backgrounds-not-antialiased.html [ Skip ]
 crbug.com/502531 fast/borders/border-antialiasing.html [ ImageOnlyFailure ]
@@ -82,9 +84,6 @@
 
 crbug.com/535141 fast/text/international/combining-marks-position.html [ NeedsRebaseline ]
 
-# Times out on the windows trybot.
-crbug.com/481269 [ Win ] fast/dom/gc-treescope.html [ Pass Timeout ]
-
 crbug.com/280342 [ Linux Win ] http/tests/media/progress-events-generated-correctly.html [ Failure ]
 
 crbug.com/520739 [ Mac ] http/tests/websocket/close-code-and-reason.html [ Failure Pass Timeout ]
@@ -119,8 +118,6 @@
 crbug.com/520169 [ Win ] fast/dom/Geolocation/timestamp.html [ Failure Pass ]
 crbug.com/520170 [ Win ] fast/dom/timer-throttling-hidden-page.html [ Failure Pass ]
 crbug.com/520172 [ Win ] fast/dom/webtiming.html [ Failure Pass ]
-crbug.com/520173 fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Failure Pass ]
-crbug.com/520173 virtual/trustedeventsdefaultaction/fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Failure Pass ]
 crbug.com/520174 fast/events/message-port-start-and-close-different-microtask.html [ Failure Pass ]
 crbug.com/520177 [ Android ] fast/images/style-access-during-imageChanged-crash.html [ Crash Pass ]
 crbug.com/520178 fast/loader/form-submit-aborts-parsing.html [ Failure Pass ]
@@ -183,6 +180,11 @@
 crbug.com/526594 [ Win10 ] plugins/webview-plugin-lifecycle.html [ ImageOnlyFailure ]
 crbug.com/518999 [ Win7 Debug ] plugins/webview-plugin-lifecycle.html [ ImageOnlyFailure Pass ]
 
+crbug.com/530331 fast/text/selection-painting-hidpi.html [ NeedsRebaseline ]
+crbug.com/530331 virtual/spv2/paint/selection/text-selection-newline-br.html [ NeedsRebaseline ]
+crbug.com/530331 paint/selection/text-selection-newline-br.html [ NeedsRebaseline ]
+crbug.com/530331 editing/selection/transformed-selection-rects.html [ NeedsRebaseline ]
+
 crbug.com/519001 storage/indexeddb/pending-version-change-stuck-works-with-terminate.html [ Pass Timeout ]
 crbug.com/519002 storage/indexeddb/pending-version-change-stuck.html [ Pass Timeout ]
 crbug.com/519003 [ Mac ] svg/batik/text/xmlSpace.svg [ Failure Pass ]
@@ -965,6 +967,16 @@
 
 crbug.com/506312 imported/csswg-test/css-pseudo-4/first-letter-001.html [ ImageOnlyFailure ]
 
+crbug.com/536234 css3/flexbox/flexbox-baseline-margins.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/forms/basic-textareas-quirks.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/forms/basic-textareas.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/forms/select/menulist-appearance-basic.html [ NeedsRebaseline ]
+crbug.com/536234 fast/forms/textarea-scrolled-focus-ring.html [ NeedsRebaseline ]
+crbug.com/536234 fast/layers/scroll-rect-to-visible.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/overflow/overflow-x-y.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/parser/open-comment-in-textarea.html [ NeedsRebaseline ]
+crbug.com/536234 [ Android Linux Win SnowLeopard Lion MountainLion Retina Mavericks ] fast/replaced/width100percent-textarea.html [ NeedsRebaseline ]
+
 crbug.com/524646 [ Yosemite ] css3/selectors3/html/css3-modsel-161.html [ NeedsRebaseline ]
 crbug.com/524646 [ Yosemite ] css3/selectors3/html/css3-modsel-19b.html [ NeedsRebaseline ]
 crbug.com/524646 [ Yosemite ] css3/selectors3/html/css3-modsel-23.html [ NeedsRebaseline ]
@@ -1533,23 +1545,23 @@
 crbug.com/521730 [ Win10 ] plugins/tabindex.html [ Crash ]
 crbug.com/521730 [ Win10 ] plugins/windowless_plugin_paint_test.html [ Crash ]
 crbug.com/521730 [ Win10 ] printing/ellipsis-printing-style.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/iframe-print.html [ Crash ]
+crbug.com/521730 [ Win10 ] printing/iframe-print.html [ Crash Failure ]
 crbug.com/521730 [ Win10 ] printing/print-no-background.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/quirks-percentage-height-body.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/quirks-percentage-height.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/simultaneous-position-float-change.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/standards-percentage-heights.html [ Crash ]
-crbug.com/521730 [ Win10 ] printing/subframes-percentage-height.html [ Crash ]
+crbug.com/521730 [ Win10 ] printing/quirks-percentage-height-body.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] printing/quirks-percentage-height.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] printing/simultaneous-position-float-change.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] printing/standards-percentage-heights.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] printing/subframes-percentage-height.html [ Crash Failure ]
 crbug.com/521730 [ Win10 ] virtual/threaded/printing/ellipsis-printing-style.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/iframe-print.html [ Crash ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/iframe-print.html [ Crash Failure ]
 crbug.com/521730 [ Win10 ] virtual/threaded/printing/print-no-background.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height-body.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/simultaneous-position-float-change.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/standards-percentage-heights.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/subframes-percentage-height.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing-preservedrawingbuffer.html [ Crash ]
-crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing.html [ Crash ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height-body.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/quirks-percentage-height.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/simultaneous-position-float-change.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/standards-percentage-heights.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/subframes-percentage-height.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing-preservedrawingbuffer.html [ Crash Failure ]
+crbug.com/521730 [ Win10 ] virtual/threaded/printing/webgl-repeated-printing.html [ Crash Failure ]
 #crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-bad-argument.html [ Timeout ]
 crbug.com/521730 [ Win10 ] imported/web-platform-tests/screen-orientation/lock-sandboxed-iframe.html [ Timeout ]
 crbug.com/521730 [ Win10 ] screen_orientation/lockOrientation-bad-argument.html [ Timeout ]
@@ -1803,13 +1815,33 @@
 crbug.com/521764 [ Win10 ] inspector/tracing/timeline-timer-fired-from-eval-call-site.html [ Failure Pass ]
 crbug.com/521764 [ Win10 ] plugins/netscape-plugin-map-data-to-src.html [ Failure Pass ]
 crbug.com/521764 [ Win10 ] plugins/update-widgets-crash.html [ Pass Timeout ]
-crbug.com/521764 [ Win10 ] printing/webgl-repeated-printing.html [ Crash Timeout ]
+crbug.com/521764 [ Win10 ] printing/webgl-repeated-printing.html [ Crash Timeout Failure ]
 crbug.com/521764 [ Win10 ] svg/custom/textPath-remove-path-pattern.svg [ ImageOnlyFailure Pass Timeout ]
 crbug.com/521764 [ Win10 ] accessibility/inline-text-changes.html [ Failure Pass ]
 crbug.com/521764 [ Win10 ] fast/loader/javascript-detached-frame-no-crash.html [ Pass Timeout ]
 crbug.com/521764 [ Win10 ] virtual/display_list_2d_canvas/fast/canvas/canvas-resize-reset.html [ Pass Timeout ]
 crbug.com/521764 [ Win10 ] transitions/equivalent-background-image-no-transition.html [ Pass Timeout ]
 
+crbug.com/535051 [ Linux Win ] compositing/force-compositing-mode/overflow-iframe-enter-compositing.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/force-compositing-mode/overflow-iframe-layer.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/become-overlapped-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/composited-parent-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/connect-compositing-iframe-delayed.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/connect-compositing-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/connect-compositing-iframe2.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/connect-compositing-iframe3.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/enter-compositing-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/iframe-resize.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/iframe-size-from-zero.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/invisible-nested-iframe-show.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/overlapped-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/resizer.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/iframes/scrolling-iframe.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/rtl/rtl-iframe-absolute-overflow-scrolled.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/rtl/rtl-iframe-absolute-overflow.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html [ NeedsRebaseline ]
+crbug.com/535051 [ Linux Win ] compositing/rtl/rtl-iframe-fixed-overflow.html [ NeedsRebaseline ]
+
 crbug.com/474759 svg/text/foreignObject-text-clipping-bug.xml [ NeedsRebaseline ]
 crbug.com/474759 paint/invalidation/invalidate-after-composited-scroll.html [ NeedsRebaseline ]
 crbug.com/474759 paint/selection/selection-within-composited-scroller.html [ NeedsRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 1a75db2c..aa3c51d 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -339,8 +339,6 @@
 imported/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml [ Skip ]
 imported/web-platform-tests/html/infrastructure/urls/resolving-urls [ Skip ]
 imported/web-platform-tests/html/infrastructure/urls/terminology-0/multiple-base.sub.html [ Skip ]
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html [ Skip ]
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html [ Skip ]
 imported/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors [ Skip ]
 imported/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html [ Skip ]
 
@@ -349,12 +347,12 @@
 imported/web-platform-tests/html/browsers/history/the-location-interface/location_hostname.html [ Skip ]
 
 # crbug.com/535615: Pathnames are too long for Windows.
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
-imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html [ Skip ]
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html [ Skip ]
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html [ Skip ]
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html [ Skip ]
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html [ Skip ]
+imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html [ Skip ]
 
 # It contains only manual SVG tests.
 imported/web-platform-tests/html/editing/dnd/svg [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/notification-listeners-expected.txt b/third_party/WebKit/LayoutTests/accessibility/notification-listeners-expected.txt
index d5030bb..efe1f94 100644
--- a/third_party/WebKit/LayoutTests/accessibility/notification-listeners-expected.txt
+++ b/third_party/WebKit/LayoutTests/accessibility/notification-listeners-expected.txt
@@ -5,11 +5,12 @@
 
 
 Slider
+SELECT Blur
 SELECT InvalidStatusChanged
 GLOBAL InvalidStatusChanged on element with role AXRole: AXPopUpButton
 SLIDER ValueChanged
 GLOBAL ValueChanged on element with role AXRole: AXSlider
-PASS selectNotificationCount is 1
+PASS selectNotificationCount is 2
 PASS sliderNotificationCount is 1
 PASS globalNotificationCount is 2
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/accessibility/notification-listeners.html b/third_party/WebKit/LayoutTests/accessibility/notification-listeners.html
index c3fc5d1..0a16441 100644
--- a/third_party/WebKit/LayoutTests/accessibility/notification-listeners.html
+++ b/third_party/WebKit/LayoutTests/accessibility/notification-listeners.html
@@ -55,7 +55,7 @@
     document.getElementById("slider").setAttribute("aria-valuenow", "6");
 
     window.setTimeout(function() {
-        shouldBe("selectNotificationCount", "1");
+        shouldBe("selectNotificationCount", "2");
         shouldBe("sliderNotificationCount", "1");
         shouldBe("globalNotificationCount", "2");
 
diff --git a/third_party/WebKit/LayoutTests/css3/calc/calc-numbers-expected.txt b/third_party/WebKit/LayoutTests/css3/calc/calc-numbers-expected.txt
index 77cd938..4dbe2e99 100644
--- a/third_party/WebKit/LayoutTests/css3/calc/calc-numbers-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/calc/calc-numbers-expected.txt
@@ -4,6 +4,7 @@
 PASS getComputedValue(".float-invalid", "tabSize") is "12345"
 PASS Number(getComputedValue(".px-invalid", "opacity")) is within 0.0001 of 0.9
 PASS getComputedValue(".num-length-invalid", "tabSize") is "12345"
+PASS getComputedValue(".px-valid", "tabSize") is "10px"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/calc/calc-numbers.html b/third_party/WebKit/LayoutTests/css3/calc/calc-numbers.html
index 1bb61ed0..22b945b3 100644
--- a/third_party/WebKit/LayoutTests/css3/calc/calc-numbers.html
+++ b/third_party/WebKit/LayoutTests/css3/calc/calc-numbers.html
@@ -21,6 +21,13 @@
 .num-length-invalid {
     tab-size: 12345;
     tab-size: calc(1 + 1px);
+    tab-size: calc(1 + 100%);
+    tab-size: calc(100%);
+    tab-size: calc(10px) bla;
+    tab-size: calc(bla) 10px;
+}
+.px-valid {
+    tab-size: calc(10px);
 }
 </style>
 <div class="default int"></div>
@@ -29,6 +36,7 @@
 <div class="default float-invalid"></div>
 <div class="default px-invalid"></div>
 <div class="default num-length-invalid"></div>
+<div class="default px-valid"></div>
 <script src="../../resources/js-test.js"></script>
 <script>
 if (window.testRunner)
@@ -44,4 +52,5 @@
 shouldBe('getComputedValue(".float-invalid", "tabSize")', '"12345"');
 shouldBeCloseTo('Number(getComputedValue(".px-invalid", "opacity"))', 0.9, .0001);
 shouldBe('getComputedValue(".num-length-invalid", "tabSize")', '"12345"');
+shouldBe('getComputedValue(".px-valid", "tabSize")', '"10px"');
 </script>
diff --git a/third_party/WebKit/LayoutTests/css3/calc/letter-spacing-expected.txt b/third_party/WebKit/LayoutTests/css3/calc/letter-spacing-expected.txt
new file mode 100644
index 0000000..5245dc7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/calc/letter-spacing-expected.txt
@@ -0,0 +1,6 @@
+PASS getComputedValue(".invalid", "letterSpacing") is "20px"
+PASS getComputedValue(".valid", "letterSpacing") is "10px"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/css3/calc/letter-spacing.html b/third_party/WebKit/LayoutTests/css3/calc/letter-spacing.html
new file mode 100644
index 0000000..ccbd996
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/calc/letter-spacing.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<style>
+.invalid {
+    letter-spacing: 20px;
+    letter-spacing: calc(1 + 1px);
+    letter-spacing: calc(1 + 100%);
+    letter-spacing: calc(100%);
+    letter-spacing: calc(10px) bla;
+    letter-spacing: calc(bla) 10px;
+}
+.valid {
+    letter-spacing: calc(10px);
+}
+</style>
+<div class="invalid"></div>
+<div class="valid"></div>
+<script src="../../resources/js-test.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+function getComputedValue(selector, property) {
+    return getComputedStyle(document.querySelector(selector))[property];
+}
+
+shouldBe('getComputedValue(".invalid", "letterSpacing")', '"20px"');
+shouldBe('getComputedValue(".valid", "letterSpacing")', '"10px"');
+</script>
diff --git a/third_party/WebKit/LayoutTests/css3/calc/word-spacing-expected.txt b/third_party/WebKit/LayoutTests/css3/calc/word-spacing-expected.txt
new file mode 100644
index 0000000..bc8e4d3d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/calc/word-spacing-expected.txt
@@ -0,0 +1,6 @@
+PASS getComputedValue(".invalid", "wordSpacing") is "20px"
+PASS getComputedValue(".valid", "wordSpacing") is "10px"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/css3/calc/word-spacing.html b/third_party/WebKit/LayoutTests/css3/calc/word-spacing.html
new file mode 100644
index 0000000..18ab370
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/calc/word-spacing.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<style>
+.invalid {
+    word-spacing: 20px;
+    word-spacing: calc(1 + 1px);
+    word-spacing: calc(1 + 100%);
+    word-spacing: calc(100%);
+    word-spacing: calc(10px) bla;
+    word-spacing: calc(bla) 10px;
+}
+.valid {
+    word-spacing: calc(10px);
+}
+</style>
+<div class="invalid"></div>
+<div class="valid"></div>
+<script src="../../resources/js-test.js"></script>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+function getComputedValue(selector, property) {
+    return getComputedStyle(document.querySelector(selector))[property];
+}
+
+shouldBe('getComputedValue(".invalid", "wordSpacing")', '"20px"');
+shouldBe('getComputedValue(".valid", "wordSpacing")', '"10px"');
+</script>
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error-expected.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error-expected.html
new file mode 100644
index 0000000..f718ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error.html b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error.html
new file mode 100644
index 0000000..1f1a86d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/filters/effect-reference-convolve-error.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background-color: red; -webkit-filter: url(#f); filter: url(#f)"></div>
+<svg height="0">
+    <filter id="f" x="0" y="0" width="1" height="1">
+        <feConvolveMatrix/>
+        <feColorMatrix values="1 0 0 0 0,
+                               0 1 0 0 0.5,
+                               0 0 1 0 0,
+                               0 0 0 1 1"
+                       color-interpolation-filters="sRGB"/>
+    </filter>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one-expected.txt b/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one-expected.txt
new file mode 100644
index 0000000..3b20d0b2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one-expected.txt
@@ -0,0 +1,9 @@
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html
new file mode 100644
index 0000000..8afb632
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-grow-less-than-one.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<link href="resources/flexbox.css" rel="stylesheet">
+<style>
+.container {
+  height: 100px;
+  width: 100px;
+  border: 1px solid black;
+}
+
+.child-flex-grow-0-5 {
+  background-color: green;
+  flex-grow: 0.5;
+}
+
+.child-flex-grow-0-25 {
+  background-color: red;
+  flex-grow: 0.25;
+}
+
+.basis {
+  flex-basis: 30px;
+}
+
+.vertical {
+  -webkit-writing-mode: vertical-rl;
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.flexbox');">
+
+<div class="flexbox container">
+  <div class="child-flex-grow-0-5" data-expected-width="50"></div>
+</div>
+
+<div class="flexbox container">
+  <div class="child-flex-grow-0-5" data-expected-width="50"></div>
+  <div class="child-flex-grow-0-25" data-expected-width="25"></div>
+</div>
+
+<div class="flexbox container column">
+  <div class="child-flex-grow-0-5" data-expected-height="50"></div>
+  <div class="child-flex-grow-0-25" data-expected-height="25"></div>
+</div>
+
+<div class="flexbox container column vertical">
+  <div class="child-flex-grow-0-5 " data-expected-width="50"></div>
+  <div class="child-flex-grow-0-25 " data-expected-width="25"></div>
+</div>
+
+<div class="flexbox container vertical">
+  <div class="child-flex-grow-0-5 " data-expected-height="50"></div>
+  <div class="child-flex-grow-0-25 " data-expected-height="25"></div>
+</div>
+
+<div class="flexbox container">
+  <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div>
+  <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div>
+ </div>
+ 
+<div class="flexbox container column">
+  <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div>
+  <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div>
+</div>
+
+<div class="flexbox container vertical">
+  <div class="child-flex-grow-0-5 basis" data-expected-height="50"></div>
+  <div class="child-flex-grow-0-25 basis" data-expected-height="40"></div>
+</div>
+
+<div class="flexbox container column vertical">
+  <div class="child-flex-grow-0-5 basis" data-expected-width="50"></div>
+  <div class="child-flex-grow-0-25 basis" data-expected-width="40"></div>
+</div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-toBlob-toDataURL-race.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-toBlob-toDataURL-race.js
index 8c94c048..856d1a1 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-toBlob-toDataURL-race.js
+++ b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-toBlob-toDataURL-race.js
@@ -12,16 +12,16 @@
 var canvas = document.createElement("canvas");
 var ctx = canvas.getContext("2d");
 ctx.fillStyle = "#EE21AF";
-ctx.fillRect(0, 0, 2500, 1750);
+ctx.fillRect(0, 0, 250, 150);
 
 function testIfAllImagesAreCorrect()
 {
     // All resultant images should be the same as both async and main threads use the same image encoder
     var imageMatched = true;
-    var firstImageData = canvasCtxs[0].getImageData(0, 0, 2500, 1750).data;
+    var firstImageData = canvasCtxs[0].getImageData(0, 0, 250, 150).data;
     for (var i = 1; i < (numToBlobCalls + numToDataURLCalls); i++) 
     {
-        var nextImageData = canvasCtxs[i].getImageData(0, 0, 2500, 1750).data;
+        var nextImageData = canvasCtxs[i].getImageData(0, 0, 250, 150).data;
         for (var k = 0; k < firstImageData.length; k++) 
         {
             if (firstImageData[k]!=nextImageData[k]) 
@@ -58,7 +58,7 @@
 
     var newImg = new Image();
     newImg.onload = function() {
-        ctx_test.drawImage(newImg, 0, 0, 2500, 1750);
+        ctx_test.drawImage(newImg, 0, 0, 250, 150);
         onCanvasDrawCompleted(ctx_test);
     }    
     testImages[i] = newImg;
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows.html
index 62ac07b9..be5c37c7 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows.html
@@ -127,10 +127,11 @@
     </div>
 </div>
 
+<!-- We normalize fraction flex factors to 1, so we don't keep exact proportions with >1 factors. -->
 <div style="width: 10px; height: 60px;">
     <div class="grid gridWithIntrinsicSizeBiggerThanFlex">
         <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="40">XXXXX XXXXX XXXXX XXXXX</div>
-        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="160"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="80"></div>
     </div>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns-expected.txt
index 11ca326..f0f9d2a 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns-expected.txt
@@ -13,3 +13,8 @@
 PASS
 PASS
 PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns.html
index 4ce3353..ab7fda8b 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-columns.html
@@ -6,6 +6,10 @@
     grid-template-columns: minmax(1fr, 50px);
     grid-template-rows: 50px;
 }
+.gridZeroFlexContent {
+    grid-template-columns: minmax(1fr, 0px);
+    grid-template-rows: 50px;
+}
 .gridMaxFlexContent {
     grid-template-columns: minmax(30px, 2fr);
     grid-template-rows: 50px;
@@ -22,6 +26,27 @@
     grid-template-columns: minmax(300px, 3fr) minmax(150px, 1fr);
     grid-template-rows: 50px;
 }
+.gridRespectBaseSize {
+    grid-template-columns: minmax(75px, 1fr) minmax(0px, 2fr);
+    grid-template-rows: 50px;
+}
+.gridRespectProportions {
+    grid-template-columns: minmax(0px, .25fr) minmax(0px, .5fr) minmax(0px, 2fr);
+    grid-template-rows: 50px;
+}
+.gridRespectBaseSizeProportions {
+    grid-template-columns: minmax(50px, .25fr) minmax(0px, .5fr) minmax(0px, 1fr);
+    grid-template-rows: 50px;
+}
+.gridRespectBaseSizeBeforeProportions {
+    grid-template-columns: minmax(50px, .25fr) minmax(0px, .5fr) minmax(0px, 1fr);
+    grid-template-rows: 50px;
+}
+.firstRowThirdColumn {
+    background-color: yellow;
+    grid-column: 3;
+    grid-row: 1;
+}
 </style>
 <script src="../../resources/check-layout.js"></script>
 <body onload="checkLayout('.grid');">
@@ -34,6 +59,12 @@
     </div>
 </div>
 
+<div style="width: 100px">
+    <div class="grid gridZeroFlexContent">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="0" data-expected-height="50"></div>
+    </div>
+</div>
+
 <!-- Allow the extra logical space distribution to occur. -->
 <div style="width: 40px; height: 10px">
     <div class="grid gridMinFlexContent">
@@ -121,5 +152,40 @@
     </div>
 </div>
 
+<!-- Flex track length must be at least its baseSize. -->
+<div style="width: 100px; height: 10px;">
+    <div class="grid gridRespectBaseSize">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="75" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-expected-width="25" data-expected-height="50"></div>
+    </div>
+</div>
+
+<!-- Flex track lengths must be proportional to their flex factors.. -->
+<div style="width: 275px; height: 10px;">
+    <div class="grid gridRespectProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="25" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowThirdColumn" data-expected-width="200" data-expected-height="50"></div>
+    </div>
+</div>
+
+<!-- Flex track lengths must be proportional but still respecting their base sizes. -->
+<div style="width: 350px; height: 10px;">
+    <div class="grid gridRespectBaseSizeProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowThirdColumn" data-expected-width="200" data-expected-height="50"></div>
+    </div>
+</div>
+
+<!-- Not enough space to respect proportions, because minTrackBreadh it's a harder requirement -->
+<div style="width: 275px; height: 10px;">
+    <div class="grid gridRespectBaseSizeBeforeProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-expected-width="75" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowThirdColumn" data-expected-width="150" data-expected-height="50"></div>
+    </div>
+</div>
+
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows-expected.txt
index 891ef55..9f7a785d 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows-expected.txt
@@ -22,3 +22,12 @@
 PASS
 PASS
 PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows.html
index 9815856..2a16081 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-content-resolution-rows.html
@@ -6,6 +6,10 @@
     grid-template-columns: 50px;
     grid-template-rows: minmax(1fr, 50px);
 }
+.gridZeroFlexContent {
+    grid-template-columns: 50px;
+    grid-template-rows: minmax(1fr, 0px);
+}
 .gridMaxFlexContent {
     grid-template-columns: 50px;
     grid-template-rows: minmax(30px, 2fr);
@@ -18,6 +22,27 @@
     grid-template-columns: 50px;
     grid-template-rows: minmax(10px, 0.5fr) minmax(10px, 2fr);
 }
+.gridRespectBaseSize {
+    grid-template-columns: 50px;
+    grid-template-rows: minmax(75px, 1fr) minmax(0px, 2fr);
+}
+.gridRespectProportions {
+    grid-template-columns: 50px;
+    grid-template-rows: minmax(25px, .25fr) minmax(0px, .5fr) minmax(0px, 2fr);
+}
+.gridRespectBaseSizeProportions {
+    grid-template-columns: 50px;
+    grid-template-rows: minmax(50px, .25fr) minmax(0px, .5fr) minmax(0px, 1fr);
+}
+.gridRespectBaseSizeBeforeProportions {
+    grid-template-columns: 50px;
+    grid-template-rows: minmax(50px, .25fr) minmax(0px, .5fr) minmax(0px, 1fr);
+}
+.thirdRowFirstColumn {
+    background-color: yellow;
+    grid-column: 1;
+    grid-row: 3;
+}
 </style>
 <script src="../../resources/check-layout.js"></script>
 <body onload="checkLayout('.grid');">
@@ -31,6 +56,12 @@
 </div>
 
 <div style="height: 0px">
+    <div class="grid gridZeroFlexContent">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="0"></div>
+    </div>
+</div>
+
+<div style="height: 0px">
     <div class="grid gridMinFlexContent">
         <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
     </div>
@@ -137,10 +168,11 @@
     </div>
 </div>
 
+<!-- We normalize fraction flex factors to 1, so we don't keep exact proportions with >1 factors. -->
 <div class="constrainedContainer">
     <div class="grid gridTwoDoubleMaxFlexContent">
         <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="10"></div>
-        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="40"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="20"></div>
     </div>
 </div>
 
@@ -152,10 +184,11 @@
     </div>
 </div>
 
+<!-- We normalize fraction flex factors to 1, so we don't keep exact proportions with >1 factors. -->
 <div style="width: 10px; height: 60px">
     <div class="grid gridTwoDoubleMaxFlexContent">
         <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="10"></div>
-        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="40"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="20"></div>
     </div>
 </div>
 
@@ -166,10 +199,77 @@
     </div>
 </div>
 
+<!-- We normalize fraction flex factors to 1, so we don't keep exact proportions with >1 factors. -->
 <div style="width: 10px; height: 120px;">
     <div class="grid gridTwoDoubleMaxFlexContent">
         <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="10"></div>
-        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="40"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="20"></div>
+    </div>
+</div>
+
+<!-- Flex track length must be at least its baseSize. -->
+<div style="width: 10px; height: 100px;">
+    <div class="grid gridRespectBaseSize" style="height: 100%;">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="75"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="25"></div>
+    </div>
+</div>
+
+<div style="width: 10px; height: 100px;">
+    <div class="grid gridRespectBaseSize">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="75"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="150"></div>
+    </div>
+</div>
+
+<!-- Flex track lengths must be proportional to their flex factors.. -->
+<div style="width: 10px; height: 275px;">
+    <div class="grid gridRespectProportions" style="height: 100%;">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="25"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="200"></div>
+    </div>
+</div>
+
+<div style="width: 10px; height: 275px;">
+    <div class="grid gridRespectProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="25"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="13"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+    </div>
+</div>
+
+<!-- Flex track lengths must be proportional but still respecting their base sizes. -->
+<div style="width: 10px; height: 350px;">
+    <div class="grid gridRespectBaseSizeProportions" style="height: 100%;">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="100"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="200"></div>
+    </div>
+</div>
+
+<div style="width: 10px; height: 350px;">
+    <div class="grid gridRespectBaseSizeProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="25"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+    </div>
+</div>
+
+<!-- Not enough space to respect proportions, because minTrackBreadh it's a harder requirement -->
+<div style="width: 10px; height: 275px;">
+    <div class="grid gridRespectBaseSizeBeforeProportions" style="height: 100%;">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="75"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="150"></div>
+    </div>
+</div>
+
+<div style="width: 10px; height: 275px;">
+    <div class="grid gridRespectBaseSizeBeforeProportions">
+        <div class="sizedToGridArea firstRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-expected-width="50" data-expected-height="25"></div>
+        <div class="sizedToGridArea thirdRowFirstColumn" data-expected-width="50" data-expected-height="50"></div>
     </div>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1-expected.txt
index bde5076..01cbaf1c 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1-expected.txt
@@ -3,3 +3,4 @@
 PASS
 PASS
 PASS
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1.html
index d8cf2ed18..f9fd9b19 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1.html
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/flex-factor-sum-less-than-1.html
@@ -19,6 +19,11 @@
     width: 100px;
     height: 100px;
 }
+.zeroValueFlexFactor {
+    grid-template-columns: .0fr .2fr .3fr;
+    grid-template-rows: 50px;
+    width: 100px;
+}
 .firstRowThirdColumn {
     background-color: yellow;
     grid-column: 3;
@@ -62,6 +67,14 @@
 </div>
 
 <div style="position: relative;">
+    <div class="grid zeroValueFlexFactor">
+        <div class="firstRowFirstColumn" data-expected-width="0" data-expected-height="50"></div>
+        <div class="firstRowSecondColumn" data-expected-width="20" data-expected-height="50"></div>
+        <div class="firstRowThirdColumn" data-expected-width="30" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative;">
     <div class="grid fixedAndfractionFlexFactors">
         <div class="firstRowFirstColumn" data-expected-width="50" data-expected-height="5"></div>
         <div class="firstRowSecondColumn" data-expected-width="4" data-expected-height="5"></div>
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set-expected.txt
index 73e4ce3..b68ead25 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-columns-rows-get-set-expected.txt
@@ -122,6 +122,14 @@
 PASS element.style.gridTemplateColumns is "3fr"
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "600px"
 PASS element.style.gridTemplateRows is "4fr"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "0px"
+PASS element.style.gridTemplateColumns is "0fr"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
+PASS element.style.gridTemplateRows is "0fr"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "0px"
+PASS element.style.gridTemplateColumns is "minmax(0fr, 0fr)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
+PASS element.style.gridTemplateRows is "minmax(0fr, 0fr)"
 
 Test getting and setting grid-template-columns and grid-template-rows to calc() values through JS
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "150px"
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/non-grid-columns-rows-get-set-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/non-grid-columns-rows-get-set-expected.txt
index dfdb802..83533059 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/non-grid-columns-rows-get-set-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/non-grid-columns-rows-get-set-expected.txt
@@ -110,6 +110,14 @@
 PASS element.style.gridTemplateColumns is "minmax(auto, 8vh)"
 PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "minmax(80px, auto)"
 PASS element.style.gridTemplateRows is "minmax(10vw, auto)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "0px"
+PASS element.style.gridTemplateColumns is "0fr"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
+PASS element.style.gridTemplateRows is "0fr"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "0px"
+PASS element.style.gridTemplateColumns is "minmax(0fr, 0fr)"
+PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "0px"
+PASS element.style.gridTemplateRows is "minmax(0fr, 0fr)"
 
 Test setting grid-template-columns and grid-template-rows to bad values through JS
 PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none"
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/grid-columns-rows-get-set.js b/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/grid-columns-rows-get-set.js
index d442239..6f024335 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/grid-columns-rows-get-set.js
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/grid-columns-rows-get-set.js
@@ -62,6 +62,9 @@
 testGridDefinitionsSetJSValues("3.1459fr", "2.718fr", "800px", "600px");
 // A leading '+' is allowed.
 testGridDefinitionsSetJSValues("+3fr", "+4fr", "800px", "600px", "3fr", "4fr");
+// Flex factor values can be zero.
+testGridDefinitionsSetJSValues("0fr", ".0fr", "0px", "0px", "0fr", "0fr");
+testGridDefinitionsSetJSValues("minmax(0fr, 0fr)", "minmax(.0fr, .0fr)", "0px", "0px", "minmax(0fr, 0fr)", "minmax(0fr, 0fr)");
 
 debug("");
 debug("Test getting and setting grid-template-columns and grid-template-rows to calc() values through JS");
@@ -80,9 +83,9 @@
 testGridDefinitionsSetBadJSValues("minmax()", "minmax(30px 30% 30em)");
 testGridDefinitionsSetBadJSValues("-2fr", "3ffr");
 testGridDefinitionsSetBadJSValues("-2.05fr", "+-3fr");
-testGridDefinitionsSetBadJSValues("0fr", "1r");
+testGridDefinitionsSetBadJSValues("1f", "1r");
 // A dimension doesn't allow spaces between the number and the unit.
-testGridDefinitionsSetBadJSValues(".0000fr", "13 fr");
+testGridDefinitionsSetBadJSValues(".1 fr", "13 fr");
 testGridDefinitionsSetBadJSValues("7.-fr", "-8,0fr");
 // Negative values are not allowed.
 testGridDefinitionsSetBadJSValues("-1px", "-6em");
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/non-grid-columns-rows-get-set.js b/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/non-grid-columns-rows-get-set.js
index a74990e..db4dbb9 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/non-grid-columns-rows-get-set.js
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/resources/non-grid-columns-rows-get-set.js
@@ -56,6 +56,9 @@
 // A leading '+' is allowed.
 testNonGridDefinitionsSetJSValues("+3fr", "+4fr", "3fr", "4fr", "3fr", "4fr");
 testNonGridDefinitionsSetJSValues("minmax(auto, 8vh)", "minmax(10vw, auto)", "minmax(auto, 48px)", "minmax(80px, auto)");
+// Flex factor values can be zero.
+testGridDefinitionsSetJSValues("0fr", ".0fr", "0px", "0px", "0fr", "0fr");
+testGridDefinitionsSetJSValues("minmax(0fr, 0fr)", "minmax(.0fr, .0fr)", "0px", "0px", "minmax(0fr, 0fr)", "minmax(0fr, 0fr)");
 
 debug("");
 debug("Test setting grid-template-columns and grid-template-rows to bad values through JS");
@@ -67,9 +70,9 @@
 testGridDefinitionsSetBadJSValues("minmax()", "minmax(30px 30% 30em)");
 testGridDefinitionsSetBadJSValues("-2fr", "3ffr");
 testGridDefinitionsSetBadJSValues("-2.05fr", "+-3fr");
-testGridDefinitionsSetBadJSValues("0fr", "1r");
+testGridDefinitionsSetBadJSValues("1f", "1r");
 // A dimension doesn't allow spaces between the number and the unit.
-testGridDefinitionsSetBadJSValues(".0000fr", "13 fr");
+testGridDefinitionsSetBadJSValues(".0001 fr", "13 fr");
 testGridDefinitionsSetBadJSValues("7.-fr", "-8,0fr");
 // Negative values are not allowed.
 testGridDefinitionsSetBadJSValues("-1px", "-6em");
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash-expected.txt
new file mode 100644
index 0000000..f9acae3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash-expected.txt
@@ -0,0 +1,5 @@
+PASS no crash
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash.html
new file mode 100644
index 0000000..1e42e2d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLScriptElement/script-element-moved-from-disposed-document-crash.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+</head>
+<body id=bodyElement>
+<iframe id=iframe></iframe>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+var xhtml = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html");
+var body = bodyElement;
+iframe.contentDocument.documentElement.appendChild(body);
+body.parentNode.removeChild(body);
+gc();
+xhtml.documentElement.appendChild(body);
+testPassed('no crash');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation-expected.txt
new file mode 100644
index 0000000..c8380ae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation-expected.txt
@@ -0,0 +1,14 @@
+Test that an inner global captured in a closure acts as if its creating context is detached when the creating context is navigated.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window is self
+PASS window is frames
+PASS parent is top
+PASS window is null.
+PASS self is null.
+PASS frames is null.
+PASS parent is null.
+PASS top is null.
+
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation.html b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation.html
new file mode 100644
index 0000000..8482fb69
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-in-closure-after-navigation.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+<script>
+var jsTestIsAsync = true;
+description('Test that an inner global captured in a closure acts as if its creating context is detached when the creating context is navigated.');
+
+var loadCount = 0;
+function maybeFinishTest()
+{
+    if (++loadCount < 2)
+        return;
+
+    savedClosure();
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</head>
+<body>
+<iframe src="resources/property-access-in-closure-after-navigation-child.html" onload="maybeFinishTest()"></iframe>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index 2e299db..5aaa248 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -26,6 +26,7 @@
 PASS oldChildWindow.innerHeight is newChildWindow.innerHeight
 PASS oldChildWindow.innerWidth is newChildWindow.innerWidth
 PASS oldChildWindow.isJsTest is newChildWindow.isJsTest
+PASS oldChildWindow.isSecureContext is newChildWindow.isSecureContext
 PASS oldChildWindow.jsTestIsAsync is newChildWindow.jsTestIsAsync
 PASS oldChildWindow.length is newChildWindow.length
 PASS oldChildWindow.location.ancestorOrigins.length is newChildWindow.location.ancestorOrigins.length
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index 0a9640a96..c2ac97b 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -26,6 +26,7 @@
 PASS childWindow.innerHeight is 0
 PASS childWindow.innerWidth is 0
 FAIL childWindow.isJsTest should be false (of type boolean). Was undefined (of type undefined).
+PASS childWindow.isSecureContext is false
 FAIL childWindow.jsTestIsAsync should be false (of type boolean). Was undefined (of type undefined).
 PASS childWindow.length is 0
 FAIL childWindow.location.ancestorOrigins.length should be 0. Threw exception TypeError: Cannot read property 'length' of undefined
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index a294994..0c5e63a 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -26,6 +26,7 @@
 PASS childWindow.innerHeight is 0
 PASS childWindow.innerWidth is 0
 FAIL childWindow.isJsTest should be false (of type boolean). Was undefined (of type undefined).
+PASS childWindow.isSecureContext is false
 PASS childWindow.length is 0
 FAIL childWindow.location.ancestorOrigins.length should be 0. Threw exception TypeError: Cannot read property 'length' of undefined
 FAIL childWindow.location.hash should be  (of type string). Was undefined (of type undefined).
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-iframe-child.html b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-iframe-child.html
index 4550d12e..ee7b2ee4 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-iframe-child.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-iframe-child.html
@@ -1,4 +1,8 @@
 <script>
+    // Capture window.window and window.parent: once this context is navigated, these properties
+    // always return null.
+    var w = window;
+    var p = parent;
     parent.accessFrame = function()
     {
         function normalizeURL(url)
@@ -7,12 +11,12 @@
         }
 
         try {
-            parent.log("document.URL: " + normalizeURL(document.URL));
-            parent.log("window.document.URL: " + normalizeURL(window.document.URL));
-            parent.log("name: " + name);
-            parent.log("window.name: " + window.name);
+            p.log("document.URL: " + normalizeURL(document.URL));
+            p.log("window.document.URL: " + normalizeURL(w.document.URL));
+            p.log("name: " + name);
+            p.log("window.name: " + w.name);
         } catch (e) {
-            parent.log("An exception was thrown: " + e.message);
+            p.log("An exception was thrown: " + e.message);
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-window-child.html b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-window-child.html
index 36910954..4b2ea00 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-window-child.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/dom-access-from-closure-window-child.html
@@ -1,4 +1,8 @@
 <script>
+    // Capture window.window and window.opener: once this context is navigated, these properties
+    // always return null.
+    var w = window;
+    var o = opener;
     opener.accessFrame = function()
     {
         function normalizeURL(url)
@@ -7,12 +11,12 @@
         }
 
         try {
-            opener.log("document.URL: " + normalizeURL(document.URL));
-            opener.log("window.document.URL: " + normalizeURL(window.document.URL));
-            opener.log("name: " + name);
-            opener.log("window.name: " + window.name);
+            o.log("document.URL: " + normalizeURL(document.URL));
+            o.log("window.document.URL: " + normalizeURL(w.document.URL));
+            o.log("name: " + name);
+            o.log("window.name: " + w.name);
         } catch (e) {
-            opener.log("An exception was thrown: " + e.message);
+            o.log("An exception was thrown: " + e.message);
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/resources/property-access-in-closure-after-navigation-child.html b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/property-access-in-closure-after-navigation-child.html
new file mode 100644
index 0000000..c951920a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/resources/property-access-in-closure-after-navigation-child.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+function startTest()
+{
+    t = window.top;
+    t.shouldBe("window", "self");
+    t.shouldBe("window", "frames");
+    t.shouldBe("parent", "top");
+    t.savedClosure = function()
+    {
+        // The normal shouldBeNull() helpers don't work well here, since they don't eval
+        //in the right context.
+        function testProperty(value, name)
+        {
+            if (value === null)
+                t.testPassed(name + " is null.");
+            else
+                t.testFailed(name + " is not null!");
+        }
+        testProperty(window, "window");
+        testProperty(self, "self");
+        testProperty(frames, "frames");
+        testProperty(parent, "parent");
+        testProperty(top, "top");
+    };
+    location = 'data:text/html,<body>Testing...</body>';
+}
+</script>
+</head>
+<body onload="startTest()">
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/gc-treescope.html b/third_party/WebKit/LayoutTests/fast/dom/gc-treescope.html
index ac108512..acd6c8cb 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/gc-treescope.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/gc-treescope.html
@@ -36,7 +36,8 @@
     // The crash (use-after-free) is flaky. We have to reload the page a number of times to reproduce the crash.
     // I couldn't find a reliable way to reproduce, such as using gc(), adjusting the scopes of variables and so on.
     // As of now, we can hit a crash by reloading about 50 times.
-    reloadUntil(80);
+    // Reload 30 times here since reloading 80 times caused flaky timeout on Win. See crbug.com/481269.
+    reloadUntil(30);
 }
 
 document.addEventListener("DOMContentLoaded", init, false);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/resources/javascript-url-crash-function-iframe.html b/third_party/WebKit/LayoutTests/fast/dom/resources/javascript-url-crash-function-iframe.html
index 1d6a49d..1520e08 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/resources/javascript-url-crash-function-iframe.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/resources/javascript-url-crash-function-iframe.html
@@ -15,8 +15,11 @@
 
 setTimeout(function ()
 {
+    // Capture window.window into a variable, since this property returns null as soon as the
+    // context is navigated.
+    var w = window;
     test();
-    if (window.testRunner)
-        testRunner.notifyDone();
+    if (w.testRunner)
+        w.testRunner.notifyDone();
 }, 0);
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt
new file mode 100644
index 0000000..29d28aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt
@@ -0,0 +1,2 @@
+CONSOLE ERROR: Blocked alert('hello world!') during beforeunload.
+Test that alert() inside a document.write() during a beforeunload handler does not confuse the modal dialog blocker. This test passes if no alert() dialogs are seen. 
diff --git a/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write.html b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write.html
new file mode 100644
index 0000000..061ec0e0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<script>
+function runTest()
+{
+    if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+        document.querySelector('iframe').onload = function () { testRunner.notifyDone(); };
+    }
+    window[0].onbeforeunload = function() { window[0].document.write("<script>alert('hello world!');</scr" + "ipt>"); }
+    window[0].location = 'data:text/plain,Done!';
+}
+</script>
+<body onload="runTest()">
+<p>Test that alert() inside a document.write() during a beforeunload handler does not confuse the modal dialog blocker. This test passes if no alert() dialogs are seen.
+<iframe>
+</iframe>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/crash-on-querying-event-path-expected.txt b/third_party/WebKit/LayoutTests/fast/events/crash-on-querying-event-path-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/http/tests/dom/crash-on-querying-event-path-expected.txt
rename to third_party/WebKit/LayoutTests/fast/events/crash-on-querying-event-path-expected.txt
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/crash-on-querying-event-path.html b/third_party/WebKit/LayoutTests/fast/events/crash-on-querying-event-path.html
similarity index 75%
rename from third_party/WebKit/LayoutTests/http/tests/dom/crash-on-querying-event-path.html
rename to third_party/WebKit/LayoutTests/fast/events/crash-on-querying-event-path.html
index 657bf25..8ffab27 100644
--- a/third_party/WebKit/LayoutTests/http/tests/dom/crash-on-querying-event-path.html
+++ b/third_party/WebKit/LayoutTests/fast/events/crash-on-querying-event-path.html
@@ -1,6 +1,6 @@
 <html>
 <head>
-<script src="/js-test-resources/js-test.js"></script>
+<script src="../../resources/js-test.js"></script>
 </head>
 <body>
 <script>
@@ -9,24 +9,18 @@
 
 var root = document.documentElement;
 var iframe = root.ownerDocument.createElement('iframe');
-var timeouts = [];
-iframe.onload = iframeOnload;
-root.appendChild(iframe);
-
-function iframeOnload() {
+iframe.onload = function() {
     var defaultView = iframe.contentDocument.defaultView;
     defaultView.onpageshow = onPageShow;
-    iframe.src = null;
-    timeouts[timeouts.length] = window.setTimeout(nextIframeLoaded, 100);
-}
+    window.setTimeout(tryToCrash, 0);
+};
+root.appendChild(iframe);
 
 function onPageShow() {
     eventObj = arguments[0];
 }
 
-function nextIframeLoaded() {
-    timeouts.forEach(window.clearTimeout);
-
+function tryToCrash() {
     // Access of eventObj.path caused the crash.
     // The test is somewhat flaky, in that the test may pass as correct
     // despite the bug being the code. The exact conditions
diff --git a/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak-expected.txt b/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak-expected.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak-expected.txt
@@ -0,0 +1 @@
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak.html b/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak.html
new file mode 100644
index 0000000..c81c4de
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/custom-event-detail-leak.html
@@ -0,0 +1,6 @@
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+// This shouldn't leak document objects.
+var e = new CustomEvent('custom', {'detail': new Error()});
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled-expected.txt b/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled-expected.txt
index b728dadd..9844604 100644
--- a/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled-expected.txt
@@ -12,7 +12,8 @@
 Activated [object HTMLInputElement] type=submit
 form submitted
 
-anchor activated
+Activated [object HTMLInputElement] type=image
+form submitted
 
 Focusing [object HTMLInputElement] type=image and pressing enter
 Activated [object HTMLInputElement] type=image
diff --git a/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled.html b/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled.html
index 649c9af..d5106257a 100644
--- a/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled.html
+++ b/third_party/WebKit/LayoutTests/fast/events/domactivate-sets-underlying-click-event-as-handled.html
@@ -5,7 +5,7 @@
     <form action="javascript:formSubmitted()">
         <input type=text>
         <input type=submit>
-        <input type=image>
+        <input src="resources/abe.png" type=image>
         <button>button</button>
         <input type=reset>
         <button type=reset>button reset</button>
@@ -30,43 +30,45 @@
 
 document.forms[0].children[0].value = "blah";
 
-for (var i=0; i < document.forms[0].children.length; i++) {
-    var element = document.forms[0].children[i];
+document.querySelector("input[type=image]").addEventListener("load", function() {
+    for (var i=0; i < document.forms[0].children.length; i++) {
+        var element = document.forms[0].children[i];
 
-    element.addEventListener("click", function () {
-        log("Activated " + this + " type=" + this.type);
-    }, false);
+        element.addEventListener("click", function () {
+            log("Activated " + this + " type=" + this.type);
+        }, false);
 
-    if (!window.eventSender)
-        continue;
+        if (!window.eventSender)
+            continue;
 
-    if (element.type == "text") {
+        if (element.type == "text") {
+            log("Focusing " + element + " type=" + element.type + " and pressing enter");
+            element.focus();
+            eventSender.keyDown("\n");
+            continue;
+        }
+
+        eventSender.mouseMoveTo(element.offsetLeft + element.clientWidth / 2, element.offsetTop + element.clientHeight / 2);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+
+        if (element.type == "radio" || element.type == "checkbox")
+            continue;
+
         log("Focusing " + element + " type=" + element.type + " and pressing enter");
         element.focus();
         eventSender.keyDown("\n");
-        continue;
     }
 
-    eventSender.mouseMoveTo(element.offsetLeft + element.clientWidth / 2, element.offsetTop + element.clientHeight / 2);
-    eventSender.mouseDown();
-    eventSender.mouseUp();
+    if (window.eventSender) {
+        var details = document.querySelector("details");
+        eventSender.mouseMoveTo(details.offsetLeft + details.clientWidth / 2, details.offsetTop + details.clientHeight / 2);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+        log("\nThe details element was " + (details.open ? "" : "not ") + "opened");
+    }
 
-    if (element.type == "radio" || element.type == "checkbox")
-        continue;
-
-    log("Focusing " + element + " type=" + element.type + " and pressing enter");
-    element.focus();
-    eventSender.keyDown("\n");
-}
-
-if (window.eventSender) {
-    var details = document.querySelector("details");
-    eventSender.mouseMoveTo(details.offsetLeft + details.clientWidth / 2, details.offsetTop + details.clientHeight / 2);
-    eventSender.mouseDown();
-    eventSender.mouseUp();
-    log("\nThe details element was " + (details.open ? "" : "not ") + "opened");
-}
-
-if (window.testRunner)
-    document.querySelector("a").style.display = "none";
+    if (window.testRunner)
+        document.querySelector("a").style.display = "none";
+});
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally-expected.txt
new file mode 100644
index 0000000..232541b8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally-expected.txt
@@ -0,0 +1,15 @@
+This tests that a gesture scroll isn't propagated from an inner div to an outer div when the inner div has remaining scroll offset on one axis but not on the other, unless the outer div starts at its scroll extent
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS horizontal.scrollLeft is 15
+PASS vertical.scrollTop is 0
+PASS horizontal.scrollLeft is 600
+PASS vertical.scrollTop is 0
+PASS horizontal.scrollLeft is 600
+PASS vertical.scrollTop is 20
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally.html
similarity index 62%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally.html
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally.html
index ce8b3fd..bfb48836 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-diagonally.html
@@ -49,15 +49,30 @@
 function runTest()
 {
     if (window.eventSender) {
-        description('This tests that a gesture scroll is propagated from an ' +
-                'inner div to an outer div when the inner div has ' +
-                'remaining scroll offset on one axis, but not on the other.');
+        description('This tests that a gesture scroll isn\'t propagated from an ' +
+            'inner div to an outer div when the inner div has ' +
+            'remaining scroll offset on one axis but not on the other, unless ' +
+            'the outer div starts at its scroll extent');
         if (checkTestDependencies()) {
             eventSender.gestureScrollBegin(10, 10);
             eventSender.gestureScrollUpdate(-15, -20);
             eventSender.gestureScrollEnd(0, 0);
             shouldBe("horizontal.scrollLeft", "15");
+            shouldBe("vertical.scrollTop", "0");
+
+            // Scroll to extents.
+            eventSender.gestureScrollBegin(10, 10);
+            eventSender.gestureScrollUpdate(-1000, -1000);
+            eventSender.gestureScrollEnd(0, 0);
+            shouldBe("horizontal.scrollLeft", "600");
+            shouldBe("vertical.scrollTop", "0");
+
+            eventSender.gestureScrollBegin(10, 10);
+            eventSender.gestureScrollUpdate(-15, -20);
+            eventSender.gestureScrollEnd(0, 0);
+            shouldBe("horizontal.scrollLeft", "600");
             shouldBe("vertical.scrollTop", "20");
+
             if (window.testRunner)
               testRunner.notifyDone();
         } else {
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-expected.txt
similarity index 72%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-expected.txt
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-expected.txt
index 48f5ed4..5df885b 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent-expected.txt
@@ -1,4 +1,4 @@
-This tests that a gesture scroll is propagated from an inner div to an outer div when the inner div has no remaining scroll offset.
+This tests that a gesture scroll isn't propagated from an inner div to an outer div when the inner div has no remaining scroll offset.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -11,7 +11,7 @@
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 second gesture
-PASS movedbox.scrollTop is 10
+PASS movedbox.scrollTop is 0
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 scroll event 0+> [object HTMLDivElement]
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent.html
similarity index 95%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent.html
index a79d6de..7d1be9b0 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-past-extent.html
@@ -83,7 +83,7 @@
 var expectedGesturesTotal = 2;
 var gesturesOccurred = 0;
 var scrollAmountX = ['0', '0'];
-var scrollAmountY = ['0', '10'];
+var scrollAmountY = ['0', '0'];
 var wheelEventsOccurred = 0;
 var expectedWheelEventsOccurred = ['0', '0'];
 var scrollEventsOccurred = 0;
@@ -125,7 +125,7 @@
     touchtarget.addEventListener("mousewheel", recordWheel);
 
     if (window.eventSender) {
-        description('This tests that a gesture scroll is propagated from an ' +
+        description('This tests that a gesture scroll isn\'t propagated from an ' +
                 'inner div to an outer div when the inner div has no ' +
                 'remaining scroll offset.');
         if (checkTestDependencies())
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally-expected.txt
deleted file mode 100644
index b7f6d2dd..0000000
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated-diagonally-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This tests that a gesture scroll is propagated from an inner div to an outer div when the inner div has remaining scroll offset on one axis, but not on the other.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-PASS horizontal.scrollLeft is 15
-PASS vertical.scrollTop is 20
-
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent-expected.txt
similarity index 71%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated-expected.txt
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent-expected.txt
index 68cb85d..407b16aa 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent-expected.txt
@@ -1,4 +1,4 @@
-This tests that a gesture scroll is propagated from an inner div to an outer div twice when the scrolled divs have no remaining scroll offset.
+This tests that a gesture scroll isn't propagated from an inner div to an outer div when the scrolled divs have no remaining scroll offset.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -11,7 +11,7 @@
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 second gesture
-PASS movedbox.scrollTop is 25
+PASS movedbox.scrollTop is 0
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 scroll event 0+> [object HTMLDivElement]
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent.html
similarity index 94%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent.html
index 7180c509..ab5137bf 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-past-extent.html
@@ -107,7 +107,7 @@
 var expectedGesturesTotal = 2;
 var gesturesOccurred = 0;
 var scrollAmountX = ['0', '0'];
-var scrollAmountY = ['0', '25'];
+var scrollAmountY = ['0', '0'];
 var wheelEventsOccurred = 0;
 var expectedWheelEventsOccurred = ['0', '0'];
 var scrollEventsOccurred = 0;
@@ -150,8 +150,8 @@
     touchtarget.addEventListener("mousewheel", recordWheel);
 
     if (window.eventSender) {
-        description('This tests that a gesture scroll is propagated from an ' +
-                'inner div to an outer div twice when the scrolled divs have no ' +
+        description('This tests that a gesture scroll isn\'t propagated from an ' +
+                'inner div to an outer div when the scrolled divs have no ' +
                 'remaining scroll offset.');
         if (checkTestDependencies())
             firstGestureScroll();
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent-expected.txt
similarity index 73%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated-expected.txt
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent-expected.txt
index 8747c1f..e644588b 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent-expected.txt
@@ -1,5 +1,5 @@
 
-This tests that a gesture scroll is propagated from an iframe to an outer div when the iframe has no remaining scroll offset.
+This tests that a gesture scroll isn't propagated from an iframe to an outer div when the iframe has no remaining scroll offset.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -12,7 +12,7 @@
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 second gesture
-PASS movedbox.scrollTop is 50
+PASS movedbox.scrollTop is 0
 PASS movedbox.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 scroll event 0+> [object HTMLDocument]
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent.html
similarity index 95%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent.html
index ee8f509..345ad0bc 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-past-extent.html
@@ -62,7 +62,7 @@
 var expectedGesturesTotal = 2;
 var gesturesOccurred = 0;
 var scrollAmountX = ['0', '0'];
-var scrollAmountY = ['0', '50'];
+var scrollAmountY = ['0', '0'];
 var wheelEventsOccurred = 0;
 var expectedWheelEventsOccurred = ['0', '0'];
 var scrollEventsOccurred = 0;
@@ -104,7 +104,7 @@
     touchtarget.contentDocument.body.addEventListener("mousewheel", recordWheel);
 
     if (window.eventSender) {
-        description('This tests that a gesture scroll is propagated from an ' +
+        description('This tests that a gesture scroll isn\'t propagated from an ' +
                 'iframe to an outer div when the iframe has no remaining ' +
                 'scroll offset.');
         if (checkTestDependencies())
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
index 33d4a28c..dd5aa912 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
@@ -25,9 +25,9 @@
 Gesture scrolling input text should scroll text the specified amount
 PASS box.scrollLeft is 60
 PASS container.scrollLeft is 0
-Gesture scrolling input text past scroll width should scroll container div
+Gesture scrolling input text past scroll width shouldn't scroll container div
 PASS box.scrollLeft is fullyScrolled
-PASS container.scrollLeft is 50
+PASS container.scrollLeft is 0
 ===Testing vertical scroll behavior===
 PASS box.scrollTop is 0
 PASS container.scrollTop is 0
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
index fb816b0b..9a18295 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
@@ -54,11 +54,11 @@
             shouldBe('container.scrollLeft', '0');
 
             eventSender.gestureScrollBegin(gestureX, gestureY);
-            // Prevent scroll to propagate by passing true for third parameter
-            eventSender.gestureScrollUpdate(-10, 0, true);
-            eventSender.gestureScrollUpdate(-10, 0, true);
-            eventSender.gestureScrollUpdate(-10, 0, true);
-            eventSender.gestureScrollUpdate(-10, 0, true);
+
+            eventSender.gestureScrollUpdate(-10, 0);
+            eventSender.gestureScrollUpdate(-10, 0);
+            eventSender.gestureScrollUpdate(-10, 0);
+            eventSender.gestureScrollUpdate(-10, 0);
             eventSender.gestureScrollEnd(0, 0);
 
             debug("Flinging input text should scroll text by the specified amount");
@@ -68,10 +68,10 @@
             resetScroll();
 
             eventSender.gestureScrollBegin(gestureX, gestureY);
-            eventSender.gestureScrollUpdate(-fullyScrolled, 0, true);
-            eventSender.gestureScrollUpdate(-100, 0, true);
-            eventSender.gestureScrollUpdate(-100, 0, true);
-            eventSender.gestureScrollUpdate(-300, 0, true);
+            eventSender.gestureScrollUpdate(-fullyScrolled, 0);
+            eventSender.gestureScrollUpdate(-100, 0);
+            eventSender.gestureScrollUpdate(-100, 0);
+            eventSender.gestureScrollUpdate(-300, 0);
             eventSender.gestureScrollEnd(0, 0);
 
             debug("Flinging input text past the scrollable width shouldn't scroll containing div");
@@ -80,8 +80,8 @@
             shouldBe('container.scrollLeft', '0');
 
             eventSender.gestureScrollBegin(gestureX, gestureY);
-            eventSender.gestureScrollUpdate(-30, 0, true);
-            eventSender.gestureScrollUpdate(-30, 0, true);
+            eventSender.gestureScrollUpdate(-30, 0);
+            eventSender.gestureScrollUpdate(-30, 0);
             eventSender.gestureScrollEnd(0, 0);
 
             debug("Flinging fully scrolled input text should fling containing div");
@@ -113,9 +113,9 @@
             eventSender.gestureScrollUpdate(-50, 0);
             eventSender.gestureScrollEnd(0, 0);
 
-            debug("Gesture scrolling input text past scroll width should scroll container div");
+            debug("Gesture scrolling input text past scroll width shouldn't scroll container div");
             shouldBe('box.scrollLeft', 'fullyScrolled');
-            shouldBe('container.scrollLeft', '50');
+            shouldBe('container.scrollLeft', '0');
         }
 
         function testVerticalScroll()
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
index 02d3c02..61fbdd649 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
@@ -27,9 +27,12 @@
 PASS container.scrollTop is 0
 PASS box.scrollTop is 0
 PASS container.scrollTop is 0
-Gesture scrolling list past the end should scroll container div
+Gesture scrolling list past the end shouldn't scroll container div
 PASS box.scrollTop is fullyScrolled
-PASS container.scrollTop is 50
+PASS container.scrollTop is 0
+Gesture scrolling list past the end should scroll container div when starting at scroll extent
+PASS box.scrollTop is fullyScrolled
+PASS container.scrollTop is fullyScrolled + 50
 ===Testing horizontal scroll===
 PASS box.scrollLeft is 0
 PASS container.scrollLeft is 0
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox.html
index 9847c71..f5dcfcb 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-listbox.html
@@ -116,9 +116,19 @@
             eventSender.gestureScrollUpdate(0, -50);
             eventSender.gestureScrollEnd(0, 0);
 
-            debug("Gesture scrolling list past the end should scroll container div");
+            debug("Gesture scrolling list past the end shouldn't scroll container div");
             shouldBe('box.scrollTop', 'fullyScrolled');
-            shouldBe('container.scrollTop', '50');
+            shouldBe('container.scrollTop', '0');
+
+            eventSender.gestureScrollBegin(gestureX, gestureY);
+            eventSender.gestureScrollUpdate(0, -fullyScrolled);
+            eventSender.gestureScrollUpdate(0, -50);
+            eventSender.gestureScrollEnd(0, 0);
+
+            debug("Gesture scrolling list past the end should scroll container div when starting at scroll extent");
+            shouldBe('box.scrollTop', 'fullyScrolled');
+            shouldBe('container.scrollTop', 'fullyScrolled + 50');
+
         }
 
         function testHorizontalScroll()
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent-expected.txt
similarity index 74%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated-expected.txt
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent-expected.txt
index 6bdf5b6c7..e1b1525a 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent-expected.txt
@@ -1,4 +1,4 @@
-This tests that a gesture scroll is propagated from a div to the page when the div has no remaining scroll offset.
+This tests that a gesture scroll isn't propagated from a div to the page when the div has no remaining scroll offset.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
@@ -11,7 +11,7 @@
 PASS document.scrollingElement.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 second gesture
-PASS document.scrollingElement.scrollTop is 160
+PASS document.scrollingElement.scrollTop is 0
 PASS document.scrollingElement.scrollLeft is 0
 PASS wheelEventsOccurred is 0
 scroll event 0+> [object HTMLDivElement]
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent.html
similarity index 96%
rename from third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html
rename to third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent.html
index 43a8432..d5e895c 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-past-extent.html
@@ -77,7 +77,7 @@
 var expectedGesturesTotal = 2;
 var gesturesOccurred = 0;
 var scrollAmountX = ['0', '0'];
-var scrollAmountY = ['0', '160'];
+var scrollAmountY = ['0', '0'];
 var wheelEventsOccurred = 0;
 var expectedWheelEventsOccurred = ['0', '0'];
 var scrollEventsOccurred = 0;
@@ -137,7 +137,7 @@
     touchtarget.addEventListener("mousewheel", recordWheel);
 
     if (window.eventSender) {
-        description('This tests that a gesture scroll is propagated from a div ' + 
+        description('This tests that a gesture scroll isn\'t propagated from a div ' + 
                 'to the page when the div has no remaining scroll offset.');
         if (checkTestDependencies())
             firstGestureScroll();
diff --git a/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch-expected.txt
index 0df52d1a..310d627 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch-expected.txt
@@ -20,6 +20,8 @@
 PASS "+1" was sanitized to "".
 PASS " 10" was sanitized to "".
 PASS "10 " was sanitized to "".
+PASS "0." was sanitized to "".
+PASS "1." was sanitized to "".
 PASS "1,2" was sanitized to "".
 PASS "1E" was sanitized to "".
 PASS "NaN" was sanitized to "".
@@ -30,8 +32,7 @@
 PASS "infinity" was sanitized to "".
 PASS "" is a valid number.
 PASS "1.2E65535" was sanitized to "".
-PASS "1." is a valid number.
-PASS "1.2e10" is a valid number.
+PASS "1.2e10" was sanitized to "1.2e10".
 PASS "invalid" is a valid number when disabled.
 PASS successfullyParsed is true
 
diff --git a/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch.html b/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch.html
index ef354536..37a83d81 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/number/number-validity-typemismatch.html
@@ -10,6 +10,8 @@
 var i = document.createElement('input');
 i.type = 'number';
 
+// TODO(tkent): check() doesn't make sense because the number type never be
+// typeMismatch.
 function check(value, disabled)
 {
     i.value = value;
@@ -55,6 +57,8 @@
 checkSanitization('+1', '');
 checkSanitization(' 10', '');
 checkSanitization('10 ', '');
+checkSanitization('0.', '');
+checkSanitization('1.', '');
 checkSanitization('1,2', '');
 checkSanitization('1E', '');
 checkSanitization('NaN', '');
@@ -70,9 +74,7 @@
 // Huge exponent.
 checkSanitization('1.2E65535', '');
 
-// The spec doesn't allow, but our implementation does.
-check('1.');
-check('1.2e10');
+checkSanitization('1.2e10', '1.2e10');
 
 // Disabled
 check('invalid', true);
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/menulist-remove-option-onchange.html b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-remove-option-onchange.html
new file mode 100644
index 0000000..d10dff1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-remove-option-onchange.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<select id="select1">
+<option value="">Placeholder</option>
+<option>a</option>
+<option>b</option>
+<option>c</option>
+</select>
+<script>
+var select = document.querySelector('select');
+var placeholderOption = document.querySelector('option');
+var selectedValue;
+select.focus();
+select.addEventListener('change', function() {
+    selectedValue = select.value;
+    if (placeholderOption.parentNode == select)
+        select.removeChild(placeholderOption);
+});
+test(function() {
+    eventSender.keyDown('a');
+    assert_equals(selectedValue, 'a');
+    assert_equals(placeholderOption.parentNode, null);
+    internals.resetTypeAheadSession(select);
+
+    eventSender.keyDown('b');
+    assert_equals(select.value, 'b');
+    assert_equals(selectedValue, 'b');
+    internals.resetTypeAheadSession(select);
+
+    eventSender.keyDown('c');
+    assert_equals(selectedValue, 'c');
+}, 'Change event should be dispatched after the option removal.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.jpg b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.jpg
new file mode 100644
index 0000000..4df68d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.jpg
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.png b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.png
new file mode 100644
index 0000000..7cdaa96a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.webp b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.webp
new file mode 100644
index 0000000..21f1e19
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/resources/blue-wheel-srgb-color-profile.webp
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-adobe-color-profile.png b/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-adobe-color-profile.png
new file mode 100644
index 0000000..5fe9020e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/resources/color-checker-adobe-color-profile.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src-expected.txt b/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src-expected.txt
new file mode 100644
index 0000000..436f57df
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src-expected.txt
@@ -0,0 +1,3 @@
+
+PASS
+crbug.com/522673: Return the correct width for images with broken data: uri's.
diff --git a/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src.html b/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src.html
new file mode 100644
index 0000000..9c78289
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/images/width-on-broken-data-src.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<img src="data:dsa" data-expected-width=20>
+<script src="../../resources/check-layout.js"></script>
+<p>crbug.com/522673: Return the correct width for images with broken data: uri's.</p>
+<script>
+    checkLayout("img");
+</script>
+
+
diff --git a/third_party/WebKit/LayoutTests/fast/js/constructor-length-expected.txt b/third_party/WebKit/LayoutTests/fast/js/constructor-length-expected.txt
index 8ca3765a..bb9f61b4 100644
--- a/third_party/WebKit/LayoutTests/fast/js/constructor-length-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/js/constructor-length-expected.txt
@@ -8,7 +8,7 @@
 PASS AutocompleteErrorEvent.length is 1
 PASS Blob.length is 0
 PASS CloseEvent.length is 1
-PASS CustomEvent.length is 1
+FAIL CustomEvent.length should be 1. Was 0.
 FAIL DOMFormData.length should be 0. Threw exception ReferenceError: DOMFormData is not defined
 PASS DOMParser.length is 0
 PASS DataView.length is 3
diff --git a/third_party/WebKit/LayoutTests/fast/js/constructor-length.html b/third_party/WebKit/LayoutTests/fast/js/constructor-length.html
index 56f1c99..f82f4ca2 100644
--- a/third_party/WebKit/LayoutTests/fast/js/constructor-length.html
+++ b/third_party/WebKit/LayoutTests/fast/js/constructor-length.html
@@ -12,6 +12,8 @@
 shouldBe('AutocompleteErrorEvent.length', '1');
 shouldBe('Blob.length', '0');
 shouldBe('CloseEvent.length', '1');
+// TODO(bashi): CustomEvent.length == 0 since it uses custom constructor.
+// Fix this regression once http://crbug.com/529941 is fixed.
 shouldBe('CustomEvent.length', '1');
 shouldBe('DOMFormData.length', '0');
 shouldBe('DOMParser.length', '0');
diff --git a/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-expected.txt b/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-expected.txt
index e135a7c..c03e6d3 100644
--- a/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-expected.txt
@@ -1,30 +1,30 @@
 The symbol in row foo and column bar shows whether <p><bar><foo> is allowed (+) or closes the <p> before opening <foo> (-).
 
-Leaf		a	b	big	em	i	s	small	strike	strong	tt	u	abbr	acronym	bdo	cite	code	dfn	kbd	q	samp	sub	sup	var	font	nobr	button	object	span	del	ins	marquee
-address	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-blockquote	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-center	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dir	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-div	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dl	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-fieldset	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h1	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h2	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h3	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h4	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h5	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h6	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-menu	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-ol	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-p	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-ul	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-pre	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-listing	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-form	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-hr	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-li	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dd	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dt	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-plaintext	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-table	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+
+Leaf		a	b	big	em	i	s	small	strike	strong	tt	u	abbr	acronym	bdo	cite	code	dfn	kbd	q	samp	sub	sup	var	font	nobr	button	applet	object	span	del	ins	marquee
+address	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+blockquote	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+center	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dir	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+div	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dl	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+fieldset	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h1	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h2	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h3	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h4	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h5	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h6	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+menu	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+ol	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+p	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+ul	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+pre	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+listing	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+form	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+hr	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+li	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dd	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dt	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+plaintext	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+table	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+	+
 
diff --git a/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-strict-expected.txt b/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-strict-expected.txt
index a246249b..a08c3cc 100644
--- a/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-strict-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/parser/p-in-scope-strict-expected.txt
@@ -1,30 +1,30 @@
 The symbol in row foo and column bar shows whether <p><bar><foo> is allowed (+) or closes the <p> before opening <foo> (-).
 
-Leaf		a	b	big	em	i	s	small	strike	strong	tt	u	abbr	acronym	bdo	cite	code	dfn	kbd	q	samp	sub	sup	var	font	nobr	button	object	span	del	ins	marquee
-address	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-blockquote	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-center	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dir	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-div	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dl	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-fieldset	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h1	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h2	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h3	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h4	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h5	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-h6	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-menu	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-ol	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-p	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-ul	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-pre	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-listing	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-form	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-hr	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-li	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dd	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-dt	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-plaintext	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
-table	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	-	-	-	+
+Leaf		a	b	big	em	i	s	small	strike	strong	tt	u	abbr	acronym	bdo	cite	code	dfn	kbd	q	samp	sub	sup	var	font	nobr	button	applet	object	span	del	ins	marquee
+address	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+blockquote	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+center	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dir	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+div	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dl	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+fieldset	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h1	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h2	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h3	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h4	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h5	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+h6	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+menu	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+ol	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+p	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+ul	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+pre	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+listing	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+form	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+hr	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+li	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dd	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+dt	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+plaintext	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
+table	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	-	+	+	+	-	-	-	+
 
diff --git a/third_party/WebKit/LayoutTests/fast/parser/resources/p-in-scope.js b/third_party/WebKit/LayoutTests/fast/parser/resources/p-in-scope.js
index 9f61c55..76ce22a 100644
--- a/third_party/WebKit/LayoutTests/fast/parser/resources/p-in-scope.js
+++ b/third_party/WebKit/LayoutTests/fast/parser/resources/p-in-scope.js
@@ -102,6 +102,7 @@
 
     "button",       // scoping
 
+    "applet",       // scoping
     "object",       // scoping
 
     "span",         // phrasing
diff --git a/third_party/WebKit/LayoutTests/fast/parser/resources/set-parent-to-javascript-url.html b/third_party/WebKit/LayoutTests/fast/parser/resources/set-parent-to-javascript-url.html
index a64b9a0..cae7ee69 100644
--- a/third_party/WebKit/LayoutTests/fast/parser/resources/set-parent-to-javascript-url.html
+++ b/third_party/WebKit/LayoutTests/fast/parser/resources/set-parent-to-javascript-url.html
@@ -1,6 +1,8 @@
 <script>
+// Capture window.parent: once this context navigates, window.parent always returns null.
+var p = parent;
 alert(1);
 parent.document.getElementsByTagName('iframe')[0].src = "javascript:alert(2),'PASS<script>alert(3)<\/script>'";
 alert(4);
-parent.setTimeout("done()", 0);
+p.setTimeout("done()", 0);
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change-expected.txt b/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change-expected.txt
new file mode 100644
index 0000000..4cc1009f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change-expected.txt
@@ -0,0 +1,18 @@
+{
+  "bounds": [800, 600],
+  "children": [
+    {
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "drawsContent": true,
+      "repaintRects": [
+        [8, 120, 100, 300],
+        [8, 120, 100, 100]
+      ],
+      "paintInvalidationClients": [
+        "LayoutBlockFlow DIV id='content'"
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change.html b/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change.html
new file mode 100644
index 0000000..c0ebee0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/repaint/clip-unclip-and-change.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script src="resources/text-based-repaint.js"></script>
+<script>
+function repaintTest() {
+  content.style.height = '100px';
+  content.style.backgroundColor = 'green';
+}
+onload = function() {
+  runAfterLayoutAndPaint(function() {
+    container.style.height = '400px';
+    runRepaintTest();
+  });
+};
+</script>
+Tests paint invalidation of previous location of an element which was clipped to be invisible initially, becme visible because of clip change, then changed color and size. Passes if there is a green square.
+<div id="container" style="position: absolute; top: 100px; width: 100px; height: 10px; overflow: hidden">
+  <div style="height: 20px"></div>
+  <div style="width: 100px; height: 300px">
+    <div id="content" style="width: 100px; height: 300px; background-color: red"></div>
+  </div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
index 8dc69a1..445c66f 100644
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
+++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
@@ -140,11 +140,11 @@
       // c applies the first two scrolls, and then hits its scroll extents.
       [0, 0, -65, -55, -45],
       // b doesn't scroll, and so leaves the same deltas unapplied as c.
-      [0, 0, -65, -55, -45],
+      [-65, -55, -45],
       // a hits its scroll extent on the second last step.
-      [0, 0, 0, 0, -45],
+      [0, 0, -45],
       // The scrollingElement performs the frame scroll.
-      [0, 0, 0, 0, 0]];
+      [0]];
 
     for (var i = 0; i < deltas.length; ++i)
       applyDelta(deltas[i]);
@@ -167,28 +167,17 @@
   test(function() {
     reset();
 
-    // Consume one pixel of delta per call to applyScroll.
-    for (var i = 0; i < elements.length; ++i) {
-      if (scrollableElements.indexOf(elements[i]) == -1)
-        continue;
-      elements[i].setApplyScroll((function(scrollState) {
-        if (scrollState.deltaY !== 0)
-          scrollState.consumeDelta(0, -1);
-      }).bind(elements[i]), "perform-before-native-scroll");
-    }
-
     // Scroll five times, with three scrollable elements.
-    // The scroll distance is decreased more the higher up the scroll chain the element is.
-    var cScrollTop = [85 - 1, 100, 100, 100, 100];
-    var aScrollTop = [0, 0, 65 - 2, 100, 100];
-    var scrollingElementScrollTop = [0, 0, 0, 0, 45 - 3];
+    var cScrollTop = [85, 100, 100, 100, 100];
+    var aScrollTop = [0, 0, 65, 100, 100];
+    var scrollingElementScrollTop = [0, 0, 0, 0, 45];
     for (var i = 0; i < deltas.length; ++i) {
       applyDelta(deltas[i]);
       assert_equals(c.scrollTop, cScrollTop[i], "For id 'c' on step " + i);
       assert_equals(a.scrollTop, aScrollTop[i], "For id 'a' on step " + i);
       assert_equals(document.scrollingElement.scrollTop, scrollingElementScrollTop[i], "For scrollingElement on step " + i);
     }
-  }, "Consuming deltas prevents scrolling.");
+  }, "Scroll propagation behaves correctly.");
 
   test(function() {
     reset();
diff --git a/third_party/WebKit/LayoutTests/fast/text/selection-painting-hidpi.html b/third_party/WebKit/LayoutTests/fast/text/selection-painting-hidpi.html
new file mode 100644
index 0000000..7074c92
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/selection-painting-hidpi.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Selection painting test</title>
+        <style>
+            div {
+                margin: 0;
+                padding: 0;
+                display: inline-block;
+            }
+        </style>
+    </head>
+    <body>
+        <div>
+            <span>There</span> <span>should</span> <span>be</span>
+            <span>no</span> <span>white</span> <span>gaps</span>
+            <span>between</span> <span>words</span>.
+        </div>
+        <script>
+            window.getSelection().selectAllChildren(document.body.firstElementChild);
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash-expected.txt
new file mode 100644
index 0000000..98637a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash-expected.txt
@@ -0,0 +1,4 @@
+
+   
+Test passes if no crash.
+
diff --git a/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash.html b/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash.html
new file mode 100644
index 0000000..51dedec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/text/whitespace/justification-expansion-crash.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<style>
+:before { content: ""; }
+body { white-space: pre; }
+</style>
+<ruby>
+   <rt>
+Test passes if no crash.
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-data-expected.txt b/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-data-expected.txt
index 1c1e2c5..7017306 100644
--- a/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-data-expected.txt
+++ b/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-data-expected.txt
@@ -5,7 +5,7 @@
 11
 12
 
-Test 8 of 107 in ../resources/tests19.dat failed. Input:
+Test 8 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><form><isindex>
 Got:
 | <!DOCTYPE html>
@@ -21,7 +21,7 @@
 |   <body>
 |     <form>
 
-Test 9 of 107 in ../resources/tests19.dat failed. Input:
+Test 9 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex action="POST">
 Got:
 | <!DOCTYPE html>
@@ -44,7 +44,7 @@
 |           name="isindex"
 |       <hr>
 
-Test 10 of 107 in ../resources/tests19.dat failed. Input:
+Test 10 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex prompt="this is isindex">
 Got:
 | <!DOCTYPE html>
@@ -66,7 +66,7 @@
 |           name="isindex"
 |       <hr>
 
-Test 11 of 107 in ../resources/tests19.dat failed. Input:
+Test 11 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex type="hidden">
 Got:
 | <!DOCTYPE html>
@@ -89,7 +89,7 @@
 |           type="hidden"
 |       <hr>
 
-Test 12 of 107 in ../resources/tests19.dat failed. Input:
+Test 12 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex name="foo">
 Got:
 | <!DOCTYPE html>
diff --git a/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-write-expected.txt b/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-write-expected.txt
index 1c1e2c5..7017306 100644
--- a/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-write-expected.txt
+++ b/third_party/WebKit/LayoutTests/html5lib/generated/run-tests19-write-expected.txt
@@ -5,7 +5,7 @@
 11
 12
 
-Test 8 of 107 in ../resources/tests19.dat failed. Input:
+Test 8 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><form><isindex>
 Got:
 | <!DOCTYPE html>
@@ -21,7 +21,7 @@
 |   <body>
 |     <form>
 
-Test 9 of 107 in ../resources/tests19.dat failed. Input:
+Test 9 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex action="POST">
 Got:
 | <!DOCTYPE html>
@@ -44,7 +44,7 @@
 |           name="isindex"
 |       <hr>
 
-Test 10 of 107 in ../resources/tests19.dat failed. Input:
+Test 10 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex prompt="this is isindex">
 Got:
 | <!DOCTYPE html>
@@ -66,7 +66,7 @@
 |           name="isindex"
 |       <hr>
 
-Test 11 of 107 in ../resources/tests19.dat failed. Input:
+Test 11 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex type="hidden">
 Got:
 | <!DOCTYPE html>
@@ -89,7 +89,7 @@
 |           type="hidden"
 |       <hr>
 
-Test 12 of 107 in ../resources/tests19.dat failed. Input:
+Test 12 of 108 in ../resources/tests19.dat failed. Input:
 <!doctype html><isindex name="foo">
 Got:
 | <!DOCTYPE html>
diff --git a/third_party/WebKit/LayoutTests/html5lib/resources/tests19.dat b/third_party/WebKit/LayoutTests/html5lib/resources/tests19.dat
index 2f9c364..2470571 100644
--- a/third_party/WebKit/LayoutTests/html5lib/resources/tests19.dat
+++ b/third_party/WebKit/LayoutTests/html5lib/resources/tests19.dat
@@ -683,6 +683,16 @@
 |     <button>
 
 #data
+<!doctype html><applet><frameset>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+|   <head>
+|   <body>
+|     <applet>
+
+#data
 <!doctype html><marquee><frameset>
 #errors
 #document
diff --git a/third_party/WebKit/LayoutTests/html5lib/resources/tests7.dat b/third_party/WebKit/LayoutTests/html5lib/resources/tests7.dat
index 54bc97b..f5193c66 100644
--- a/third_party/WebKit/LayoutTests/html5lib/resources/tests7.dat
+++ b/third_party/WebKit/LayoutTests/html5lib/resources/tests7.dat
@@ -124,7 +124,7 @@
 |         " "
 
 #data
-<!doctype html><p><object type="application/x-non-existant-plugin"><p>X</p></object>
+<!doctype html><p><applet><p>X</p></applet>
 #errors
 #document
 | <!DOCTYPE html>
@@ -132,8 +132,7 @@
 |   <head>
 |   <body>
 |     <p>
-|       <object>
-|         type="application/x-non-existant-plugin"
+|       <applet>
 |         <p>
 |           "X"
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
index 38d074e0..1737b837 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -1,3 +1,8 @@
+function scheduleTestFunction()
+{
+    setTimeout(testFunction, 0);
+}
+
 var initialize_DebuggerTest = function() {
 
 InspectorTest.preloadPanel("sources");
@@ -71,7 +76,7 @@
 
 InspectorTest.runTestFunction = function()
 {
-    InspectorTest.evaluateInPage("setTimeout(testFunction, 0)");
+    InspectorTest.evaluateInPage("scheduleTestFunction()");
     InspectorTest.addResult("Set timer for test function.");
 };
 
@@ -271,6 +276,12 @@
             results.push(s);
             if (options.printReturnValue && frame.returnValue())
                 results.push("       <return>: " + frame.returnValue().description);
+            if (frame.functionName === "scheduleTestFunction") {
+                var remainingFrames = callFrames.length - 1 - i;
+                if (remainingFrames)
+                    results.push("    <... skipped remaining frames ...>");
+                break;
+            }
         }
         return printed;
     }
@@ -284,8 +295,6 @@
         var printed = printCallFrames(WebInspector.DebuggerModel.CallFrame.fromPayloadArray(debuggerModel, asyncStackTrace.callFrames));
         if (!printed)
             results.pop();
-        if (asyncStackTrace.callFrames.peekLast().functionName === "testFunction")
-            break;
         asyncStackTrace = asyncStackTrace.asyncStackTrace;
     }
     return results.join("\n");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/edit-css-with-source-url.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/edit-css-with-source-url.html
index 5b7ccb7..6bda7f5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/edit-css-with-source-url.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/edit-css-with-source-url.html
@@ -33,13 +33,18 @@
             InspectorTest.addResult("Adding file system.");
             var fs = new InspectorTest.TestFileSystem(fileSystemPath);
             fs.root.addFile("foo.css", "#inspected {\n    color: red;\n}\n");
-            fs.reportCreated();
+            fs.reportCreated(fileSystemCreated);
 
-            InspectorTest.addResult("Adding file system mapping.");
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            WebInspector.fileSystemMapping.addFileMapping(fileSystemPath, "http://localhost:8000/inspector/elements/styles/", "/");
-            var uiSourceCode = WebInspector.workspace.uiSourceCode(fileSystemProjectId, "foo.css");
-            InspectorTest.showUISourceCode(uiSourceCode, didShowScriptSource);
+            var uiSourceCode;
+
+            function fileSystemCreated()
+            {
+                InspectorTest.addResult("Adding file system mapping.");
+                var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
+                WebInspector.fileSystemMapping.addFileMapping(fileSystemPath, "http://localhost:8000/inspector/elements/styles/", "/");
+                uiSourceCode = WebInspector.workspace.uiSourceCode(fileSystemProjectId, "foo.css");
+                InspectorTest.showUISourceCode(uiSourceCode, didShowScriptSource);
+            }
 
             function didShowScriptSource(sourceFrame)
             {
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css
new file mode 100644
index 0000000..bec1c33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css
@@ -0,0 +1,5 @@
+a {
+  foo: bar;
+  /* COMMENT */
+  font-size: 12px; }
+/*# sourceMappingURL=update-locations-on-filesystem-scss-load.css.map */
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css.map b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css.map
index 260709a..c055c13a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css.map
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css.map
@@ -1,6 +1,6 @@
 {
 "version": "3",
 "mappings": "AAAA,CAAE;EACA,GAAG,EAAE,GAAG;;EAER,SAAS,EAAE,IAAI",
-"sources": ["update-locations-on-filesystem-scss-load.scss"],
+"sources": ["source/update-locations-on-filesystem-scss-load.scss"],
 "file": "update-locations-on-filesystem-scss-load.css"
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load-expected.txt
index fd6cf2c..1695597 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load-expected.txt
@@ -1,11 +1,9 @@
-Tests that stylesheet LiveLocations are updated when an SCSS file is added from the filesystem.
+Tests that stylesheet LiveLocations are updated when an SCSS file is loaded from the filesystem.
 
-Adding file system.
-Adding stylesheet header.
-Adding network resource.
-LiveLocation updated:
+Creating filesystem with the SCSS file...
+Loading raw css with mapping...
+Stylesheet was added, dumping location:
 http://127.0.0.1:8000/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.css:0:1
-Adding filesystem SCSS.
-LiveLocation updated:
-http://127.0.0.1:8000/inspector/elements/styles/resources/update-locations-on-filesystem-scss-load.scss:0:2
+Source map was bound to the file loaded from filesystem:
+http://127.0.0.1:8000/inspector/elements/styles/resources/source/update-locations-on-filesystem-scss-load.scss:0:2
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
index 5d6e6ec8..ed5a470 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/styles/update-locations-on-filesystem-scss-load.html
@@ -4,53 +4,47 @@
 <script src="../../isolated-filesystem-test.js"></script>
 <script src="../../workspace-test.js"></script>
 <script>
+function loadCSS()
+{
+    var link = document.createElement("link");
+    link.rel = "stylesheet";
+    link.type = "text/css";
+    link.href = "resources/update-locations-on-filesystem-scss-load.css";
+    document.head.appendChild(link);
+}
+
 function test()
 {
-    var target = InspectorTest.createWorkspaceWithTarget();
-    var manager = InspectorTest.createIsolatedFileSystemManager(InspectorTest.testWorkspace);
+    InspectorTest.addResult("Creating filesystem with the SCSS file...");
+    var fs = new InspectorTest.TestFileSystem("/var/www");
+    fs.root.addFile("update-locations-on-filesystem-scss-load.scss", ["a {", "  foo: bar;", "/* COMMENT */", "  font-size: 12px;", "}"].join("\n"));
+    fs.addFileMapping(WebInspector.ParsedURL.completeURL(InspectorTest.resourceTreeModel.inspectedPageURL(), "resources/source/"), "/");
+    fs.reportCreated(fileSystemCreated);
 
-    var fileSystem;
+    function fileSystemCreated()
+    {
+        InspectorTest.addResult("Loading raw css with mapping...");
+        InspectorTest.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, styleSheetAdded);
+        InspectorTest.addSniffer(WebInspector.SASSSourceMapping.prototype, "_bindUISourceCode", afterBind);
+        InspectorTest.evaluateInPage("loadCSS()");
+    }
+
     var liveLocation;
-    var mockStyleSheetId = 1;
-    var fileSystemPath = "/var/www";
-    var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
 
-    function addMockHeader(sourceURL, sourceMapURL)
+    function styleSheetAdded(event)
     {
-        WebInspector.CSSStyleModel.fromTarget(target)._styleSheetAdded({
-            styleSheetId: mockStyleSheetId,
-            frameId: 1000,
-            sourceURL: sourceURL,
-            sourceMapURL: sourceMapURL,
-            origin: "regular",
-            title: "",
-            disabled: false,
-            isInline: false,
-            startLine: 0,
-            startColumn: 0
-        });
+        InspectorTest.addResult("Stylesheet was added, dumping location:");
+        var header = event.data;
+        var cssLocation = new WebInspector.CSSLocation(header.cssModel(), header.id, header.sourceURL, 0, 1);
+        liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(cssLocation, function() {});
+        dumpLiveLocation();
     }
 
-    function uiSourceCodeAdded(uiSourceCode) { }
-
-    function dumpFileSystemUISourceCodesMappings()
+    function afterBind()
     {
-        var uiSourceCodes = InspectorTest.testWorkspace.project(fileSystemProjectId).uiSourceCodes();
-        InspectorTest.addResult("UISourceCode uri to url mappings:");
-        for (var i = 0; i < uiSourceCodes.length; ++i) {
-            var networkURL = InspectorTest.testNetworkMapping.networkURL(uiSourceCodes[i]);
-            InspectorTest.addResult("    " + uiSourceCodes[i].uri() + " -> " + networkURL);
-        }
-    }
-
-    function fileSystemAdded(event)
-    {
-        fileSystem = event.data;
-    }
-
-    function updateDelegate()
-    {
-        InspectorTest.addResult("LiveLocation updated:");
+        InspectorTest.addResult("Source map was bound to the file loaded from filesystem:");
+        dumpLiveLocation();
+        InspectorTest.completeTest();
     }
 
     function dumpLiveLocation()
@@ -60,60 +54,13 @@
             InspectorTest.addResult("Null uiLocation");
             return;
         }
-        var networkURL = InspectorTest.testNetworkMapping.networkURL(uiLocation.uiSourceCode);
+        var networkURL = WebInspector.networkMapping.networkURL(uiLocation.uiSourceCode);
         InspectorTest.addResult(networkURL + ":" + uiLocation.lineNumber + ":" + uiLocation.columnNumber);
     }
-
-    var resourcesURL = WebInspector.ParsedURL.completeURL(InspectorTest.resourceTreeModel.inspectedPageURL(), "resources/");
-    var namePrefix = "update-locations-on-filesystem-scss-load."
-    var cssURL = resourcesURL + namePrefix + "css";
-    var scssURL = resourcesURL + namePrefix + "scss";
-    var cssLocation = new WebInspector.CSSLocation(WebInspector.CSSStyleModel.fromTarget(target), mockStyleSheetId, cssURL, 0, 1);
-    var scssContent =
-        ["a {",
-        "  foo: bar;",
-        "/* COMMENT */",
-        "  font-size: 12px;",
-        "}"].join("\n");
-    var cssContent =
-        ["a {",
-        "  foo: bar;",
-        "  /* COMMENT */",
-        "  font-size: 12px; }"].join("\n");
-
-    var files = {};
-    files["/" + namePrefix + "css"] = cssContent;
-    InspectorTest.waitForWorkspaceUISourceCodeAddedEvent(uiSourceCodeAdded, 4);
-    InspectorTest.addResult("Adding file system.");
-    manager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, fileSystemAdded, this);
-    manager.addMockFileSystem(fileSystemPath);
-    InspectorTest.testFileSystemMapping.addFileMapping(fileSystemPath, resourcesURL, "/");
-    manager.addFiles(fileSystemPath, files);
-
-    InspectorTest.addSniffer(WebInspector.SASSSourceMapping.prototype, "_bindUISourceCode", afterBind);
-
-    InspectorTest.addResult("Adding stylesheet header.");
-    addMockHeader(cssURL, cssURL + ".map");
-    InspectorTest.addResult("Adding network resource.");
-    InspectorTest.addMockUISourceCodeToWorkspace(cssURL, WebInspector.resourceTypes.Stylesheet, cssContent);
-    liveLocation = WebInspector.cssWorkspaceBinding.createLiveLocation(cssLocation, updateDelegate);
-    dumpLiveLocation();
-
-    InspectorTest.addResult("Adding filesystem SCSS.");
-    var scssPath = namePrefix + "scss";
-    fileSystem.setFileContent(scssPath, scssContent, function() {});
-    InspectorTest.addMockUISourceCodeToWorkspace(scssURL, WebInspector.resourceTypes.Stylesheet, scssContent);
-    manager.fileSystemWorkspaceBinding._boundFileSystems.get(fileSystemPath)._addFile(scssPath);
-
-    function afterBind()
-    {
-        dumpLiveLocation();
-        InspectorTest.completeTest();
-    }
 };
 </script>
 </head>
 <body onload="runTest()">
-<p>Tests that stylesheet LiveLocations are updated when an SCSS file is added from the filesystem.</p>
+<p>Tests that stylesheet LiveLocations are updated when an SCSS file is loaded from the filesystem.</p>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/filesystem/async-callstack-filesystem-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/filesystem/async-callstack-filesystem-expected.txt
index 7986f21d0..edbb401 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/filesystem/async-callstack-filesystem-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/filesystem/async-callstack-filesystem-expected.txt
@@ -8,6 +8,9 @@
     0) timeout (async-callstack-filesystem.html:31)
     [setTimeout]
     0) testFunction (async-callstack-filesystem.html:25)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onFileCreated (async-callstack-filesystem.html:51)
@@ -84,5 +87,8 @@
     0) timeout (async-callstack-filesystem.html:31)
     [setTimeout]
     0) testFunction (async-callstack-filesystem.html:25)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
index c890a50..bf21460 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js
@@ -1,191 +1,63 @@
 var initialize_IsolatedFileSystemTest = function() {
 
-InspectorTest.createIsolatedFileSystemManager = function(workspace)
-{
-    var normalizePath = WebInspector.IsolatedFileSystem.normalizePath
-    WebInspector.IsolatedFileSystem = MockIsolatedFileSystem;
-    WebInspector.IsolatedFileSystem.normalizePath = normalizePath;
-
-    var manager = new MockIsolatedFileSystemManager();
-    manager.fileSystemMapping = InspectorTest.testFileSystemMapping;
-    manager.fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(manager, workspace, InspectorTest.testNetworkMapping);
-    return manager;
-}
-
-var MockIsolatedFileSystem = function(manager, path, name, rootURL)
-{
-    MockIsolatedFileSystem._isolatedFileSystemMocks = MockIsolatedFileSystem._isolatedFileSystemMocks || {};
-    MockIsolatedFileSystem._isolatedFileSystemMocks[path] = this;
-    this.originalTimestamp = 1000000;
-    this.modificationTimestampDelta = 1000;
-    this._path = path;
-    this._manager = manager;
-};
-MockIsolatedFileSystem.prototype = {
-    path: function()
-    {
-        return this._path;
-    },
-
-    normalizedPath: function()
-    {
-        return this._path;
-    },
-
-    requestFileContent: function(path, callback)
-    {
-        callback(this._files[path]);
-    },
-
-    requestMetadata: function(path, callback)
-    {
-        if (!(path in this._files)) {
-            callback(null, null);
-            return;
-        }
-        callback(new Date(this._modificationTimestamps[path]), this._files[path].length);
-    },
-
-    setFileContent: function(path, newContent, callback)
-    {
-        this._files[path] = newContent;
-        this._modificationTimestamps[path] = (this._modificationTimestamps[path] || (this.originalTimestamp - this.modifiationTimestampDelta)) + this.modificationTimestampDelta;
-        callback();
-    },
-
-    requestFilesRecursive: function(path, callback)
-    {
-        this._callback = callback;
-        if (!this._files)
-            return;
-        this._innerRequestFilesRecursive();
-    },
-
-    renameFile: function(filePath, newName, callback)
-    {
-        callback(true, newName);
-    },
-
-    _innerRequestFilesRecursive: function()
-    {
-        if (!this._callback)
-            return;
-        var files = Object.keys(this._files);
-        for (var i = 0; i < files.length; ++i) {
-            var isExcluded = false;
-            for (var j = 0; j < files[i].length; ++j) {
-                if (files[i][j] === "/") {
-                    if (InspectorTest.testExcludedFolderManager.isFileExcluded(this._path, files[i].substr(0, j + 1)))
-                        isExcluded = true;
-                }
-            }
-            if (isExcluded)
-                continue;
-            this._callback(files[i].substr(1));
-        }
-        delete this._callback;
-    },
-
-    _addFiles: function(files)
-    {
-        this._files = files;
-        this._modificationTimestamps = {};
-        var files = Object.keys(this._files);
-        for (var i = 0; i < files.length; ++i)
-            this._modificationTimestamps[files[i]] = this.originalTimestamp;
-        this._innerRequestFilesRecursive();
-    }
-}
-
-var MockIsolatedFileSystemManager = function() {};
-MockIsolatedFileSystemManager.prototype = {
-    addMockFileSystem: function(path, skipAddFileSystem)
-    {
-        var fileSystem = new MockIsolatedFileSystem(this, path, "", "");
-        this._fileSystems = this._fileSystems || {};
-        this._fileSystems[path] = fileSystem;
-        if (!skipAddFileSystem)
-            this.fileSystemMapping.addFileSystem(path);
-        this.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, fileSystem);
-    },
-
-    addFiles: function(path, files)
-    {
-        var fileSystem = this._fileSystems[path];
-        fileSystem._addFiles(files);
-    },
-
-    removeFileSystem: function(path)
-    {
-        var fileSystem = this._fileSystems[path];
-        delete this._fileSystems[path];
-        this.fileSystemMapping.removeFileSystem(path);
-        this.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, fileSystem);
-    },
-
-    mapping: function()
-    {
-        return this.fileSystemMapping;
-    },
-
-    excludedFolderManager: function()
-    {
-        return InspectorTest.testExcludedFolderManager;
-    },
-
-    __proto__: WebInspector.Object.prototype
-}
-
-InspectorTest.addMockFileSystem = function(path)
-{
-    var fileSystem = { fileSystemName: "", rootURL: "", fileSystemPath: path };
-    WebInspector.isolatedFileSystemManager._onFileSystemAdded({data: {fileSystem: fileSystem}});
-    return MockIsolatedFileSystem._isolatedFileSystemMocks[path];
-}
-
-InspectorTest.addFilesToMockFileSystem = function(path, files)
-{
-    MockIsolatedFileSystem._isolatedFileSystemMocks[path]._addFiles(files);
-}
-
-InspectorFrontendHost.isolatedFileSystem = function(name, url)
+InspectorFrontendHost.isolatedFileSystem = function(name)
 {
     return InspectorTest.TestFileSystem._instances[name];
 }
 
 InspectorTest.TestFileSystem = function(fileSystemPath)
 {
-    this.root = new InspectorTest.TestFileSystem.Entry("", true);
+    this.root = new InspectorTest.TestFileSystem.Entry("", true, null);
     this.fileSystemPath = fileSystemPath;
 }
 
 InspectorTest.TestFileSystem._instances = {};
 
 InspectorTest.TestFileSystem.prototype = {
-    reportCreated: function()
+    reportCreated: function(callback)
     {
-        WebInspector.isolatedFileSystemManager._loaded = true;
+        var fileSystemPath = this.fileSystemPath;
         InspectorTest.TestFileSystem._instances[this.fileSystemPath] = this;
         InspectorFrontendHost.events.dispatchEventToListeners(InspectorFrontendHostAPI.Events.FileSystemAdded, {
             fileSystem: { fileSystemPath: this.fileSystemPath,
                           fileSystemName: this.fileSystemPath }
         });
+
+        WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, created);
+
+        function created(event)
+        {
+            var fileSystem = event.data;
+            if (fileSystem.path() !== fileSystemPath)
+                return;
+            WebInspector.isolatedFileSystemManager.removeEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, created);
+            callback(fileSystem);
+        }
     },
 
-    removeFileSystem: function()
+    reportRemoved: function()
     {
         delete InspectorTest.TestFileSystem._instances[this.fileSystemPath];
         InspectorFrontendHost.events.dispatchEventToListeners(InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath);
+    },
+
+    addFileMapping: function(urlPrefix, pathPrefix)
+    {
+        var fileSystemMapping = new WebInspector.FileSystemMapping();
+        fileSystemMapping.addFileSystem(this.fileSystemPath);
+        fileSystemMapping.addFileMapping(this.fileSystemPath, urlPrefix, pathPrefix);
+        WebInspector.fileSystemMapping._loadFromSettings();
     }
 }
 
-InspectorTest.TestFileSystem.Entry = function(name, isDirectory)
+InspectorTest.TestFileSystem.Entry = function(name, isDirectory, parent)
 {
     this.name = name;
     this._children = [];
     this._childrenMap = {};
     this.isDirectory = isDirectory;
     this._timestamp = 1000000;
+    this._parent = parent;
 }
 
 InspectorTest.TestFileSystem.Entry.prototype = {
@@ -196,7 +68,7 @@
 
     mkdir: function(name)
     {
-        var child = new InspectorTest.TestFileSystem.Entry(name, true);
+        var child = new InspectorTest.TestFileSystem.Entry(name, true, this);
         this._childrenMap[name] = child;
         this._children.push(child);
         child.parent = this;
@@ -205,7 +77,7 @@
 
     addFile: function(name, content)
     {
-        var child = new InspectorTest.TestFileSystem.Entry(name, false);
+        var child = new InspectorTest.TestFileSystem.Entry(name, false, this);
         this._childrenMap[name] = child;
         this._children.push(child);
         child.parent = this;
@@ -227,17 +99,17 @@
         callback(this.content);
     },
 
-    getDirectory: function(path, noop, callback)
+    getDirectory: function(path, noop, callback, errorCallback)
     {
-        this.getEntry(path, noop, callback);
+        this.getEntry(path, noop, callback, errorCallback);
     },
 
-    getFile: function(path, noop, callback)
+    getFile: function(path, noop, callback, errorCallback)
     {
-        this.getEntry(path, noop, callback);
+        this.getEntry(path, noop, callback, errorCallback);
     },
 
-    getEntry: function(path, noop, callback)
+    getEntry: function(path, noop, callback, errorCallback)
     {
         if (path.startsWith("/"))
             path = path.substring(1);
@@ -248,7 +120,7 @@
         var entry = this;
         for (var token of path.split("/"))
             entry = entry._childrenMap[token];
-        callback(entry);
+        entry ? callback(entry) : errorCallback({ code: FileError.NOT_FOUND_ERR});
     },
 
     getMetadata: function(success, failure)
@@ -258,6 +130,20 @@
             size: this.isDirectory ? 0 : this.content.size
         });
     },
+
+    moveTo: function(parent, newName, callback, errorCallback)
+    {
+        this._parent._children.remove(this);
+        this._parent = parent;
+        this._parent._children.push(this);
+        this.name = newName;
+        callback(this);
+    },
+
+    getParent: function(callback, errorCallback)
+    {
+        callback(this._parent);
+    }
 }
 
 InspectorTest.TestFileSystem.Reader = function(children)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-in-files.html b/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-in-files.html
index 7f7b41e..b6e41f5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-in-files.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-in-files.html
@@ -30,9 +30,13 @@
     function onAllResourcesLoaded()
     {
         WebInspector.inspectorView.showViewInDrawer("search");
-        fs.reportCreated();
-        InspectorTest.addResult("Total uiSourceCodes: " + WebInspector.workspace.uiSourceCodes().length);
-        InspectorTest.runTestSuite(testSuite);
+        fs.reportCreated(fileSystemCreated);
+
+        function fileSystemCreated()
+        {
+            InspectorTest.addResult("Total uiSourceCodes: " + WebInspector.workspace.uiSourceCodes().length);
+            InspectorTest.runTestSuite(testSuite);
+        }
     }
 
     function populateFileSystem(name)
@@ -53,7 +57,7 @@
             var paths = [];
             for (var i = 0; i < names.length; ++i)
                 paths.push("/var/www/" + names[i]);
-            WebInspector.fileSystemWorkspaceBinding._onSearchCompleted({data: {requestId: requestId, fileSystemPath: path, files: paths}});
+            WebInspector.networkMapping._fileSystemWorkspaceBinding._onSearchCompleted({data: {requestId: requestId, fileSystemPath: path, files: paths}});
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-many-projects.html b/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-many-projects.html
index 56ff495..253f0b6 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-many-projects.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/search/sources-search-scope-many-projects.html
@@ -34,7 +34,11 @@
     {
         for (var resourceName in resources)
             fs.root.addFile(resourceName, resources[resourceName]);
-        fs.reportCreated();
+        fs.reportCreated(fileSystemCreated);
+    }
+
+    function fileSystemCreated()
+    {
         WebInspector.inspectorView.showViewInDrawer("search");
 
         var uiSourceCodes = InspectorTest.fileSystemUISourceCodes();
@@ -76,7 +80,7 @@
             var paths = [];
             for (var i = 0; i < names.length; ++i)
                 paths.push("/var/www/" + names[i]);
-            WebInspector.fileSystemWorkspaceBinding._onSearchCompleted({data: {requestId: requestId, fileSystemPath: path, files: paths}});
+            WebInspector.networkMapping._fileSystemWorkspaceBinding._onSearchCompleted({data: {requestId: requestId, fileSystemPath: path, files: paths}});
         }
     }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
index 1e6f041..b9b6468e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
@@ -2,15 +2,14 @@
 
 InspectorTest.createWorkspace = function(ignoreEvents)
 {
-    WebInspector.settings.createSetting("fileSystemMapping", {}).set({});
-    InspectorTest.testFileSystemMapping = new WebInspector.FileSystemMapping();
-    InspectorTest.testExcludedFolderManager = new WebInspector.ExcludedFolderManager();
-    InspectorTest.testFileSystemMapping._fileSystemMappingSetting = new InspectorTest.MockSetting({});
-    InspectorTest.testFileSystemMapping._excludedFoldersSetting = new InspectorTest.MockSetting({});
+    if (InspectorTest.testFileSystemWorkspaceBinding)
+        InspectorTest.testFileSystemWorkspaceBinding.dispose();
+    WebInspector.fileSystemMapping.resetForTesting();
 
     InspectorTest.testTargetManager = new WebInspector.TargetManager();
-    InspectorTest.testWorkspace = new WebInspector.Workspace(InspectorTest.testFileSystemMapping);
-    InspectorTest.testNetworkMapping = new WebInspector.NetworkMapping(InspectorTest.testWorkspace, WebInspector.fileSystemWorkspaceBinding, InspectorTest.testFileSystemMapping);
+    InspectorTest.testWorkspace = new WebInspector.Workspace();
+    InspectorTest.testFileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, InspectorTest.testWorkspace);
+    InspectorTest.testNetworkMapping = new WebInspector.NetworkMapping(InspectorTest.testWorkspace, InspectorTest.testFileSystemWorkspaceBinding, WebInspector.fileSystemMapping);
     InspectorTest.testNetworkProjectManager = new WebInspector.NetworkProjectManager(InspectorTest.testTargetManager, InspectorTest.testWorkspace, InspectorTest.testNetworkMapping);
     InspectorTest.testDebuggerWorkspaceBinding = new WebInspector.DebuggerWorkspaceBinding(InspectorTest.testTargetManager, InspectorTest.testWorkspace, InspectorTest.testNetworkMapping);
     InspectorTest.testCSSWorkspaceBinding = new WebInspector.CSSWorkspaceBinding(InspectorTest.testTargetManager, InspectorTest.testWorkspace, InspectorTest.testNetworkMapping);
@@ -111,6 +110,12 @@
     InspectorTest.testNetworkProject.addFileForURL(url, mockContentProvider);
 }
 
+InspectorTest.addMockUISourceCodeViaNetwork = function(url, type, content)
+{
+    var mockContentProvider = new WebInspector.StaticContentProvider(type, content);
+    InspectorTest.testNetworkProject._addFile(url, mockContentProvider);
+}
+
 InspectorTest._defaultWorkspaceEventHandler = function(event)
 {
     var uiSourceCode = event.data;
diff --git a/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html b/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html
index 72e98d4e..06ae806 100644
--- a/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html
+++ b/third_party/WebKit/LayoutTests/http/tests/push_messaging/subscribe-encryption-public-key.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
     <head>
-        <title>Subscribing should provide a Curve25519 ECDH public key.</title>
+        <title>Subscribing should provide a P-256 ECDH public key.</title>
         <link rel="manifest" href="resources/push_manifest.json">
         <script src="../resources/testharness.js"></script>
         <script src="../resources/testharnessreport.js"></script>
@@ -16,14 +16,14 @@
             }
 
             // When running this test manually, grant permission when prompted.
-            // This test verifies that push subscriptions get an ECDH Curve25519
-            // key that can be used on the application server to encrypt payloads.
+            // This test verifies that push subscriptions get an ECDH P-256 key
+            // that can be used on the application server to encrypt payloads.
             async_test(function(test) {
                 var workerUrl = 'resources/empty_worker.js';
                 var workerScope = 'resources/scope/' + location.pathname;
                 var swRegistration, encryptionKey;
 
-                // Size of an ECDH curve25519 public key, in bytes.
+                // Size of an ECDH p256 public key, in bytes.
                 var EXPECTED_KEY_LENGTH = 32;
 
                 service_worker_unregister_and_register(test, workerUrl, workerScope)
@@ -39,27 +39,27 @@
                     })
                     .then(function(pushSubscription) {
                         assert_own_property(PushSubscription.prototype, 'getKey');
-                        assert_not_equals(pushSubscription.getKey('curve25519dh'), null);
-                        assert_equals(pushSubscription.getKey('curve25519dh').byteLength, EXPECTED_KEY_LENGTH);
+                        assert_not_equals(pushSubscription.getKey('p256dh'), null);
+                        assert_equals(pushSubscription.getKey('p256dh').byteLength, EXPECTED_KEY_LENGTH);
 
                         // The returned ArrayBuffers are expected to be the same.
-                        assert_equals(pushSubscription.getKey('curve25519dh'), pushSubscription.getKey('curve25519dh'));
+                        assert_equals(pushSubscription.getKey('p256dh'), pushSubscription.getKey('p256dh'));
 
                         // Getting a key with an unsupported algorithm should throw an exception.
                         assert_throws(TypeError(), () => pushSubscription.getKey('petercurve9001'));
 
-                        encryptionKey = SerializeArrayBuffer(pushSubscription.getKey('curve25519dh'));
+                        encryptionKey = SerializeArrayBuffer(pushSubscription.getKey('p256dh'));
 
                         return swRegistration.pushManager.getSubscription();
                     })
                     .then(function(pushSubscription) {
-                        assert_equals(SerializeArrayBuffer(pushSubscription.getKey('curve25519dh')), encryptionKey);
+                        assert_equals(SerializeArrayBuffer(pushSubscription.getKey('p256dh')), encryptionKey);
 
                         return service_worker_unregister_and_done(test, workerScope);
                     })
                     .catch(unreached_rejection(test));
 
-            }, 'Subscribing should provide a Curve25519 ECDH public key');
+            }, 'Subscribing should provide a P-256 ECDH public key');
         </script>
     </body>
 </html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/resources/get-host-info.js b/third_party/WebKit/LayoutTests/http/tests/resources/get-host-info.js
index 2bc2af2..a7d31d7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/resources/get-host-info.js
+++ b/third_party/WebKit/LayoutTests/http/tests/resources/get-host-info.js
@@ -1,7 +1,8 @@
 function get_host_info() {
   var ORIGINAL_HOST = '127.0.0.1';
   var REMOTE_HOST = 'localhost';
-  var UNAUTHENTICATED_HOST = 'example.test';
+  // TODO(mkwst): This should be a host that WPT supports. I don't know why we're using 'example.test'.
+  var OTHER_HOST = 'example.test';
   var HTTP_PORT = 8000;
   var HTTPS_PORT = 8443;
   try {
@@ -19,6 +20,7 @@
     HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
     HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
     HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
-    UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
+    UNAUTHENTICATED_ORIGIN: 'http://' + OTHER_HOST + ':' + HTTP_PORT,
+    AUTHENTICATED_ORIGIN: 'https://' + OTHER_HOST + ':' + HTTPS_PORT
   };
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html
index d8d38784..ed94e48 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html
@@ -1,6 +1,7 @@
 <script>
+var f = window.frames;
 function go() {
-    window.frames[0].location = "http://127.0.0.1:8000/security/frameNavigation/resources/fail.html";
+    f[0].location = "http://127.0.0.1:8000/security/frameNavigation/resources/fail.html";
 }
 opener.postMessage("ready", "*");
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/resources/xss-eval2.html b/third_party/WebKit/LayoutTests/http/tests/security/resources/xss-eval2.html
index 462cd58..33253cb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/resources/xss-eval2.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/resources/xss-eval2.html
@@ -3,9 +3,15 @@
 
 parent.childEval = eval;
 
-parent.childEvalCaller = function(s) {
-    return window.eval(s);
-}
+parent.childEvalCaller = (function()
+{
+    // Capture window.window into a variable, since this property always returns null once
+    // the context is navigated.
+    var w = window;
+    return function(s) {
+        return w.eval(s);
+    }
+})();
 
 parent.childLocalEvalCaller = (function()
 {
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/127.0.0.1.html b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/127.0.0.1.html
new file mode 100644
index 0000000..bd9f8517
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/127.0.0.1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>127.0.0.1 is secure</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharness-helpers.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/resources/get-host-info.js"></script>
+</head>
+<body>
+    <script>
+        test(function () {
+            assert_equals(document.location.hostname, "127.0.0.1", "Sanity check the test runner.");
+            assert_true(window.isSecureContext);
+        }, "127.0.0.1 is secure.");
+    </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/authenticated.html b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/authenticated.html
new file mode 100644
index 0000000..b88da392
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/authenticated.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Authenticated origins are secure, both at top-level and in frames.</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/resources/get-host-info.js"></script>
+</head>
+<body>
+    <script>
+        if (window.location.origin != get_host_info().AUTHENTICATED_ORIGIN) {
+            window.location = get_host_info().AUTHENTICATED_ORIGIN +
+                              window.location.pathname;
+        } else {
+            test(function () {
+                assert_equals(window.location.origin, get_host_info().AUTHENTICATED_ORIGIN, "Sanity check the test runner.");
+                assert_true(window.isSecureContext);
+            }, "authenticated origin is secure at the top-level.");
+
+            async_test(function (t) {
+                var messages = 0;
+                window.addEventListener("message", t.step_func(function (e) {
+                    if (e.origin == get_host_info().AUTHENTICATED_ORIGIN)
+                        assert_true(e.data.isSecureContext);
+                    if (e.origin == get_host_info().UNAUTHENTICATED_ORIGIN)
+                        assert_false(e.data.isSecureContext);
+                    messages++;
+                    if (messages >= 2)
+                        t.done();
+                }), false);
+
+                var i1 = document.createElement("iframe");
+                i1.src = get_host_info().UNAUTHENTICATED_ORIGIN + "/security/secureContexts/resources/post-securecontext-status.html";
+                // This will almost certainly be blocked by the mixed content checker, handle that case by incrementing the `messages` count.
+                i1.addEventListener("error", t.step_func(function (e) {
+                    messages++;
+                    if (messages >= 2)
+                        t.done();
+                }), false);
+                document.body.appendChild(i1);
+
+                var i2 = document.createElement("iframe");
+                i2.src = get_host_info().AUTHENTICATED_ORIGIN + "/security/secureContexts/resources/post-securecontext-status.html";
+                document.body.appendChild(i2);
+            }, "Frames are either secure or insecure (and blocked by mixed content).");
+        }
+    </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/localhost.html b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/localhost.html
new file mode 100644
index 0000000..c49a9ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/localhost.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Locahost is secure</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharness-helpers.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/resources/get-host-info.js"></script>
+</head>
+<body>
+    <script>
+        if (window.location.origin != get_host_info().HTTP_REMOTE_ORIGIN) {
+            window.location = get_host_info().HTTP_REMOTE_ORIGIN +
+                              window.location.pathname;
+        } else {
+            test(function () {
+                assert_equals(document.location.hostname, "localhost", "Sanity check the test runner.");
+                assert_true(window.isSecureContext);
+            }, "localhost is secure.");
+        }
+    </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/resources/post-securecontext-status.html b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/resources/post-securecontext-status.html
new file mode 100644
index 0000000..8ce225c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/resources/post-securecontext-status.html
@@ -0,0 +1,6 @@
+<script>
+    ["top", "parent", "opener"].forEach(function (x) {
+        if (window[x] && window[x] != window)
+            window[x].postMessage({ "isSecureContext": window.isSecureContext }, "*");
+    });
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/unauthenticated.html b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/unauthenticated.html
new file mode 100644
index 0000000..aa9bb05
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/secureContexts/unauthenticated.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Unauthenticated origin is insecure</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharness-helpers.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/resources/get-host-info.js"></script>
+</head>
+<body>
+    <script>
+        if (window.location.origin != get_host_info().UNAUTHENTICATED_ORIGIN) {
+            window.location = get_host_info().UNAUTHENTICATED_ORIGIN +
+                              window.location.pathname;
+        } else {
+            test(function () {
+                assert_equals(window.location.origin, get_host_info().UNAUTHENTICATED_ORIGIN, "Sanity check the test runner.");
+                assert_false(window.isSecureContext);
+            }, "unauthenticated origin is insecure.");
+
+            async_test(function (t) {
+                var messages = 0;
+                window.addEventListener("message", t.step_func(function (e) {
+                    assert_false(e.data.isSecureContext);
+                    messages++;
+                    if (messages >= 2)
+                        t.done();
+                }), false);
+
+                var i1 = document.createElement("iframe");
+                i1.src = get_host_info().UNAUTHENTICATED_ORIGIN + "/security/secureContexts/resources/post-securecontext-status.html";
+                document.body.appendChild(i1);
+
+                var i2 = document.createElement("iframe");
+                i2.src = get_host_info().AUTHENTICATED_ORIGIN + "/security/secureContexts/resources/post-securecontext-status.html";
+                document.body.appendChild(i2);
+            }, "Frames are insecure");
+        }
+    </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
deleted file mode 100644
index 7225bb9..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!doctype html>
-<title>NOT invoking resource selection by inserting document fragment into a document</title>
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<div id=log></div>
-<script>
-var v;
-var t = async_test(function(t) {
-  v = document.createElement('video');
-  var fragment = document.createDocumentFragment();
-  fragment.appendChild(v);
-  assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after fragment.appendChild(v)');
-  document.body.appendChild(fragment);
-  assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(fragment)');
-});
-</script>
-<script>
-t.step(function() {
-  assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
-  t.done();
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
deleted file mode 100644
index 335a78ef..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!doctype html>
-<title>NOT invoking resource selection by inserting parent into a document</title>
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<div id=log></div>
-<script>
-async_test(function(t) {
-  var v = document.createElement('video');
-  var div = document.createElement('div');
-  div.appendChild(v);
-  assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after div.appendChild(v)');
-  document.body.appendChild(div);
-  assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(div)');
-  window.onload = t.step_func(function() {
-    assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in window.onload');
-    t.done();
-  });
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
deleted file mode 100644
index f8902bb8..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!doctype html>
-<title>invoking resource selection by inserting &lt;source> in video not in a document</title>
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<div id=log></div>
-<script>
-async_test(function(t) {
-  var v = document.createElement('video');
-  v.onloadstart = t.step_func(function() { t.done(); });
-  v.appendChild(document.createElement('source'));
-  window.onload = t.step_func(function() { assert_unreached(); });
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
deleted file mode 100644
index 361315413..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!doctype html>
-<title>NOT invoking resource selection with implicit pause() when networkState is not NETWORK_EMPTY</title>
-<script src="../../../../../../../resources/testharness.js"></script>
-<script src="../../../../../../../resources/testharnessreport.js"></script>
-<div id=log></div>
-<video></video>
-<script>
-var v;
-var t = async_test(function(t) {
-  v = document.querySelector('video');
-  v.src = 'data:,';
-  document.body.appendChild(v);
-  assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
-  var errorCount = 0;
-  v.onerror = t.step_func(function() {
-    errorCount++;
-    if (errorCount == 1) {
-      assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onerror');
-      document.body.removeChild(v); // invokes pause() which should not invoke RSA. if it does, error will be fired again.
-    } else {
-      assert_unreached();
-    }
-  });
-  onload = t.step_func(function() {
-    assert_equals(errorCount, 1, 'errorCount');
-    t.done();
-  });
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-input-element/number-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-input-element/number-expected.txt
index 9421b6c9..ab7b71b6 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-input-element/number-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/semantics/forms/the-input-element/number-expected.txt
@@ -15,7 +15,7 @@
 PASS Value <= max attribute 
 PASS Value > max attribute 
 PASS value with a leading '.' 
-FAIL value ending with '.' assert_equals: expected "" but got "1."
+PASS value ending with '.' 
 PASS value = -0 
 PASS  value = Infinity 
 PASS value = -Infinity 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests19-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests19-expected.txt
index 96512b2..764ae6a 100644
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests19-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests19-expected.txt
@@ -57,7 +57,7 @@
 PASS html5lib_tests19.html 511bf4bae15c8119042e5e80b5358b70e7da26c1 
 PASS html5lib_tests19.html c51ee24ef9d92206318cc5bbba784630cd10e531 
 PASS html5lib_tests19.html 819d39ae49fd04f0dfce90ac8ed2f8e423bb9329 
-FAIL html5lib_tests19.html ef6bdf5b3ba9d41d6c1c08ede60c2e7fb21c6d71 assert_equals: expected "#document\n| <!DOCTYPE html>\n| <html>\n|   <head>\n|   <body>\n|     <applet>" but got "#document\n| <!DOCTYPE html>\n| <html>\n|   <head>\n|   <frameset>"
+PASS html5lib_tests19.html ef6bdf5b3ba9d41d6c1c08ede60c2e7fb21c6d71 
 PASS html5lib_tests19.html 6bf9c038255c31f20d8fbeaebdf3609eb3c9ed75 
 PASS html5lib_tests19.html 08983ab2a54f61b09a1df134cdaf51d321f3ef32 
 PASS html5lib_tests19.html 2ef94ed028fa71b70540cf41f0884ae0c1cf8077 
diff --git a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests7-expected.txt b/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests7-expected.txt
deleted file mode 100644
index 5199823..0000000
--- a/third_party/WebKit/LayoutTests/imported/web-platform-tests/html/syntax/parsing/html5lib_tests7-expected.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-CONSOLE ERROR: line 1: Uncaught SyntaxError: Unexpected token <
-This is a testharness.js-based test.
-PASS html5lib_tests7.html 7cb496e242a4dc9aed321252b5ca6ebf4f02ebcd 
-PASS html5lib_tests7.html c0cffec1e999db2aefb2f6beb679fd9620566dbd 
-PASS html5lib_tests7.html 7c644a6da21bfd551385b0a5044b82cf7be0a22f 
-PASS html5lib_tests7.html 52fde917ba333b89afeff0e31104421455f4bf1b 
-PASS html5lib_tests7.html a8f53ca779c0e5fc484771c4ec2aa6fb6d609779 
-PASS html5lib_tests7.html e4ce65a5fb6a3726b341ec94da583dee7c2c8232 
-PASS html5lib_tests7.html 8779e761986b4c724bfe73fee95b7972145fb4d3 
-PASS html5lib_tests7.html 620e44a8a55e82cec0d51e9d93025d8a5c4456fc 
-PASS html5lib_tests7.html 37b910b755c2df155a3129d5a1150f0c0fdd7934 
-PASS html5lib_tests7.html 868bff3a23219b836fdc702063d637f817ce65e1 
-FAIL html5lib_tests7.html a33a56f5571b4bcb23138ffb60df3824f5c53773 assert_equals: expected "#document\n| <!DOCTYPE html>\n| <html>\n|   <head>\n|   <body>\n|     <p>\n|       <applet>\n|         <p>\n|           \"X\"" but got "#document\n| <!DOCTYPE html>\n| <html>\n|   <head>\n|   <body>\n|     <p>\n|       <applet>\n|     <p>\n|       \"X\""
-PASS html5lib_tests7.html 8ba11b54fa74a1c229d079b2902d6e33e139f33b 
-PASS html5lib_tests7.html 84e2152c284f4dfee7d8d12846c08b2c025578a6 
-PASS html5lib_tests7.html 8e3432411baa59cbef731ab3ba2703cb5d518453 
-PASS html5lib_tests7.html e2f6144290512430ad25bbf9598eae77288c7b7a 
-PASS html5lib_tests7.html 350ebd648764d585f4aa0c29b925e6276579e9d0 
-PASS html5lib_tests7.html 9120ef80d3ee017007f3510121ddf7eba31b79e0 
-PASS html5lib_tests7.html 2026cd3ed42e41c168dd37c8c2675584f4eef335 
-PASS html5lib_tests7.html ff2e324237e22efc8430ad7137d50d6d3d311820 
-PASS html5lib_tests7.html 02c9eb822611b0c206b544e0f2e5044695195ba8 
-PASS html5lib_tests7.html cb3d1a50dd56a85135a0856cfa1c23a091ef2af4 
-PASS html5lib_tests7.html 13847685cfff75642823a0e78c6ef232ecb9d94b 
-PASS html5lib_tests7.html 99bb5e9a6e0daf62ba418dd97b5e8e3925f4137e 
-PASS html5lib_tests7.html 7a8e5ec2c95e725717c564dd49bfa86c2e1a88ba 
-PASS html5lib_tests7.html 17dcea170bb74d18ed4776dbb98f0bac6a11364d 
-PASS html5lib_tests7.html 9457c10c9f987bbc95937b34763fe956d61d237b 
-PASS html5lib_tests7.html 0fa23bb5d8b2a591afb1842b8f4c00c490c127b4 
-PASS html5lib_tests7.html f6d60b3ae48e2b69b4c25125f9b5a3ab4867521b 
-PASS html5lib_tests7.html 5b0b3edcc3ce9fdc9f58eb62d326865ca0aab8c8 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/inspector/file-system-mapping-expected.txt b/third_party/WebKit/LayoutTests/inspector/file-system-mapping-expected.txt
index b281143..69667cb0 100644
--- a/third_party/WebKit/LayoutTests/inspector/file-system-mapping-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/file-system-mapping-expected.txt
@@ -27,7 +27,7 @@
      - /home/username/projects/foo
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
 
 Adding file mapping (/www/site1, http://www.foo.com/, /foo/)
 Testing file system mapping.
@@ -35,29 +35,29 @@
      - /home/username/projects/foo
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Adding file mapping (/home/username/projects/foo, http://www.example.com/bar/, /foo/)
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Adding file mapping for resource (http://www.bar.com/foo/folder/42.js, /home/username/projects/foo, baz/folder/42.js)
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Testing mappings for url:
     Has mapping for 'http://www.bar.com/foo/folder/42.js': true
@@ -88,37 +88,37 @@
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.bar.com/foo/","pathPrefix":"/baz/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Removing file mapping for url http://www.bar.com/foo/folder/42.js
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/"}
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://localhost/","pathPrefix":"/","configurable":true}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Removing file mapping (/www/site1, http://localhost/, /)
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
-         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/www/site1","urlPrefix":"http://www.foo.com/","pathPrefix":"/foo/","configurable":true}
 
 Removing file mapping (/www/site1, http://www.foo.com/, /foo/)
 Testing file system mapping.
     file system paths:
      - /home/username/projects/foo
-         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/"}
+         - {"fileSystemPath":"/home/username/projects/foo","urlPrefix":"http://www.example.com/bar/","pathPrefix":"/foo/","configurable":true}
      - /home/username/projects/bar
      - /www/site1
 
diff --git a/third_party/WebKit/LayoutTests/inspector/file-system-project-expected.txt b/third_party/WebKit/LayoutTests/inspector/file-system-project-expected.txt
index b4a093c..702987e4 100644
--- a/third_party/WebKit/LayoutTests/inspector/file-system-project-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/file-system-project-expected.txt
@@ -46,3 +46,32 @@
 Removing first file system.
     number of uiSourceCodes in workspace after removing first file system: 0
 
+Running: testDefaultExcludes
+
+-- Default excludes --
+Dumping uiSourceCodes origin URLs:
+  - file:///var/www/html/foo.js
+  - file:///var/www/bar.js
+  - file:///var/www/html2/foo.js
+
+Running: testExcludesSettings
+
+-- Excluded /html/ --
+Dumping uiSourceCodes origin URLs:
+  - file:///var/www2/bar.js
+  - file:///var/www2/html2/foo.js
+
+Running: testExcludesViaDelegate
+
+-- Excluded /html2/ --
+Dumping uiSourceCodes origin URLs:
+  - file:///var/www3/html/foo.js
+  - file:///var/www3/bar.js
+
+Running: testExcludesViaProject
+
+-- Excluded /html2/ via .devtools --
+Dumping uiSourceCodes origin URLs:
+  - file:///html/foo.js
+  - file:///bar.js
+
diff --git a/third_party/WebKit/LayoutTests/inspector/file-system-project.html b/third_party/WebKit/LayoutTests/inspector/file-system-project.html
index e501a01..240327f 100644
--- a/third_party/WebKit/LayoutTests/inspector/file-system-project.html
+++ b/third_party/WebKit/LayoutTests/inspector/file-system-project.html
@@ -43,6 +43,24 @@
         }
     }
 
+    function dumpWorkspaceUISourceCodes()
+    {
+        InspectorTest.addResult("Dumping uiSourceCodes origin URLs:");
+        var uiSourceCodes = InspectorTest.fileSystemUISourceCodes();
+        for (var i = 0; i < uiSourceCodes.length; ++i)
+            InspectorTest.addResult("  - " + uiSourceCodes[i].originURL());
+    }
+
+    function createFileSystem(name, callback)
+    {
+        var fs = new InspectorTest.TestFileSystem(name);
+        fs.root.mkdir("html").addFile("foo.js", "");
+        fs.root.mkdir(".git").addFile("foogit.js", "");
+        fs.root.addFile("bar.js", "");
+        fs.root.mkdir("html2").addFile("foo.js", "");
+        fs.reportCreated(callback.bind(null, fs));
+    }
+
     InspectorTest.runTestSuite([
         function testFileSystems(next)
         {
@@ -51,35 +69,33 @@
             var fs2 = new InspectorTest.TestFileSystem("/foo/bar");
             InspectorTest.addResult("Adding second file system.");
 
-            fs1.reportCreated();
-            fs2.reportCreated();
-            InspectorTest.addResult("Adding file mappings.");
-            WebInspector.fileSystemMapping.addFileMapping("/var/www", "http://localhost/", "/localhost/");
-            WebInspector.fileSystemMapping.addFileMapping("/foo/bar", "http://www.example.com/", "/");
-
-            InspectorTest.addResult("Adding files to file systems.");
-
-            var localhostDir = fs1.root.mkdir("localhost");
-            localhostDir.addFile("foo.js", "<foo content>");
-            fs1.root.addFile("bar.js", "<bark content>");
-
-            fs2.root.addFile("baz.js", "<bazzz content>");
-
-            InspectorTest.refreshFileSystemProjects(onProjectsRefreshed);
-
             var uiSourceCodes;
 
+            fs1.reportCreated(function() {});
+            fs2.reportCreated(fileSystemCreated);
+
+            function fileSystemCreated()
+            {
+                InspectorTest.addResult("Adding file mappings.");
+                WebInspector.fileSystemMapping.addFileMapping("/var/www", "http://localhost/", "/localhost/");
+                WebInspector.fileSystemMapping.addFileMapping("/foo/bar", "http://www.example.com/", "/");
+
+                InspectorTest.addResult("Adding files to file systems.");
+
+                var localhostDir = fs1.root.mkdir("localhost");
+                localhostDir.addFile("foo.js", "<foo content>");
+                fs1.root.addFile("bar.js", "<bark content>");
+
+                fs2.root.addFile("baz.js", "<bazzz content>");
+                InspectorTest.refreshFileSystemProjects(onProjectsRefreshed);
+            }
+
             function onProjectsRefreshed()
             {
                 uiSourceCodes = InspectorTest.fileSystemUISourceCodes();
                 dumpUISourceCodes(uiSourceCodes, uiSourceCodesDumped);
             }
 
-            function uiSourceCodeAdded(uiSourceCode)
-            {
-                uiSourceCodes.push(uiSourceCode)
-            }
-
             function uiSourceCodesDumped()
             {
                 dumpUISourceCodeLocations(uiSourceCodes, 5);
@@ -117,15 +133,79 @@
                     InspectorTest.addResult("New modificationTime=" + modificationTime.getTime() + ", size=" + size);
                     var uiSourceCodesCount = InspectorTest.fileSystemUISourceCodes().length;
                     InspectorTest.addResult("Removing second file system.");
-                    fs1.removeFileSystem();
+                    fs1.reportRemoved();
                     InspectorTest.addResult("    number of uiSourceCodes in workspace after removing second file system: " + InspectorTest.fileSystemUISourceCodes().length);
                     InspectorTest.addResult("Removing first file system.");
-                    fs2.removeFileSystem();
+                    fs2.reportRemoved();
                     InspectorTest.addResult("    number of uiSourceCodes in workspace after removing first file system: " + InspectorTest.fileSystemUISourceCodes().length);
                     next();
                 }
             }
         },
+
+        function testDefaultExcludes(next)
+        {
+            createFileSystem("/var/www", dumpExcludes);
+
+            function dumpExcludes(fs)
+            {
+                InspectorTest.addResult("");
+                InspectorTest.addResult("-- Default excludes --");
+                dumpWorkspaceUISourceCodes();
+                fs.reportRemoved();
+                next();
+            }
+        },
+
+        function testExcludesSettings(next)
+        {
+            WebInspector.settings.createLocalSetting("workspaceExcludedFolders", {}).set({"/var/www2":["/html/"]});
+            createFileSystem("/var/www2", dumpExcludes);
+
+            function dumpExcludes(fs)
+            {
+                InspectorTest.addResult("");
+                InspectorTest.addResult("-- Excluded /html/ --");
+                dumpWorkspaceUISourceCodes();
+                fs.reportRemoved();
+                next();
+            }
+        },
+
+        function testExcludesViaDelegate(next)
+        {
+            createFileSystem("/var/www3", dumpExcludes);
+
+            function dumpExcludes(fs)
+            {
+                InspectorTest.fileSystemUISourceCodes()[0].project().excludeFolder("/html2/");
+                InspectorTest.addResult("");
+                InspectorTest.addResult("-- Excluded /html2/ --");
+                dumpWorkspaceUISourceCodes();
+                fs.reportRemoved();
+                next();
+            }
+        },
+
+        function testExcludesViaProject(next)
+        {
+            var fs = new InspectorTest.TestFileSystem(name);
+            fs.root.addFile(".devtools", JSON.stringify({excludes:["/html2/"]}));
+            fs.root.mkdir("html").addFile("foo.js", "");
+            fs.root.mkdir(".git").addFile("foogit.js", "");
+            fs.root.addFile("bar.js", "");
+            fs.root.mkdir("html2").addFile("foo.js", "");
+            fs.reportCreated(dumpExcludes);
+
+            function dumpExcludes()
+            {
+                InspectorTest.addResult("");
+                InspectorTest.addResult("-- Excluded /html2/ via .devtools --");
+                dumpWorkspaceUISourceCodes();
+                fs.reportRemoved();
+                next();
+            }
+        }
     ]);
 };
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval-expected.txt
index 607762eb..58d3f282 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval-expected.txt
@@ -2,11 +2,16 @@
 
 Set timer for test function.
 Call stack:
-    0) timeout (async-callstack-eval.html:25)
+    0) timeout (async-callstack-eval.html:26)
     [setTimeout]
-    0) inner (async-callstack-eval.html:15)
-    1) testFunction (async-callstack-eval.html:17)
+    0) inner (async-callstack-eval.html:16)
+    1) testFunction (async-callstack-eval.html:18)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 Select call frame: inner
 a = "PASS"
 b = "PASS"
+Select call frame: scheduleTestFunction
+g = "PASS"
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval.html
index 5063c695..365f302 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-eval.html
@@ -6,6 +6,7 @@
 <script>
 
 var a = "FAIL";
+var g = "PASS";
 function testFunction()
 {
     var a = "PASS";
@@ -46,11 +47,16 @@
     {
         InspectorTest.captureStackTrace(callFrames, asyncStackTrace);
 
+        selectCallFrameAndRun(1, step3);
+    }
+
+    function selectCallFrameAndRun(frameNumber, callback)
+    {
         var pane = WebInspector.panels.sources.sidebarPanes.callstack;
-        var frame = pane.callFrames[1];
+        var frame = pane.callFrames[frameNumber];
         InspectorTest.addResult("Select call frame: " + frame.title());
         pane._callFrameSelected(frame);
-        InspectorTest.runAfterPendingDispatches(step3);
+        InspectorTest.runAfterPendingDispatches(callback);
     }
 
     function step3()
@@ -60,7 +66,17 @@
 
     function step4()
     {
-        InspectorTest.evaluateInConsoleAndDump("b", tearDown);
+        InspectorTest.evaluateInConsoleAndDump("b", step5);
+    }
+
+    function step5()
+    {
+        selectCallFrameAndRun(3, step6);
+    }
+
+    function step6()
+    {
+        InspectorTest.evaluateInConsoleAndDump("g", tearDown);
     }
 
     function tearDown()
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events-expected.txt
index 092ca1d..1c264b9 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-events-expected.txt
@@ -7,12 +7,18 @@
     [hashchange]
     0) doTestHashChange (async-callstack-events.html:46)
     1) testFunction (async-callstack-events.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onHashChange2 (async-callstack-events.html:58)
     [hashchange]
     0) doTestHashChange (async-callstack-events.html:46)
     1) testFunction (async-callstack-events.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onSelectionChange (async-callstack-events.html:39)
@@ -20,11 +26,17 @@
     0) setSelection (async-callstack-events.html:24)
     1) doTestSelectionChange (async-callstack-events.html:31)
     2) testFunction (async-callstack-events.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onVideoPlay (async-callstack-events.html:71)
     [play]
     0) doTestMediaEvents (async-callstack-events.html:65)
     1) testFunction (async-callstack-events.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt
index 11877d57..adb5d402 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-expected.txt
@@ -9,6 +9,9 @@
     1) innerTestFunction (async-callstack.html:11)
     [setTimeout]
     0) testFunction (async-callstack.html:13)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) animFrame2 (async-callstack.html:47)
@@ -19,6 +22,9 @@
     1) innerTestFunction (async-callstack.html:11)
     [setTimeout]
     0) testFunction (async-callstack.html:13)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) interval1 (async-callstack.html:37)
@@ -28,12 +34,18 @@
     1) innerTestFunction (async-callstack.html:11)
     [setTimeout]
     0) testFunction (async-callstack.html:13)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) timeout1 (async-callstack.html:18)
     1) innerTestFunction (async-callstack.html:11)
     [setTimeout]
     0) testFunction (async-callstack.html:13)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) timeout2 (async-callstack.html:42)
@@ -44,6 +56,9 @@
     1) innerTestFunction (async-callstack.html:11)
     [setTimeout]
     0) testFunction (async-callstack.html:13)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) timeout3 (async-callstack.html:61)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string-expected.txt
index 1c132cb..4c0dd22 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-get-as-string-expected.txt
@@ -10,11 +10,17 @@
     1) timeout (async-callstack-get-as-string.html:24)
     [setTimeout]
     0) testFunction (async-callstack-get-as-string.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onPaste (async-callstack-get-as-string.html:29)
     1) timeout (async-callstack-get-as-string.html:24)
     [setTimeout]
     0) testFunction (async-callstack-get-as-string.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt
index 7adcae1..d433bb0 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-indexed-db-expected.txt
@@ -51,6 +51,9 @@
     0) openDB (async-callstack-indexed-db.html:23)
     [setTimeout]
     0) testFunction (async-callstack-indexed-db.html:12)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onSuccessStorePut (async-callstack-indexed-db.html:59)
@@ -61,6 +64,9 @@
     0) openDB (async-callstack-indexed-db.html:23)
     [setTimeout]
     0) testFunction (async-callstack-indexed-db.html:12)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onUpgradeNeeded (async-callstack-indexed-db.html:31)
@@ -68,5 +74,8 @@
     0) openDB (async-callstack-indexed-db.html:23)
     [setTimeout]
     0) testFunction (async-callstack-indexed-db.html:12)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt
index 572855b..645b7eb 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-mutation-observer-expected.txt
@@ -9,6 +9,9 @@
     1) timeout1 (async-callstack-mutation-observer.html:44)
     [setTimeout]
     0) testFunction (async-callstack-mutation-observer.html:35)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) mutationCallback (async-callstack-mutation-observer.html:21)
@@ -19,6 +22,9 @@
     0) timeout1 (async-callstack-mutation-observer.html:43)
     [setTimeout]
     0) testFunction (async-callstack-mutation-observer.html:35)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) nestedMutationCallback (async-callstack-mutation-observer.html:28)
@@ -30,6 +36,9 @@
     1) timeout1 (async-callstack-mutation-observer.html:44)
     [setTimeout]
     0) testFunction (async-callstack-mutation-observer.html:35)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) nestedMutationCallback (async-callstack-mutation-observer.html:28)
@@ -54,6 +63,9 @@
     1) timeout1 (async-callstack-mutation-observer.html:44)
     [setTimeout]
     0) testFunction (async-callstack-mutation-observer.html:35)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) timeoutFromNestedMutation (async-callstack-mutation-observer.html:75)
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-object-observe-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-object-observe-expected.txt
index cb7bb2a..609ff246 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-object-observe-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-object-observe-expected.txt
@@ -11,5 +11,8 @@
     0) timeout1 (async-callstack-object-observe.html:16)
     [setTimeout]
     0) testFunction (async-callstack-object-observe.html:10)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt
index b3ec4c9..e0d340c9 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-post-message-expected.txt
@@ -24,6 +24,9 @@
     1) timeout (async-callstack-post-message.html:16)
     [setTimeout]
     0) testFunction (async-callstack-post-message.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onMessageReceivedInParent (async-callstack-post-message.html:21)
@@ -50,6 +53,9 @@
     1) timeout (async-callstack-post-message.html:16)
     [setTimeout]
     0) testFunction (async-callstack-post-message.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onMessageReceivedInParent (async-callstack-post-message.html:21)
@@ -58,5 +64,8 @@
     1) timeout (async-callstack-post-message.html:15)
     [setTimeout]
     0) testFunction (async-callstack-post-message.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt
index e4173be1c..028ad4e 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-promises-expected.txt
@@ -13,6 +13,9 @@
     3) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) catchCallback (async-callstack-promises.html:118)
@@ -56,6 +59,9 @@
     3) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) chained2 (async-callstack-promises.html:83)
@@ -112,6 +118,9 @@
     1) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) errorCallback (async-callstack-promises.html:60)
@@ -120,6 +129,9 @@
     1) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) promiseCallback (async-callstack-promises.html:67)
@@ -127,6 +139,9 @@
     2) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) thenCallback (async-callstack-promises.html:55)
@@ -135,6 +150,9 @@
     1) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) thenCallback (async-callstack-promises.html:55)
@@ -143,6 +161,9 @@
     1) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) thenCallback (async-callstack-promises.html:55)
@@ -170,5 +191,8 @@
     3) testFunctionTimeout (async-callstack-promises.html:50)
     [setTimeout]
     0) testFunction (async-callstack-promises.html:43)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll-expected.txt
index 274ddfa..f6dd552 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-scripted-scroll-expected.txt
@@ -8,6 +8,9 @@
     0) timeout (async-callstack-scripted-scroll.html:18)
     [setTimeout]
     0) testFunction (async-callstack-scripted-scroll.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onScroll2 (async-callstack-scripted-scroll.html:33)
@@ -15,5 +18,8 @@
     0) timeout (async-callstack-scripted-scroll.html:18)
     [setTimeout]
     0) testFunction (async-callstack-scripted-scroll.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval-expected.txt
index b05d6f2..413ce90 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-set-interval-expected.txt
@@ -6,15 +6,24 @@
     0) callback (async-callstack-set-interval.html:17)
     [setInterval]
     0) testFunction (async-callstack-set-interval.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) callback (async-callstack-set-interval.html:19)
     [setInterval]
     0) testFunction (async-callstack-set-interval.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) callback (async-callstack-set-interval.html:22)
     [setInterval]
     0) testFunction (async-callstack-set-interval.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql-expected.txt
index 4580bdf..c162f7cc 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-web-sql-expected.txt
@@ -9,6 +9,9 @@
     0) openDB (async-callstack-web-sql.html:27)
     [setTimeout]
     0) testFunction (async-callstack-web-sql.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onDropTable (async-callstack-web-sql.html:47)
@@ -18,6 +21,9 @@
     0) openDB (async-callstack-web-sql.html:27)
     [setTimeout]
     0) testFunction (async-callstack-web-sql.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onSuccess (async-callstack-web-sql.html:14)
@@ -27,6 +33,9 @@
     0) openDB (async-callstack-web-sql.html:27)
     [setTimeout]
     0) testFunction (async-callstack-web-sql.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onSuccess (async-callstack-web-sql.html:14)
@@ -36,6 +45,9 @@
     0) openDB (async-callstack-web-sql.html:27)
     [setTimeout]
     0) testFunction (async-callstack-web-sql.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) onSuccess (async-callstack-web-sql.html:14)
@@ -43,5 +55,8 @@
     0) openDB (async-callstack-web-sql.html:27)
     [setTimeout]
     0) testFunction (async-callstack-web-sql.html:9)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs-expected.txt
index cf67f378..d9a4f12 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-async/async-callstack-xhrs-expected.txt
@@ -10,6 +10,9 @@
     3) timeout (async-callstack-xhrs.html:16)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) downloadEnd1 (async-callstack-xhrs.html:36)
@@ -19,6 +22,9 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) downloadEnd2 (async-callstack-xhrs.html:41)
@@ -27,6 +33,9 @@
     3) timeout (async-callstack-xhrs.html:16)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) downloadEnd2 (async-callstack-xhrs.html:41)
@@ -36,6 +45,9 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) downloadProgress (async-callstack-xhrs.html:50)
@@ -45,6 +57,9 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) uploadEnd (async-callstack-xhrs.html:46)
@@ -54,6 +69,9 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) uploadProgress (async-callstack-xhrs.html:55)
@@ -63,6 +81,9 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) xhr.onreadystatechange (async-callstack-xhrs.html:30)
@@ -71,6 +92,9 @@
     3) timeout (async-callstack-xhrs.html:16)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 Call stack:
     0) xhr.onreadystatechange (async-callstack-xhrs.html:30)
@@ -80,5 +104,8 @@
     2) timeout (async-callstack-xhrs.html:17)
     [setTimeout]
     0) testFunction (async-callstack-xhrs.html:11)
+    [setTimeout]
+    0) scheduleTestFunction (debugger-test.js:3)
+    <... skipped remaining frames ...>
 
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit-expected.txt
new file mode 100644
index 0000000..f98703a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit-expected.txt
@@ -0,0 +1,8 @@
+Tests file system project mappings in combination with live edit.
+
+
+Running: testLiveEditReload
+Adding file system.
+Editing filesystem resource: file:///var/www/html/edit-me.js
+Edited function returns: live-edited string
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit.html
new file mode 100644
index 0000000..50172ea3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-live-edit.html
@@ -0,0 +1,64 @@
+<html>
+<head>
+<script src="../../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../../http/tests/inspector/debugger-test.js"></script>
+<script src="../../../http/tests/inspector/workspace-test.js"></script>
+<script src="../../../http/tests/inspector/isolated-filesystem-test.js"></script>
+<script src="../../../http/tests/inspector/live-edit-test.js"></script>
+<script>
+function addScript()
+{
+    var script = document.createElement("script");
+    script.src = "resources/edit-me.js";
+    document.head.appendChild(script);
+}
+
+function test()
+{
+    InspectorTest.runTestSuite([
+        function testLiveEditReload(next)
+        {
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.mkdir("html").addFile("edit-me.js", "function f()\n{\n    return 0;\n}\n");
+            fs.root.addFile("bar.js", "<bar content>");
+            InspectorTest.addResult("Adding file system.");
+            fs.addFileMapping(WebInspector.ParsedURL.completeURL(InspectorTest.resourceTreeModel.inspectedPageURL(), "resources/"), "/html/");
+            fs.reportCreated(fileSystemCreated);
+
+            function fileSystemCreated()
+            {
+                InspectorTest.evaluateInPage("addScript()", didAddScript);
+            }
+
+            function didAddScript()
+            {
+                InspectorTest.showScriptSource("edit-me.js", didShowScriptSource);
+            }
+
+            function didShowScriptSource(sourceFrame)
+            {
+                InspectorTest.addResult("Editing filesystem resource: " + sourceFrame.uiSourceCode().originURL());
+                InspectorTest.addSniffer(WebInspector.DebuggerModel.prototype, "_didEditScriptSource", didEditScriptSource);
+                InspectorTest.replaceInSource(sourceFrame, "return 0;", "return \"live-edited string\";");
+                InspectorTest.commitSource(sourceFrame);
+            }
+
+            function didEditScriptSource()
+            {
+                InspectorTest.evaluateInPage("f()", didEvaluateInPage);
+            }
+
+            function didEvaluateInPage(result)
+            {
+                InspectorTest.addResult("Edited function returns: " + result.description);
+                next();
+            }
+        }
+    ]);
+};
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests file system project mappings in combination with live edit.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping-expected.txt
index e89b67f..3b5a9fdb 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping-expected.txt
@@ -11,7 +11,6 @@
 UISourceCode uri to url mappings:
     filesystem:/var/www/html/foo.js -> 
     filesystem:/var/www/bar.js -> 
-error: networkUISourceCode: [object Object]
 Adding mapping between network and file system resources.
 Emulate reloading inspector.
 Workspace event: UISourceCodeAdded: filesystem:/var/www/html/foo.js.
@@ -23,6 +22,8 @@
 Emulate reloading inspector.
 Workspace event: UISourceCodeAdded: filesystem:/var/www/html/foo.js.
 Workspace event: UISourceCodeAdded: filesystem:/var/www/bar.js.
+Workspace event: UISourceCodeAdded: http://localhost/html/foo.js.
+Workspace event: UISourceCodeAdded: http://localhost/bar.js.
 UISourceCode uri to url mappings:
     filesystem:/var/www/html/foo.js -> 
     filesystem:/var/www/bar.js -> 
@@ -81,32 +82,6 @@
  - hasDivergedFromVM: true
  - sourceFrame._muted: true
 
-Running: testLiveEditReload
-Adding file system.
-Adding file system mapping.
-Page reloaded.
-Page reloaded.
-==Source frame contents start==
-function f()
-{
-    return "live-edited string";
-}
-
-==Source frame contents end==
-
-Running: testExcludingFolders
-Adding file system.
-Adding exclusion pattern and excluded folder.
-Workspace event: UISourceCodeAdded: filesystem:/var/www/bar.js.
-Workspace event: UISourceCodeAdded: filesystem:/var/www/html2/foo.js.
-Dumping uiSourceCodes origin URLs:
-  - file:///var/www/bar.js
-  - file:///var/www/html2/foo.js
-Excluding html2 folder:
-Workspace event: UISourceCodeRemoved: filesystem:/var/www/html2/foo.js.
-Dumping uiSourceCodes origin URLs:
-  - file:///var/www/bar.js
-
 Running: testRemoveProject
 Adding file system.
 Workspace event: UISourceCodeAdded: filesystem:/var/www/foo.js.
@@ -126,3 +101,11 @@
     uiSourceCode URL change after renaming: http://localhost/bar.js -> http://localhost/newName.js
     uiSourceCode URL change after renaming: http://localhost/foo/bar/baz.js -> http://localhost/foo/bar/newName.js
 
+Running: testProjectBasedMapping
+Adding file system.
+Workspace event: UISourceCodeAdded: filesystem:/var/www/html/foo.js.
+Workspace event: UISourceCodeAdded: filesystem:/var/www/html2/bar.js.
+UISourceCode uri to url mappings:
+    filesystem:/var/www/html/foo.js -> http://localhost/h1/foo.js
+    filesystem:/var/www/html2/bar.js -> http://localhost/h2/bar.js
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping.html
index 10307323..5d73f7b 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/file-system-project-mapping.html
@@ -5,86 +5,93 @@
 <script src="../../../http/tests/inspector/workspace-test.js"></script>
 <script src="../../../http/tests/inspector/isolated-filesystem-test.js"></script>
 <script src="../../../http/tests/inspector/live-edit-test.js"></script>
-<script src="resources/edit-me.js"></script>
 <script>
 function test()
 {
     var target;
-    var manager;
     var resourceScriptMapping;
     var defaultScriptMapping;
+    var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId("/var/www");
 
-    function createObjects()
+    function createWorkspaceWithTarget()
     {
-        if (target)
-            InspectorTest.testTargetManager.removeTarget(target);
-        target = InspectorTest.createWorkspaceWithTarget();
-        manager = InspectorTest.createIsolatedFileSystemManager(InspectorTest.testWorkspace);
+        target = InspectorTest.createWorkspaceWithTarget(false);
         var entry = InspectorTest.testDebuggerWorkspaceBinding._targetToData.get(target);
         resourceScriptMapping = entry._resourceMapping;
         defaultScriptMapping = entry._defaultMapping;
     }
 
+    function dumpFileSystemUISourceCodesMappings()
+    {
+        var uiSourceCodes = InspectorTest.testWorkspace.project(fileSystemProjectId).uiSourceCodes();
+        InspectorTest.addResult("UISourceCode uri to url mappings:");
+        for (var i = 0; i < uiSourceCodes.length; ++i) {
+            var networkURL = InspectorTest.testNetworkMapping.networkURL(uiSourceCodes[i]);
+            InspectorTest.addResult("    " + uiSourceCodes[i].uri() + " -> " + networkURL);
+        }
+    }
+
     InspectorTest.runTestSuite([
         function testAutomaticMapping(next)
         {
-            function dumpFileSystemUISourceCodesMappings()
-            {
-                var uiSourceCodes = InspectorTest.testWorkspace.project(fileSystemProjectId).uiSourceCodes();
-                InspectorTest.addResult("UISourceCode uri to url mappings:");
-                for (var i = 0; i < uiSourceCodes.length; ++i) {
-                    var networkURL = InspectorTest.testNetworkMapping.networkURL(uiSourceCodes[i]);
-                    InspectorTest.addResult("    " + uiSourceCodes[i].uri() + " -> " + networkURL);
-                }
-            }
-
-            var fileSystemPath = "/var/www";
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            var files = {"/html/foo.js": "<foo content>", "/bar.js": "<bar content>"};
-            var uiSourceCode;
-            var networkUISourceCode;
-            var setting;
-
-            createObjects();
+            createWorkspaceWithTarget();
 
             InspectorTest.addResult("Adding file system.");
-            manager.addMockFileSystem(fileSystemPath);
-            manager.addFiles(fileSystemPath, files);
-            InspectorTest.addResult("Adding network resource.");
-            InspectorTest.addMockUISourceCodeToWorkspace("http://localhost/html/foo.js", WebInspector.resourceTypes.Script, "<foo content>");
-            InspectorTest.addMockUISourceCodeToWorkspace("http://localhost/bar.js", WebInspector.resourceTypes.Script, "<foo content>");
-            dumpFileSystemUISourceCodesMappings();
-            uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
-            networkUISourceCode = InspectorTest.testWorkspace.uiSourceCode(WebInspector.NetworkProject.projectId(target, "http://localhost"), "html/foo.js");
-            console.error("networkUISourceCode: " + networkUISourceCode);
-            InspectorTest.override(WebInspector.SourcesPanel.prototype, "_suggestReload", function() { });
-            InspectorTest.addResult("Adding mapping between network and file system resources.");
-            InspectorTest.testNetworkMapping.addMapping(networkUISourceCode, uiSourceCode, manager.fileSystemWorkspaceBinding);
-            setting = InspectorTest.testFileSystemMapping._fileSystemMappingSetting;
-            InspectorTest.addResult("Emulate reloading inspector.");
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.mkdir("html").addFile("foo.js", "<foo content>");
+            fs.root.addFile("bar.js", "<bar content>");
+            fs.reportCreated(fileSystemCreated1);
+            var networkUISourceCode;
 
-            createObjects();
+            function fileSystemCreated1()
+            {
+                InspectorTest.addResult("Adding network resource.");
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/html/foo.js", WebInspector.resourceTypes.Script, "<foo content>");
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/bar.js", WebInspector.resourceTypes.Script, "<foo content>");
+                dumpFileSystemUISourceCodesMappings();
 
-            InspectorTest.testFileSystemMapping._fileSystemMappingSetting = setting;
-            InspectorTest.testFileSystemMapping._loadFromSettings();
-            manager.addMockFileSystem(fileSystemPath, true);
-            manager.addFiles(fileSystemPath, files);
-            dumpFileSystemUISourceCodesMappings();
-            InspectorTest.addResult("Removing mapping between network and file system resources.");
-            uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
-            InspectorTest.testNetworkMapping.removeMapping(uiSourceCode);
+                var uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
+                networkUISourceCode = InspectorTest.testWorkspace.uiSourceCode(WebInspector.NetworkProject.projectId(target, "http://localhost"), "html/foo.js");
+                InspectorTest.override(WebInspector.SourcesPanel.prototype, "_suggestReload", function() { });
+                InspectorTest.addResult("Adding mapping between network and file system resources.");
+                InspectorTest.testNetworkMapping.addMapping(networkUISourceCode, uiSourceCode);
+                var setting = JSON.stringify(WebInspector.fileSystemMapping._fileSystemMappingSetting.get());
 
-            InspectorTest.addResult("Emulate reloading inspector.");
+                InspectorTest.addResult("Emulate reloading inspector.");
+                fs.reportRemoved();
+                createWorkspaceWithTarget();
+                WebInspector.fileSystemMapping._fileSystemMappingSetting.set(JSON.parse(setting));
+                WebInspector.fileSystemMapping._loadFromSettings();
+                fs.reportCreated(fileSystemCreated2);
+            }
 
-            createObjects();
+            function fileSystemCreated2()
+            {
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/html/foo.js", WebInspector.resourceTypes.Script, "<foo content>");
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/bar.js", WebInspector.resourceTypes.Script, "<foo content>");
+                dumpFileSystemUISourceCodesMappings();
 
-            manager.addMockFileSystem(fileSystemPath);
-            manager.addFiles(fileSystemPath, files);
-            dumpFileSystemUISourceCodesMappings();
+                InspectorTest.addResult("Removing mapping between network and file system resources.");
+                var uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
+                InspectorTest.testNetworkMapping.removeMapping(uiSourceCode);
 
-            var networkURL = InspectorTest.testNetworkMapping.networkURL(networkUISourceCode);
-            InspectorTest.testFileSystemMapping.removeMappingForURL(networkURL);
-            next();
+                InspectorTest.addResult("Emulate reloading inspector.");
+                fs.reportRemoved();
+                createWorkspaceWithTarget();
+                fs.reportCreated(fileSystemCreated3);
+            }
+
+            function fileSystemCreated3()
+            {
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/html/foo.js", WebInspector.resourceTypes.Script, "<foo content>");
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/bar.js", WebInspector.resourceTypes.Script, "<foo content>");
+                dumpFileSystemUISourceCodesMappings();
+
+                var networkURL = InspectorTest.testNetworkMapping.networkURL(networkUISourceCode);
+                WebInspector.fileSystemMapping.removeMappingForURL(networkURL);
+                fs.reportRemoved();
+                next();
+            }
         },
 
         function testScriptFileOnReloadWithDirtyFile(next)
@@ -105,29 +112,31 @@
                 resourceScriptMapping.addScript(script);
             }
 
-            var fileSystemPath = "/var/www";
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            var files = {"/html/foo.js": originalFileContent, "/bar.js": "<bar content>"};
             var uiSourceCode;
-            var target;
 
-            createObjects();
+            createWorkspaceWithTarget();
 
             InspectorTest._originalDebuggerBinding = WebInspector.debuggerWorkspaceBinding;
             WebInspector.debuggerWorkspaceBinding = InspectorTest.testDebuggerWorkspaceBinding;
-            target = InspectorTest.testTargetManager.targets()[0];
+            var target = InspectorTest.testTargetManager.targets()[0];
             WebInspector._originalTargetManager = WebInspector.targetManager;
             WebInspector.targetManager = InspectorTest.testTargetManager;
+
             InspectorTest.addResult("Adding file system.");
-            manager.addMockFileSystem(fileSystemPath);
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.mkdir("html").addFile("foo.js", originalFileContent);
+            fs.root.addFile("bar.js", "<bar content>");
             InspectorTest.addResult("Adding file system mapping.");
-            InspectorTest.testFileSystemMapping.addFileMapping(fileSystemPath, "http://localhost/", "/");
-            manager.addFiles(fileSystemPath, files);
+            fs.addFileMapping("http://localhost/", "/");
+            fs.reportCreated(fileSystemCreated);
 
-            loadScript();
+            function fileSystemCreated()
+            {
+                loadScript();
 
-            uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
-            InspectorTest.showUISourceCode(uiSourceCode, didShowScriptSource);
+                uiSourceCode = InspectorTest.testWorkspace.uiSourceCode(fileSystemProjectId, "html/foo.js");
+                InspectorTest.showUISourceCode(uiSourceCode, didShowScriptSource);
+            }
 
             function dumpUISourceCodeAndScriptContents()
             {
@@ -210,104 +219,12 @@
                 unloadScript();
                 loadScript;
 
-                InspectorTest.testFileSystemMapping.removeFileMapping(fileSystemPath, "http://localhost/", "/");
                 WebInspector.debuggerWorkspaceBinding = InspectorTest._originalDebuggerBinding;
+                fs.reportRemoved();
                 next();
             }
         },
 
-        function testLiveEditReload(next)
-        {
-            InspectorTest.showScriptSource("edit-me.js", didShowScriptSource);
-            
-            function didShowScriptSource(sourceFrame)
-            {
-                var scriptURL = InspectorTest.testNetworkMapping.networkURL(sourceFrame._uiSourceCode);
-
-                var fileContent = "function f()\n{\n    return 0;\n}\n";
-                var fileSystemPath = "/var/www";
-                var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-                var filePath = "/html/edit-me.js"; 
-                var files = {};
-                files[filePath] = fileContent;
-                InspectorTest.addResult("Adding file system.");
-                InspectorTest.addMockFileSystem(fileSystemPath)
-                InspectorTest.addResult("Adding file system mapping.");
-                WebInspector.fileSystemMapping.addMappingForResource(scriptURL, fileSystemPath, filePath.substr(1));
-                InspectorTest.addFilesToMockFileSystem(fileSystemPath, files);
-                // Now that we've set everything up, we need to reload a page to remove all network resources.
-                InspectorTest.waitForWorkspaceUISourceCodeAddedEvent(function() {}, 7);
-                InspectorTest.reloadPage(pageReloaded);
-            }
-
-            function pageReloaded()
-            {
-                // Now reload again as part of test.
-                InspectorTest.waitForWorkspaceUISourceCodeAddedEvent(function() {}, 7);
-                InspectorTest.reloadPage(pageReloadedAgain);
-            }
-
-            function pageReloadedAgain()
-            {
-                WebInspector.targetManager = WebInspector._originalTargetManager;
-                InspectorTest.showScriptSource("edit-me.js", didShowFile);
-            }
-
-            function didShowFile(sourceFrame)
-            {
-                replaceInSource(sourceFrame, "return 0;", "return \"live-edited string\";", didEditScriptSource);
-            }
-
-            function didEditScriptSource()
-            {
-                InspectorTest.evaluateInPage("f()", didEvaluateInPage)
-            }
-
-            function didEvaluateInPage(result)
-            {
-                InspectorTest.assertEquals("live-edited string", result.description, "edited function returns wrong result");
-                var panel = WebInspector.panels.sources;
-                InspectorTest.dumpSourceFrameContents(panel.visibleView);
-                next();
-            }
-
-            function replaceInSource(sourceFrame, string, replacement, callback)
-            {
-                InspectorTest.addSniffer(WebInspector.DebuggerModel.prototype, "_didEditScriptSource", callback);
-                InspectorTest.replaceInSource(sourceFrame, string, replacement);
-                InspectorTest.commitSource(sourceFrame);
-            }
-        },
-
-        function testExcludingFolders(next)
-        {
-            function dumpWorkspaceUISourceCodes()
-            {
-                InspectorTest.addResult("Dumping uiSourceCodes origin URLs:");
-                var uiSourceCodes = InspectorTest.testWorkspace.uiSourceCodes();
-                for (var i = 0; i < uiSourceCodes.length; ++i)
-                    InspectorTest.addResult("  - " + uiSourceCodes[i].originURL());
-            }
-
-            var fileSystemPath = "/var/www";
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            var files = {"/html/foo.js": "", "/.git/foogit.js": "", "/bar.js": "", "/html2/foo.js": ""};
-
-            createObjects();
-
-            InspectorTest.addResult("Adding file system.");
-            manager.addMockFileSystem(fileSystemPath);
-            InspectorTest.addResult("Adding exclusion pattern and excluded folder.");
-            InspectorTest.testExcludedFolderManager.addExcludedFolder(fileSystemPath, "/html/");
-            manager.addFiles(fileSystemPath, files);
-            dumpWorkspaceUISourceCodes();
-            InspectorTest.addResult("Excluding html2 folder:");
-            InspectorTest.testWorkspace.uiSourceCodes()[0].project().excludeFolder("/html2/");
-            dumpWorkspaceUISourceCodes();
-            InspectorTest.testExcludedFolderManager.removeExcludedFolder(fileSystemPath, "/html/");
-            next();
-        },
-
         function testRemoveProject(next)
         {
             function dumpWorkspaceUISourceCodes()
@@ -318,47 +235,54 @@
                     InspectorTest.addResult("  - " + uiSourceCodes[i].originURL());
             }
 
-            var fileSystemPath = "/var/www";
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            var files = {"/foo.js": ""};
-            createObjects();
+            createWorkspaceWithTarget();
 
             InspectorTest.addResult("Adding file system.");
-            manager.addMockFileSystem(fileSystemPath);
-            manager.addFiles(fileSystemPath, files);
-            dumpWorkspaceUISourceCodes();
-            InspectorTest.addResult("Removing project:");
-            InspectorTest.testWorkspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, projectRemoved);
-            InspectorTest.testTargetManager.removeTarget(target);
-            target = null;
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.addFile("foo.js", "");
+            fs.reportCreated(fileSystemCreated);
+
+            function fileSystemCreated()
+            {
+                dumpWorkspaceUISourceCodes();
+                InspectorTest.addResult("Removing project:");
+                InspectorTest.testWorkspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, projectRemoved);
+                InspectorTest.testTargetManager.removeTarget(target);
+                target = null;
+            }
 
             function projectRemoved()
             {
+                InspectorTest.testWorkspace.removeEventListener(WebInspector.Workspace.Events.ProjectRemoved, projectRemoved);
                 InspectorTest.addResult("Received project removed event.");
+                fs.reportRemoved();
                 setImmediate(next);
             }
         },
 
         function testURLAfterRenaming(next)
         {
-            var fileSystemPath = "/var/www";
-            var fileSystemProjectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
-            var files = {"/html/foo.js": "<foo content>", "/bar.js": "<bar content>", "/foo/bar/baz.js": "<baz content>"};
-            var uiSourceCodes;
             var index = 0;
             var oldURL;
 
-            createObjects();
+            createWorkspaceWithTarget();
 
             InspectorTest.addResult("Adding file system.");
-            manager.addMockFileSystem(fileSystemPath);
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.mkdir("html").addFile("foo.js", "<foo content>");
+            fs.root.addFile("bar.js", "<bar content>");
+            fs.root.mkdir("foo").mkdir("bar").addFile("baz.js", "<baz content>");
             InspectorTest.addResult("Adding file system mapping.");
-            InspectorTest.testFileSystemMapping.addFileMapping(fileSystemPath, "http://localhost/", "/");
-            manager.addFiles(fileSystemPath, files);
+            fs.addFileMapping("http://localhost/", "/");
+            fs.reportCreated(fileSystemCreated);
+            var uiSourceCodes;
 
-            InspectorTest.addResult("Renaming files:");
-            uiSourceCodes = InspectorTest.testWorkspace.uiSourceCodes();
-            renameNextFile();
+            function fileSystemCreated()
+            {
+                InspectorTest.addResult("Renaming files:");
+                uiSourceCodes = InspectorTest.testWorkspace.uiSourceCodes();
+                renameNextFile();
+            }
 
             function renameNextFile()
             {
@@ -375,10 +299,33 @@
                 ++index;
                 if (index < uiSourceCodes.length)
                     renameNextFile();
-                else
+                else {
+                    fs.reportRemoved();
                     next();
+                }
             }
         },
+
+        function testProjectBasedMapping(next)
+        {
+            createWorkspaceWithTarget();
+
+            InspectorTest.addResult("Adding file system.");
+            var fs = new InspectorTest.TestFileSystem("/var/www");
+            fs.root.mkdir("html").addFile("foo.js", "<foo content>");
+            fs.root.mkdir("html2").addFile("bar.js", "<bar content>");
+            fs.root.addFile(".devtools", JSON.stringify({ mappings: [ { folder: "/html/", url: "http://localhost/h1/" }, { folder: "/html2/", url: "http://localhost/h2/" } ]}));
+            fs.reportCreated(fileSystemCreated);
+
+            function fileSystemCreated()
+            {
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/h1/foo.js", WebInspector.resourceTypes.Script, "<foo content>");
+                InspectorTest.addMockUISourceCodeViaNetwork("http://localhost/h2/bar.js", WebInspector.resourceTypes.Script, "<bar content>");
+                dumpFileSystemUISourceCodesMappings();
+                fs.reportRemoved();
+                next();
+            }
+        }
     ]);
 };
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/workspace-mapping.html b/third_party/WebKit/LayoutTests/inspector/workspace-mapping.html
index e3e0998..cddb07d 100644
--- a/third_party/WebKit/LayoutTests/inspector/workspace-mapping.html
+++ b/third_party/WebKit/LayoutTests/inspector/workspace-mapping.html
@@ -40,8 +40,9 @@
     var projectId = WebInspector.FileSystemWorkspaceBinding.projectId(fileSystemPath);
     fileSystemMapping.addFileSystem("/var/www");
     fileSystemMapping.addFileMapping("/var/www", "http://localhost/", "/localhost/");
-    var workspace = new WebInspector.Workspace(fileSystemMapping);
-    var networkMapping = new WebInspector.NetworkMapping(workspace, WebInspector.fileSystemWorkspaceBinding, fileSystemMapping);
+    var workspace = new WebInspector.Workspace();
+    var fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, workspace);
+    var networkMapping = new WebInspector.NetworkMapping(workspace, fileSystemWorkspaceBinding, fileSystemMapping);
 
     function dumpHasMappingForURL(url)
     {
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child-expected.html
new file mode 100644
index 0000000..19815c77
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child-expected.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<span>Tests</span> anonymous block is collapsed. Passes if this line doesn't change when 'Block' disappears.
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child.html b/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child.html
new file mode 100644
index 0000000..828e16b8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/collapse-anonymous-block-child.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+onload = function() {
+  runAfterLayoutAndPaint(function() {
+    block.style.display = 'none';
+  }, true);
+};
+</script>
+<span>Tests</span> anonymous block is collapsed. Passes if this line doesn't change when 'Block' disappears.
+<div id="block">Block</div>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background-expected.html
new file mode 100644
index 0000000..7713284
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background-expected.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+Tests repaint of composited table cells when their containers change background.
+Passes if there are two green table cells.
+<table>
+  <tr id="row1" style="backface-visibility: hidden; background-color: green">
+    <td style="width: 100px; height: 50px"></td>
+  </tr>
+  <tr id="row2" style="background-color: green">
+    <td style="width: 100px; height: 50px"></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background.html b/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background.html
new file mode 100644
index 0000000..318d37c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/composited-table-cell-container-background.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+onload = function() {
+  runAfterLayoutAndPaint(function() {
+    document.getElementById('row1').style.backgroundColor = 'green';
+    document.getElementById('row2').style.backgroundColor = 'green';
+  }, true);
+};
+</script>
+Tests repaint of composited table cells when their containers change background.
+Passes if there are two green table cells.
+<table>
+  <tr id="row1" style="backface-visibility: hidden; background-color: red">
+    <td style="backface-visibility: hidden; width: 100px; height: 50px"></td>
+  </tr>
+  <tr id="row2" style="background-color: red">
+    <td style="backface-visibility: hidden; width: 100px; height: 50px"></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash-expected.txt b/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash-expected.txt
new file mode 100644
index 0000000..0b145705
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash-expected.txt
@@ -0,0 +1,3 @@
+xxx xxxxxx xxx xx blockquoted.xxxxxxxxxxxxxxxxxxxTest passes if it does not CRASH.
+
+
diff --git a/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash.html b/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash.html
new file mode 100644
index 0000000..753a20f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/text-selection-editing-crash.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<style>
+.box {
+    height: 100px;
+    -webkit-user-modify: read-only;
+}
+</style>
+<script>
+</script>
+Test passes if it does not CRASH.
+<div class="box">
+<script>
+if (window.testRunner) {
+    window.testRunner.dumpAsText();
+    window.testRunner.waitUntilDone();
+}
+
+document.designMode = 'on';
+document.execCommand("selectAll");
+document.execCommand("selectAll");
+document.execCommand("formatblock", false, "h1");
+document.execCommand("InsertHTML", false, "<blockquote type='cite'>xxxx xxxxxx xxx xx blockquoted.</blockquote>");
+document.execCommand("InsertText", false, "xxxxxxxxxxxxxxxxxxx");
+document.execCommand("FindString", true, "d");
+document.execCommand("selectAll");
+document.execCommand("forwardDelete");
+
+window.requestAnimationFrame(function() {
+    window.testRunner.notifyDone();
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/theme/search-field-resuts-decoration-crash-expected.txt b/third_party/WebKit/LayoutTests/paint/theme/search-field-results-decoration-crash-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/paint/theme/search-field-resuts-decoration-crash-expected.txt
rename to third_party/WebKit/LayoutTests/paint/theme/search-field-results-decoration-crash-expected.txt
diff --git a/third_party/WebKit/LayoutTests/paint/theme/search-field-resuts-decoration-crash.html b/third_party/WebKit/LayoutTests/paint/theme/search-field-results-decoration-crash.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/paint/theme/search-field-resuts-decoration-crash.html
rename to third_party/WebKit/LayoutTests/paint/theme/search-field-results-decoration-crash.html
diff --git a/third_party/WebKit/LayoutTests/platform/android/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/android/virtual/stable/webexposed/global-interface-listing-expected.txt
index df2a5676..c30adba 100644
--- a/third_party/WebKit/LayoutTests/platform/android/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/android/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4491,11 +4491,7 @@
     getter currentTranslate
     getter currentView
     getter height
-    getter pixelUnitToMillimeterX
-    getter pixelUnitToMillimeterY
     getter preserveAspectRatio
-    getter screenPixelToMillimeterX
-    getter screenPixelToMillimeterY
     getter useCurrentView
     getter viewBox
     getter viewport
diff --git a/third_party/WebKit/LayoutTests/platform/android/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/android/webexposed/global-interface-listing-expected.txt
index b85f560..4d01841 100644
--- a/third_party/WebKit/LayoutTests/platform/android/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/android/webexposed/global-interface-listing-expected.txt
@@ -4929,11 +4929,7 @@
     getter currentTranslate
     getter currentView
     getter height
-    getter pixelUnitToMillimeterX
-    getter pixelUnitToMillimeterY
     getter preserveAspectRatio
-    getter screenPixelToMillimeterX
-    getter screenPixelToMillimeterY
     getter useCurrentView
     getter viewBox
     getter viewport
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
index 33d4a28c..dd5aa912 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-input-field-expected.txt
@@ -25,9 +25,9 @@
 Gesture scrolling input text should scroll text the specified amount
 PASS box.scrollLeft is 60
 PASS container.scrollLeft is 0
-Gesture scrolling input text past scroll width should scroll container div
+Gesture scrolling input text past scroll width shouldn't scroll container div
 PASS box.scrollLeft is fullyScrolled
-PASS container.scrollLeft is 50
+PASS container.scrollLeft is 0
 ===Testing vertical scroll behavior===
 PASS box.scrollTop is 0
 PASS container.scrollTop is 0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
index e68537aa..564ad1a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/events/touch/gesture/touch-gesture-scroll-listbox-expected.txt
@@ -27,9 +27,12 @@
 PASS container.scrollTop is 0
 PASS box.scrollTop is 0
 PASS container.scrollTop is 0
-Gesture scrolling list past the end should scroll container div
+Gesture scrolling list past the end shouldn't scroll container div
 PASS box.scrollTop is fullyScrolled
-PASS container.scrollTop is 50
+PASS container.scrollTop is 0
+Gesture scrolling list past the end should scroll container div when starting at scroll extent
+PASS box.scrollTop is fullyScrolled
+PASS container.scrollTop is fullyScrolled + 50
 ===Testing horizontal scroll===
 PASS box.scrollLeft is 0
 PASS container.scrollLeft is 0
diff --git a/third_party/WebKit/LayoutTests/storage/indexeddb/cursor-after-range-bug.html b/third_party/WebKit/LayoutTests/storage/indexeddb/cursor-after-range-bug.html
new file mode 100644
index 0000000..2742af9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/storage/indexeddb/cursor-after-range-bug.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>IndexedDB: Reading cursor value after advancing past range</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="resources/testharness-helpers.js"></script>
+<script>
+
+// A regression test for http://crbug.com/487711
+indexeddb_test(
+    function(t, db) {
+        var store = db.createObjectStore('store');
+        for (var i = 0; i < 10; ++i)
+            store.put(i, i);
+    },
+    function(t, db) {
+        var transaction = db.transaction('store', 'readonly');
+        var store = transaction.objectStore('store');
+        var req = store.openCursor();
+        var last_cursor;
+        req.onsuccess = t.step_func(function(evt) {
+            var cursor = evt.target.result;
+            if (cursor) {
+                last_cursor = cursor;
+                cursor.continue();
+            } else {
+                assert_equals(last_cursor.value, undefined);
+                t.done();
+            }
+        });
+        req.onerror = t.step_func(function() {
+            assert_unreached('open should not fail');
+        });
+    },
+    'Access to cursor value after final advance should be undefined'
+);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling-expected.html b/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling-expected.html
new file mode 100644
index 0000000..8711e6c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling-expected.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<svg width="500">
+  <rect width="100" height="100" fill="green"/>
+  <rect width="100" height="100" fill="green" x="100"/>
+  <rect width="100" height="100" fill="green" x="200"/>
+  <rect width="100" height="100" fill="green" x="300"/>
+  <rect width="100" height="100" fill="green" x="400"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling.html b/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling.html
new file mode 100644
index 0000000..23a23fddd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/filters/feConvolveMatrix-error-handling.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<svg width="500" color-interpolation-filters="sRGB">
+  <filter id="convError1" x="0" y="0" width="1" height="1">
+    <feConvolveMatrix order="-1 -1" kernelMatrix="1"/>
+    <feColorMatrix values="1 0 0 0 0, 0 1 0 0 0.5, 0 0 1 0 0, 0 0 0 1 1"/>
+  </filter>
+  <filter id="convError2" x="0" y="0" width="1" height="1">
+    <feConvolveMatrix order="1 1" kernelMatrix="1 1"/>
+    <feColorMatrix values="1 0 0 0 0, 0 1 0 0 0.5, 0 0 1 0 0, 0 0 0 1 1"/>
+  </filter>
+  <filter id="convError3" x="0" y="0" width="1" height="1">
+    <feConvolveMatrix order="1 1" kernelMatrix="1" divisor="0"/>
+    <feColorMatrix values="1 0 0 0 0, 0 1 0 0 0.5, 0 0 1 0 0, 0 0 0 1 1"/>
+  </filter>
+  <filter id="convError4" x="0" y="0" width="1" height="1">
+    <feConvolveMatrix order="1 1" kernelMatrix="1" divisor="1" targetX="1"/>
+    <feColorMatrix values="1 0 0 0 0, 0 1 0 0 0.5, 0 0 1 0 0, 0 0 0 1 1"/>
+  </filter>
+  <filter id="convError5" x="0" y="0" width="1" height="1">
+    <feConvolveMatrix order="1 1" kernelMatrix="1" divisor="1" targetX="0" targetY="1"/>
+    <feColorMatrix values="1 0 0 0 0, 0 1 0 0 0.5, 0 0 1 0 0, 0 0 0 1 1"/>
+  </filter>
+
+  <rect width="500" height="100" fill="red"/>
+  <rect width="100" height="100" fill="red" filter="url(#convError1)"/>
+  <rect width="100" height="100" fill="red" filter="url(#convError2)" x="100"/>
+  <rect width="100" height="100" fill="red" filter="url(#convError3)" x="200"/>
+  <rect width="100" height="100" fill="red" filter="url(#convError4)" x="300"/>
+  <rect width="100" height="100" fill="red" filter="url(#convError5)" x="400"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index d86fba0..69937364 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -240,6 +240,7 @@
 html element abbr
 html element acronym
 html element address
+html element applet
 html element area
     property alt
     property coords
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index d247664..76d38a6 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2665,6 +2665,10 @@
     getter newVersion
     getter oldVersion
     method constructor
+interface IdleDeadline
+    getter didTimeout
+    method constructor
+    method timeRemaining
 interface Image
     method constructor
 interface ImageBitmap
@@ -4393,11 +4397,7 @@
     getter currentTranslate
     getter currentView
     getter height
-    getter pixelUnitToMillimeterX
-    getter pixelUnitToMillimeterY
     getter preserveAspectRatio
-    getter screenPixelToMillimeterX
-    getter screenPixelToMillimeterY
     getter useCurrentView
     getter viewBox
     getter viewport
@@ -5937,6 +5937,7 @@
     attribute innerHeight
     attribute innerWidth
     attribute internals
+    attribute isSecureContext
     attribute layoutTestController
     attribute length
     attribute localStorage
@@ -6066,6 +6067,7 @@
     method blur
     method btoa
     method cancelAnimationFrame
+    method cancelIdleCallback
     method captureEvents
     method clearInterval
     method clearTimeout
@@ -6089,6 +6091,7 @@
     method prompt
     method releaseEvents
     method requestAnimationFrame
+    method requestIdleCallback
     method resizeBy
     method resizeTo
     method scroll
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/timeline-paint-expected.txt b/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/timeline-paint-expected.txt
deleted file mode 100644
index 7cc6934..0000000
--- a/third_party/WebKit/LayoutTests/virtual/threaded/inspector/tracing/timeline-paint-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Tests the Timeline API instrumentation of a paint event
-
-
-Paint Properties:
-{
-    data : {
-        clip : <object>
-        frame : <string>
-        layerId : <number>
-        nodeId : <number>
-    }
-    endTime : <number>
-    frameId : <string>
-    startTime : <number>
-    thread : <string>
-    type : "Paint"
-}
-
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions-expected.txt b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions-expected.txt
index 5053286e..dc44e6b 100644
--- a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions-expected.txt
+++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions-expected.txt
@@ -17,8 +17,9 @@
 PASS setValueCurveAtTime(curve, 0.05, 0.1) did not throw an exception.
 PASS setValueCurveAtTime(curve, 0.00625, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.00625, 0.01) overlaps linearRampToValueAtTime(1, 0.0125).
 PASS setValueCurveAtTime(curve, 0.018750000000000003, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.01875, 0.01) overlaps exponentialRampToValue(1, 0.025).
-PASS setValueCurveAtTime(curve, 0.03125, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.03125, 0.01) overlaps setTargetAtTime(1, 0.0375, 0.1).
-PASS setValueCurveAtTime(curve, 0.04375, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.04375, 0.01) overlaps setValueCurveAtTime(..., 0.05, 0.1).
+PASS setValueCurveAtTime(curve, 0.03125, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.03125, 0.01) overlaps setTargetAtTime(1, 0.03750000000000001, 0.1).
+PASS setValueCurveAtTime(curve, 0.043750000000000004, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.04375, 0.01) overlaps setValueCurveAtTime(..., 0.05, 0.1).
+PASS setValueCurveAtTime(curve, 0.031415926535897934, 0.01) threw NotSupportedError: Failed to execute 'setValueCurveAtTime' on 'AudioParam': setValueCurveAtTime(..., 0.03141592653589793, 0.01) overlaps setTargetAtTime(1, 0.03750000000000001, 0.1).
 PASS setValueCurve overlapping existing automation functions correctly signaled errors.
 
 PASS setValueAtTime(1, 0) did not throw an exception.
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions.html
index 4ab2a2d..7ad31e1 100644
--- a/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions.html
+++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setValueCurve-exceptions.html
@@ -32,29 +32,29 @@
         // Some time that is known to during the setValueCurveTime interval.
         var automationTime = curveStartTime + duration / 2;
 
-        success = success && Should("setValueCurveAtTime(curve, " + curveStartTime + ", " + duration + ")", function() {
+        success = Should("setValueCurveAtTime(curve, " + curveStartTime + ", " + duration + ")", function() {
           g.gain.setValueCurveAtTime(curve, curveStartTime, duration);
-        }).notThrow();
+        }).notThrow() && success;
 
-        success = success && Should("setValueAtTime(1, " + automationTime + ")", function() {
+        success = Should("setValueAtTime(1, " + automationTime + ")", function() {
           g.gain.setValueAtTime(1, automationTime);
-        }).throw("NotSupportedError");
+        }).throw("NotSupportedError") && success;
 
-        success = success && Should("linearRampToValueAtTime(1, " + automationTime + ")", function() {
+        success = Should("linearRampToValueAtTime(1, " + automationTime + ")", function() {
           g.gain.linearRampToValueAtTime(1, automationTime);
-        }).throw("NotSupportedError");
+        }).throw("NotSupportedError") && success;
 
-        success = success && Should("exponentialRampToValueAtTime(1, " + automationTime + ")", function() {
+        success = Should("exponentialRampToValueAtTime(1, " + automationTime + ")", function() {
           g.gain.exponentialRampToValueAtTime(1, automationTime);
-        }).throw("NotSupportedError");
+        }).throw("NotSupportedError") && success;
 
-        success = success && Should("setTargetAtTime(1, " + automationTime + ", 1)", function() {
+        success = Should("setTargetAtTime(1, " + automationTime + ", 1)", function() {
           g.gain.setTargetAtTime(1, automationTime, 1);
-        }).throw("NotSupportedError");
+        }).throw("NotSupportedError") && success;
 
-        success = success && Should("setValueAtTime(1, " + (curveStartTime + 1.1 * duration) + ")", function() {
+        success = Should("setValueAtTime(1, " + (curveStartTime + 1.1 * duration) + ")", function() {
           g.gain.setValueAtTime(1, curveStartTime + 1.1 * duration);
-        }).notThrow();
+        }).notThrow() && success;
 
         var prefix = "Automation functions overlapping an existing setValueCurveAtTime";
         if (success)
@@ -72,39 +72,45 @@
 
         var curve = new Float32Array(2);
         // Start time and duration for setValueCurveAtTime
-        var startTime = 0
+        var startTime = 0;
         var timeInterval = testDurationSec / 10;
 
         startTime += timeInterval;
-        success = success && Should("linearRampToValueAtTime(1, " + startTime + ")", function () {
+        success = Should("linearRampToValueAtTime(1, " + startTime + ")", function () {
           g.gain.linearRampToValueAtTime(1, startTime);
-        }).notThrow();
+        }).notThrow() && success;
       
         startTime += timeInterval;
-        success = success && Should("exponentialRampToValueAtTime(1, " + startTime + ")", function () {
+        success = Should("exponentialRampToValueAtTime(1, " + startTime + ")", function () {
           g.gain.exponentialRampToValueAtTime(1, startTime);
-        }).notThrow();
+        }).notThrow() && success;
       
         startTime += timeInterval;
-        success = success && Should("setTargetAtTime(1, " + startTime + ", 0.1)", function () {
+        success = Should("setTargetAtTime(1, " + startTime + ", 0.1)", function () {
           g.gain.setTargetAtTime(1, startTime, 0.1);
-        }).notThrow();
+        }).notThrow() && success;
       
         startTime += timeInterval;
-        success = success && Should("setValueCurveAtTime(curve, " + startTime + ", 0.1)", function () {
+        success = Should("setValueCurveAtTime(curve, " + startTime + ", 0.1)", function () {
           g.gain.setValueCurveAtTime(curve, startTime, 0.1);
-        }).notThrow();
+        }).notThrow() && success;
 
         // Now try to setValueCurve that overlaps each of the above automations
         startTime = timeInterval / 2;
 
         for (var k = 0; k < 4; ++k) {
-          success = success && Should("setValueCurveAtTime(curve, " + startTime + ", 0.01)", function () {
-            g.gain.setValueCurveAtTime(curve, startTime, 0.01);
-          }).throw("NotSupportedError");
-          startTime += timeInterval;
+          var time = startTime + timeInterval * k;
+          success = Should("setValueCurveAtTime(curve, " + time + ", 0.01)", function () {
+            g.gain.setValueCurveAtTime(curve, time, 0.01);
+          }).throw("NotSupportedError") && success;
         }
 
+        // One last test that prints out lots of digits for the time.
+        var time = Math.PI / 100;
+        success = Should("setValueCurveAtTime(curve, " + time + ", 0.01)", function () {
+          g.gain.setValueCurveAtTime(curve, time, 0.01);
+        }).throw("NotSupportedError") && success;
+
         var prefix = "setValueCurve overlapping existing automation functions";
         if (success)
           testPassed(prefix + " correctly signaled errors.\n");
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index 1430b4f..5ba3374 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -251,6 +251,7 @@
 html element abbr
 html element acronym
 html element address
+html element applet
 html element area
     property alt
     property coords
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 3f2a4ab..ec85131b0 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4910,11 +4910,7 @@
     getter currentTranslate
     getter currentView
     getter height
-    getter pixelUnitToMillimeterX
-    getter pixelUnitToMillimeterY
     getter preserveAspectRatio
-    getter screenPixelToMillimeterX
-    getter screenPixelToMillimeterY
     getter useCurrentView
     getter viewBox
     getter viewport
@@ -6644,6 +6640,7 @@
     attribute innerHeight
     attribute innerWidth
     attribute internals
+    attribute isSecureContext
     attribute layoutTestController
     attribute length
     attribute localStorage
diff --git a/third_party/WebKit/ManualTests/webaudio/audiobuffersource-looping.html b/third_party/WebKit/ManualTests/webaudio/audiobuffersource-looping.html
new file mode 100644
index 0000000..0f2908a
--- /dev/null
+++ b/third_party/WebKit/ManualTests/webaudio/audiobuffersource-looping.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+  <head>
+    <title>AudioBufferSource with Looping Enabled then Disabled</title>
+    <script>
+      var context = new AudioContext();
+      // Launch countdown example
+      var url = "http://www.nasa.gov/mp3/590318main_ringtone_135_launch.mp3";
+
+      function enableButtons()
+      {
+        document.getElementById("Original").disabled = false;
+        document.getElementById("Test").disabled = false;
+      }
+
+      function disableButtons()
+      {
+        document.getElementById("Original").disabled = true;
+        document.getElementById("Test").disabled = true;
+      }
+
+      function playClip(loopEndTime) {
+        disableButtons();
+
+        var request = new XMLHttpRequest();
+        request.open("GET", url, true);
+        request.responseType = "arraybuffer";
+        request.onload = function () {
+          context.decodeAudioData(
+            request.response,
+            function (buffer) {
+              var source = context.createBufferSource();
+              source.buffer = buffer;
+              source.connect(context.destination);
+              source.onended = enableButtons;
+              source.start();
+              // If a loopEndTime is given, enable looping and stop looping after loopEndTime ms.
+              if (loopEndTime) {
+                // These limits were selected to cause the word "eight" to be repeated in the given
+                // URL.  If the URL is updated these values probably need to be changed.
+                source.loopStart = 2.2;
+                source.loopEnd = 3;
+                source.loop = true;
+
+                setTimeout(function () {
+                    source.loop = false;
+                  },
+                  loopEndTime);
+              }
+            },
+            function () {
+              alert("Could not get audio clip");
+            });
+        };
+        request.send();
+      }
+    </script>
+  </head>
+
+  <body>
+    <h1>AudioBufferSource with looping enabled then disabled</h1>
+    <p>
+      This tests an AudioBufferSource node is not prematurely stopped if looping is enabled for the
+      buffer and then disabled.  This can't be tested in an offline context until suspend/resume
+      support is added for an offline context.
+    </p>
+
+    <p>Press "Original" to play the clip in its entirety (15 sec).</p>
+
+    <p>
+      Press "Test" to run the test.  A part of the clip will be looped for a while and then looping
+      will be turned off.  (You should hear "eight" repeated about four times.)  The rest of the
+      clip should be heard in its entirety.  The onended event should also be fired, enabling the
+      buttons again.  If the buttons are not enabled, the test has failed.  File a new bug at <a
+      href="http://crbug.com/new">crbug.com/new</a>.
+    </p>
+
+    <button id="Original" onclick="playClip()">Original</button>
+    <button id="Test" onclick="playClip(5000)">Test</button>
+  </body>
+</html>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
index c83dd50..9b40fb2 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMWrapper.cpp
@@ -152,7 +152,7 @@
     // TODO(jochen): Currently, Location is the only object for which we can reach this code path. Should be generalized.
     ExceptionState exceptionState(ExceptionState::ConstructionContext, "Location", isolate->GetCurrentContext()->Global(), isolate);
     LocalDOMWindow* callingWindow = callingDOMWindow(isolate);
-    DOMWindow* targetWindow = toFrameIfNotDetached(m_context)->domWindow();
+    DOMWindow* targetWindow = toDOMWindow(m_context);
     exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(callingWindow), targetWindow->crossDomainAccessErrorMessage(callingWindow));
     exceptionState.throwIfNeeded();
 }
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomEventCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomEventCustom.cpp
index 6e03109..89bd349 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomEventCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CustomEventCustom.cpp
@@ -35,6 +35,7 @@
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
 #include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8CustomEventInit.h"
 #include "bindings/core/v8/V8DOMWrapper.h"
 #include "bindings/core/v8/V8Event.h"
 #include "bindings/core/v8/V8HiddenValue.h"
@@ -49,6 +50,48 @@
     return detail;
 }
 
+void V8CustomEvent::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
+{
+    ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomEvent", info.Holder(), info.GetIsolate());
+    if (UNLIKELY(info.Length() < 1)) {
+        setMinimumArityTypeError(exceptionState, 1, info.Length());
+        exceptionState.throwIfNeeded();
+        return;
+    }
+
+    V8StringResource<> type = info[0];
+    if (!type.prepare())
+        return;
+
+    CustomEventInit eventInitDict;
+    if (!isUndefinedOrNull(info[1])) {
+        if (!info[1]->IsObject()) {
+            exceptionState.throwTypeError("parameter 2 ('eventInitDict') is not an object.");
+            exceptionState.throwIfNeeded();
+            return;
+        }
+        V8CustomEventInit::toImpl(info.GetIsolate(), info[1], eventInitDict, exceptionState);
+        if (exceptionState.throwIfNeeded())
+            return;
+    }
+
+    RefPtrWillBeRawPtr<CustomEvent> impl = CustomEvent::create(type, eventInitDict);
+    v8::Local<v8::Object> wrapper = info.Holder();
+    wrapper = impl->associateWithWrapper(info.GetIsolate(), &V8CustomEvent::wrapperTypeInfo, wrapper);
+
+    // TODO(bashi): Workaround for http://crbug.com/529941. We need to store
+    // |detail| as a hidden value to avoid cycle references.
+    if (eventInitDict.hasDetail()) {
+        v8::Local<v8::Value> v8Detail = eventInitDict.detail().v8Value();
+        cacheState(info.GetIsolate(), wrapper, v8Detail);
+        // When a custom event is created in an isolated world, serialize
+        // |detail| and store it in |impl| so that we can clone |detail|
+        // when the getter of |detail| is called in the main world later.
+        if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld())
+            impl->setSerializedDetail(SerializedScriptValueFactory::instance().createAndSwallowExceptions(info.GetIsolate(), v8Detail));
+    }
+    v8SetReturnValue(info, wrapper);
+}
 
 void V8CustomEvent::detailAttributeGetterCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
 {
@@ -63,10 +106,16 @@
 
     // Be careful not to return a V8 value which is created in different world.
     v8::Local<v8::Value> detail;
-    if (SerializedScriptValue* serializedValue = event->serializedDetail())
+    if (SerializedScriptValue* serializedValue = event->serializedDetail()) {
         detail = serializedValue->deserialize();
-    else
-        detail = event->detail().v8ValueFor(ScriptState::current(info.GetIsolate()));
+    } else if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld()) {
+        v8::Local<v8::Value> mainWorldDetail = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::detail(info.GetIsolate()));
+        if (!mainWorldDetail.IsEmpty()) {
+            event->setSerializedDetail(SerializedScriptValueFactory::instance().createAndSwallowExceptions(info.GetIsolate(), mainWorldDetail));
+            detail = event->serializedDetail()->deserialize();
+        }
+    }
+
     // |detail| should be null when it is an empty handle because its default value is null.
     if (detail.IsEmpty())
         detail = v8::Null(info.GetIsolate());
diff --git a/third_party/WebKit/Source/build/scripts/templates/MakeNames.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/MakeNames.cpp.tmpl
index c9098ca..ed0c0316 100644
--- a/third_party/WebKit/Source/build/scripts/templates/MakeNames.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/MakeNames.cpp.tmpl
@@ -17,9 +17,7 @@
 
 using namespace WTF;
 
-const int k{{suffix}}NameCount = {{entries|length}};
-
-void* {{suffix}}NamesStorage[k{{suffix}}NameCount * ((sizeof(AtomicString) + sizeof(void *) - 1) / sizeof(void *))];
+void* {{suffix}}NamesStorage[{{namespace}}{{suffix}}NamesCount * ((sizeof(AtomicString) + sizeof(void *) - 1) / sizeof(void *))];
 
 {% for entry in entries|sort(attribute='name', case_sensitive=True) %}
 {% filter enable_conditional(entry.Conditional) %}
diff --git a/third_party/WebKit/Source/build/scripts/templates/MakeNames.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/MakeNames.h.tmpl
index 7d01d3df..e1ff10b 100644
--- a/third_party/WebKit/Source/build/scripts/templates/MakeNames.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/MakeNames.h.tmpl
@@ -32,6 +32,8 @@
 {% endfilter %}
 {% endfor %}
 
+const unsigned {{namespace}}{{suffix}}NamesCount = {{entries|length}};
+
 {{symbol_export}}void init{{suffix}}();
 
 } // {{namespace}}Names
diff --git a/third_party/WebKit/Source/core/Init.cpp b/third_party/WebKit/Source/core/Init.cpp
index 1576624..02fe099 100644
--- a/third_party/WebKit/Source/core/Init.cpp
+++ b/third_party/WebKit/Source/core/Init.cpp
@@ -58,7 +58,6 @@
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityPolicy.h"
 #include "wtf/Partitions.h"
-#include "wtf/text/StringStatics.h"
 
 namespace blink {
 
@@ -76,6 +75,32 @@
 {
     ASSERT(!m_isInited);
     m_isInited = true;
+    // Note: in order to add core static strings for a new module (1)
+    // the value of 'coreStaticStringsCount' must be updated with the
+    // added strings count, (2) if the added strings are quialified names
+    // the 'qualifiedNamesCount' must be updated as well, (3) the strings
+    // 'init()' function call must be added.
+    // TODO(mikhail.pozdnyakov@intel.com): We should generate static strings initialization code.
+    const unsigned qualifiedNamesCount = HTMLNames::HTMLTagsCount + HTMLNames::HTMLAttrsCount
+        + MathMLNames::MathMLTagsCount + MathMLNames::MathMLAttrsCount
+        + SVGNames::SVGTagsCount + SVGNames::SVGAttrsCount
+        + XLinkNames::XLinkAttrsCount
+        + XMLNSNames::XMLNSAttrsCount
+        + XMLNames::XMLAttrsCount;
+
+    const unsigned coreStaticStringsCount = qualifiedNamesCount
+        + EventNames::EventNamesCount
+        + EventTargetNames::EventTargetNamesCount
+        + EventTypeNames::EventTypeNamesCount
+        + FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount
+        + FontFamilyNames::FontFamilyNamesCount
+        + HTMLTokenizerNames::HTMLTokenizerNamesCount
+        + InputTypeNames::InputTypeNamesCount
+        + MediaFeatureNames::MediaFeatureNamesCount
+        + MediaTypeNames::MediaTypeNamesCount;
+
+    StringImpl::reserveStaticStringsCapacityForSize(coreStaticStringsCount + StringImpl::allStaticStrings().size());
+    QualifiedName::initAndReserveCapacityForSize(qualifiedNamesCount);
 
     HTMLNames::init();
     SVGNames::init();
@@ -97,13 +122,8 @@
     CSSPrimitiveValue::initUnitTable();
     CSSParserTokenRange::initStaticEOFToken();
 
-    // It would make logical sense to do this in WTF::initialize() but there are
-    // ordering dependencies, e.g. about "xmlns".
-    WTF::StringStatics::init();
-
     StyleChangeExtraData::init();
 
-    QualifiedName::init();
     EventTracer::initialize();
     KURL::initialize();
     SecurityPolicy::init();
diff --git a/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.cpp b/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.cpp
index ca8b739..c5bdbe4b 100644
--- a/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.cpp
+++ b/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.cpp
@@ -7,7 +7,7 @@
 
 #include "core/animation/ElementAnimations.h"
 #include "core/animation/css/CSSAnimatableValueFactory.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSImageValue.h"
 #include "core/css/CSSPrimitiveValue.h"
 #include "core/css/CSSQuadValue.h"
@@ -48,8 +48,14 @@
     // FIXME: should not require resolving styles for inherit/initial/unset.
     if (value.isCSSWideKeyword())
         return true;
-    if (value.isBasicShapeValue())
-        return interpolationRequiresStyleResolve(toCSSBasicShapeValue(value));
+    if (value.isBasicShapeCircleValue())
+        return interpolationRequiresStyleResolve(toCSSBasicShapeCircleValue(value));
+    if (value.isBasicShapeEllipseValue())
+        return interpolationRequiresStyleResolve(toCSSBasicShapeEllipseValue(value));
+    if (value.isBasicShapePolygonValue())
+        return interpolationRequiresStyleResolve(toCSSBasicShapePolygonValue(value));
+    if (value.isBasicShapeInsetValue())
+        return interpolationRequiresStyleResolve(toCSSBasicShapeInsetValue(value));
     if (value.isPrimitiveValue())
         return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value));
     if (value.isQuadValue())
@@ -133,9 +139,27 @@
         || interpolationRequiresStyleResolve(pair.second());
 }
 
-bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShapeValue& shape)
+bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShapeCircleValue& shape)
 {
-    // FIXME: Should determine the specific shape, and inspect the members.
+    // FIXME: Should inspect the members.
+    return false;
+}
+
+bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShapeEllipseValue& shape)
+{
+    // FIXME: Should inspect the members.
+    return false;
+}
+
+bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShapePolygonValue& shape)
+{
+    // FIXME: Should inspect the members.
+    return false;
+}
+
+bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSBasicShapeInsetValue& shape)
+{
+    // FIXME: Should inspect the members.
     return false;
 }
 
diff --git a/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.h b/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.h
index 021d43c..4c25cc8 100644
--- a/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.h
+++ b/third_party/WebKit/Source/core/animation/DeferredLegacyStyleInterpolation.h
@@ -12,7 +12,10 @@
 
 namespace blink {
 
-class CSSBasicShapeValue;
+class CSSBasicShapeCircleValue;
+class CSSBasicShapeEllipseValue;
+class CSSBasicShapePolygonValue;
+class CSSBasicShapeInsetValue;
 class CSSImageValue;
 class CSSPrimitiveValue;
 class CSSQuadValue;
@@ -37,7 +40,10 @@
     static bool interpolationRequiresStyleResolve(const CSSSVGDocumentValue&);
     static bool interpolationRequiresStyleResolve(const CSSValueList&);
     static bool interpolationRequiresStyleResolve(const CSSValuePair&);
-    static bool interpolationRequiresStyleResolve(const CSSBasicShapeValue&);
+    static bool interpolationRequiresStyleResolve(const CSSBasicShapeCircleValue&);
+    static bool interpolationRequiresStyleResolve(const CSSBasicShapeEllipseValue&);
+    static bool interpolationRequiresStyleResolve(const CSSBasicShapePolygonValue&);
+    static bool interpolationRequiresStyleResolve(const CSSBasicShapeInsetValue&);
     static bool interpolationRequiresStyleResolve(const CSSQuadValue&);
 
 private:
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 249dccc..81ea4225 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -1021,7 +1021,7 @@
             'css/BasicShapeFunctions.cpp',
             'css/BinaryDataFontFaceSource.cpp',
             'css/BinaryDataFontFaceSource.h',
-            'css/CSSBasicShapeValue.cpp',
+            'css/CSSBasicShapeValues.cpp',
             'css/CSSBorderImage.cpp',
             'css/CSSBorderImage.h',
             'css/CSSBorderImageSliceValue.cpp',
@@ -1740,15 +1740,16 @@
             'inspector/ScriptCallStack.h',
             'inspector/ScriptDebuggerBase.cpp',
             'inspector/ScriptDebuggerBase.h',
-            'inspector/V8DebuggerAgent.cpp',
-            'inspector/V8DebuggerAgent.h',
-            'inspector/V8AsyncCallTracker.cpp',
-            'inspector/V8AsyncCallTracker.h',
             'inspector/v8/InspectorWrapper.cpp',
             'inspector/v8/InspectorWrapper.h',
             'inspector/v8/JavaScriptCallFrame.cpp',
             'inspector/v8/JavaScriptCallFrame.h',
             'inspector/v8/ScriptBreakpoint.h',
+            'inspector/v8/V8AsyncCallTracker.cpp',
+            'inspector/v8/V8AsyncCallTracker.h',
+            'inspector/v8/V8DebuggerAgent.h',
+            'inspector/v8/V8DebuggerAgentImpl.cpp',
+            'inspector/v8/V8DebuggerAgentImpl.h',
             'inspector/v8/V8Debugger.h',
             'inspector/v8/V8DebuggerClient.h',
             'inspector/v8/V8DebuggerImpl.cpp',
@@ -3801,6 +3802,7 @@
             'editing/InputMethodControllerTest.cpp',
             'editing/iterators/CharacterIteratorTest.cpp',
             'editing/iterators/SearchBufferTest.cpp',
+            'editing/iterators/SimplifiedBackwardsTextIteratorTest.cpp',
             'editing/iterators/TextIteratorTest.cpp',
             'editing/markers/DocumentMarkerControllerTest.cpp',
             'editing/PositionTest.cpp',
diff --git a/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp b/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
index a0a9575..50bc0e3 100644
--- a/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
+++ b/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp
@@ -30,7 +30,7 @@
 #include "config.h"
 #include "core/css/BasicShapeFunctions.h"
 
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSPrimitiveValueMappings.h"
 #include "core/css/CSSValuePair.h"
 #include "core/css/CSSValuePool.h"
@@ -65,7 +65,7 @@
     return nullptr;
 }
 
-PassRefPtrWillBeRawPtr<CSSBasicShapeValue> valueForBasicShape(const ComputedStyle& style, const BasicShape* basicShape)
+PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const ComputedStyle& style, const BasicShape* basicShape)
 {
     CSSValuePool& pool = cssValuePool();
     switch (basicShape->type()) {
@@ -194,12 +194,11 @@
     return BasicShapeRadius(convertToLength(state, radius.get()));
 }
 
-PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSBasicShapeValue& basicShapeValue)
+PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSValue& basicShapeValue)
 {
     RefPtr<BasicShape> basicShape;
 
-    switch (basicShapeValue.type()) {
-    case CSSBasicShapeValue::CSSBasicShapeCircleType: {
+    if (basicShapeValue.isBasicShapeCircleValue()) {
         const CSSBasicShapeCircleValue& circleValue = toCSSBasicShapeCircleValue(basicShapeValue);
         RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create();
 
@@ -208,9 +207,7 @@
         circle->setRadius(cssValueToBasicShapeRadius(state, circleValue.radius()));
 
         basicShape = circle.release();
-        break;
-    }
-    case CSSBasicShapeValue::CSSBasicShapeEllipseType: {
+    } else if (basicShapeValue.isBasicShapeEllipseValue()) {
         const CSSBasicShapeEllipseValue& ellipseValue = toCSSBasicShapeEllipseValue(basicShapeValue);
         RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create();
 
@@ -220,9 +217,7 @@
         ellipse->setRadiusY(cssValueToBasicShapeRadius(state, ellipseValue.radiusY()));
 
         basicShape = ellipse.release();
-        break;
-    }
-    case CSSBasicShapeValue::CSSBasicShapePolygonType: {
+    } else if (basicShapeValue.isBasicShapePolygonValue()) {
         const CSSBasicShapePolygonValue& polygonValue = toCSSBasicShapePolygonValue(basicShapeValue);
         RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create();
 
@@ -232,9 +227,7 @@
             polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get()));
 
         basicShape = polygon.release();
-        break;
-    }
-    case CSSBasicShapeValue::CSSBasicShapeInsetType: {
+    } else if (basicShapeValue.isBasicShapeInsetValue()) {
         const CSSBasicShapeInsetValue& rectValue = toCSSBasicShapeInsetValue(basicShapeValue);
         RefPtr<BasicShapeInset> rect = BasicShapeInset::create();
 
@@ -249,10 +242,8 @@
         rect->setBottomLeftRadius(convertToLengthSize(state, rectValue.bottomLeftRadius()));
 
         basicShape = rect.release();
-        break;
-    }
-    default:
-        break;
+    } else {
+        ASSERT_NOT_REACHED();
     }
 
     return basicShape.release();
diff --git a/third_party/WebKit/Source/core/css/BasicShapeFunctions.h b/third_party/WebKit/Source/core/css/BasicShapeFunctions.h
index e9ecc35e..083dbf1 100644
--- a/third_party/WebKit/Source/core/css/BasicShapeFunctions.h
+++ b/third_party/WebKit/Source/core/css/BasicShapeFunctions.h
@@ -43,8 +43,8 @@
 class StyleResolverState;
 class ComputedStyle;
 
-PassRefPtrWillBeRawPtr<CSSBasicShapeValue> valueForBasicShape(const ComputedStyle&, const BasicShape*);
-PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState&, const CSSBasicShapeValue&);
+PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const ComputedStyle&, const BasicShape*);
+PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState&, const CSSValue&);
 FloatPoint floatPointForCenterCoordinate(const BasicShapeCenterCoordinate&, const BasicShapeCenterCoordinate&, FloatSize);
 
 }
diff --git a/third_party/WebKit/Source/core/css/CSSBasicShapeValue.cpp b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
similarity index 87%
rename from third_party/WebKit/Source/core/css/CSSBasicShapeValue.cpp
rename to third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
index e76fd9e..f291e29 100644
--- a/third_party/WebKit/Source/core/css/CSSBasicShapeValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
@@ -28,7 +28,7 @@
  */
 
 #include "config.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 
 #include "core/css/CSSValuePair.h"
 #include "core/css/CSSValuePool.h"
@@ -39,60 +39,6 @@
 
 namespace blink {
 
-String CSSBasicShapeValue::customCSSText() const
-{
-    switch (m_type) {
-    case CSSBasicShapeEllipseType:
-        return toCSSBasicShapeEllipseValue(this)->customShapeCSSText();
-    case CSSBasicShapePolygonType:
-        return toCSSBasicShapePolygonValue(this)->customShapeCSSText();
-    case CSSBasicShapeCircleType:
-        return toCSSBasicShapeCircleValue(this)->customShapeCSSText();
-    case CSSBasicShapeInsetType:
-        return toCSSBasicShapeInsetValue(this)->customShapeCSSText();
-    }
-    ASSERT_NOT_REACHED();
-    return String();
-}
-
-bool CSSBasicShapeValue::equals(const CSSBasicShapeValue& other) const
-{
-    if (m_type != other.m_type)
-        return false;
-
-    switch (m_type) {
-    case CSSBasicShapeEllipseType:
-        return toCSSBasicShapeEllipseValue(this)->equals(toCSSBasicShapeEllipseValue(other));
-    case CSSBasicShapePolygonType:
-        return toCSSBasicShapePolygonValue(this)->equals(toCSSBasicShapePolygonValue(other));
-    case CSSBasicShapeCircleType:
-        return toCSSBasicShapeCircleValue(this)->equals(toCSSBasicShapeCircleValue(other));
-    case CSSBasicShapeInsetType:
-        return toCSSBasicShapeInsetValue(this)->equals(toCSSBasicShapeInsetValue(other));
-    }
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-DEFINE_TRACE_AFTER_DISPATCH(CSSBasicShapeValue)
-{
-    switch (m_type) {
-    case CSSBasicShapeEllipseType:
-        toCSSBasicShapeEllipseValue(this)->traceAfterDispatch(visitor);
-        break;
-    case CSSBasicShapePolygonType:
-        toCSSBasicShapePolygonValue(this)->traceAfterDispatch(visitor);
-        break;
-    case CSSBasicShapeCircleType:
-        toCSSBasicShapeCircleValue(this)->traceAfterDispatch(visitor);
-        break;
-    case CSSBasicShapeInsetType:
-        toCSSBasicShapeInsetValue(this)->traceAfterDispatch(visitor);
-        break;
-    }
-    CSSValue::traceAfterDispatch(visitor);
-}
-
 static String buildCircleString(const String& radius, const String& centerX, const String& centerY)
 {
     char at[] = "at";
@@ -157,7 +103,7 @@
     return CSSValuePair::create(cssValuePool().createValue(side), amount.release(), CSSValuePair::KeepIdenticalValues);
 }
 
-String CSSBasicShapeCircleValue::customShapeCSSText() const
+String CSSBasicShapeCircleValue::customCSSText() const
 {
     RefPtrWillBeRawPtr<CSSValuePair> normalizedCX = buildSerializablePositionOffset(m_centerX, CSSValueLeft);
     RefPtrWillBeRawPtr<CSSValuePair> normalizedCY = buildSerializablePositionOffset(m_centerY, CSSValueTop);
@@ -217,7 +163,7 @@
     return result.toString();
 }
 
-String CSSBasicShapeEllipseValue::customShapeCSSText() const
+String CSSBasicShapeEllipseValue::customCSSText() const
 {
     RefPtrWillBeRawPtr<CSSValuePair> normalizedCX = buildSerializablePositionOffset(m_centerX, CSSValueLeft);
     RefPtrWillBeRawPtr<CSSValuePair> normalizedCY = buildSerializablePositionOffset(m_centerY, CSSValueTop);
@@ -296,7 +242,7 @@
     return result.toString();
 }
 
-String CSSBasicShapePolygonValue::customShapeCSSText() const
+String CSSBasicShapePolygonValue::customCSSText() const
 {
     Vector<String> points;
     points.reserveInitialCapacity(m_values.size());
@@ -403,7 +349,7 @@
     height = cornerRadius->second().cssText();
 }
 
-String CSSBasicShapeInsetValue::customShapeCSSText() const
+String CSSBasicShapeInsetValue::customCSSText() const
 {
     String topLeftRadiusWidth;
     String topLeftRadiusHeight;
diff --git a/third_party/WebKit/Source/core/css/CSSBasicShapeValue.h b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.h
similarity index 77%
rename from third_party/WebKit/Source/core/css/CSSBasicShapeValue.h
rename to third_party/WebKit/Source/core/css/CSSBasicShapeValues.h
index 9bb1b4f..1a088c95 100644
--- a/third_party/WebKit/Source/core/css/CSSBasicShapeValue.h
+++ b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.h
@@ -27,8 +27,8 @@
  * SUCH DAMAGE.
  */
 
-#ifndef CSSBasicShapeValue_h
-#define CSSBasicShapeValue_h
+#ifndef CSSBasicShapeValues_h
+#define CSSBasicShapeValues_h
 
 #include "core/css/CSSPrimitiveValue.h"
 #include "core/css/CSSValue.h"
@@ -40,46 +40,11 @@
 
 namespace blink {
 
-// TODO(Oilpan): the GC plugin is not capable of understanding that
-// the traceAfterDispatch() method covers subtypes of CSSBasicShapeValue.
-// Temporarily exempt it from being checked
-class GC_PLUGIN_IGNORE("535448") CORE_EXPORT CSSBasicShapeValue : public CSSValue {
-public:
-    enum Type {
-        CSSBasicShapeEllipseType,
-        CSSBasicShapePolygonType,
-        CSSBasicShapeCircleType,
-        CSSBasicShapeInsetType
-    };
-
-    String customCSSText() const;
-
-    bool equals(const CSSBasicShapeValue& other) const;
-
-    Type type() const { return m_type; }
-    bool isEllipse() const { return m_type == CSSBasicShapeEllipseType; }
-    bool isPolygon() const { return m_type == CSSBasicShapePolygonType; }
-    bool isCircle() const { return m_type == CSSBasicShapeCircleType; }
-    bool isInset() const { return m_type == CSSBasicShapeInsetType; }
-
-    DECLARE_TRACE_AFTER_DISPATCH();
-
-protected:
-    CSSBasicShapeValue(Type type)
-        : CSSValue(BasicShapeClass)
-        , m_type(type)
-    {
-    }
-
-private:
-    Type m_type;
-};
-
-class CSSBasicShapeCircleValue final : public CSSBasicShapeValue {
+class CSSBasicShapeCircleValue final : public CSSValue {
 public:
     static PassRefPtrWillBeRawPtr<CSSBasicShapeCircleValue> create() { return adoptRefWillBeNoop(new CSSBasicShapeCircleValue); }
 
-    String customShapeCSSText() const;
+    String customCSSText() const;
     bool equals(const CSSBasicShapeCircleValue&) const;
 
     CSSValue* centerX() const { return m_centerX.get(); }
@@ -95,7 +60,7 @@
 
 private:
     CSSBasicShapeCircleValue()
-        : CSSBasicShapeValue(CSSBasicShapeCircleType)
+        : CSSValue(BasicShapeCircleClass)
         { }
 
     RefPtrWillBeMember<CSSValue> m_centerX;
@@ -103,11 +68,11 @@
     RefPtrWillBeMember<CSSPrimitiveValue> m_radius;
 };
 
-class CSSBasicShapeEllipseValue final : public CSSBasicShapeValue {
+class CSSBasicShapeEllipseValue final : public CSSValue {
 public:
     static PassRefPtrWillBeRawPtr<CSSBasicShapeEllipseValue> create() { return adoptRefWillBeNoop(new CSSBasicShapeEllipseValue); }
 
-    String customShapeCSSText() const;
+    String customCSSText() const;
     bool equals(const CSSBasicShapeEllipseValue&) const;
 
     CSSValue* centerX() const { return m_centerX.get(); }
@@ -125,7 +90,7 @@
 
 private:
     CSSBasicShapeEllipseValue()
-        : CSSBasicShapeValue(CSSBasicShapeEllipseType)
+        : CSSValue(BasicShapeEllipseClass)
         { }
 
     RefPtrWillBeMember<CSSValue> m_centerX;
@@ -134,7 +99,7 @@
     RefPtrWillBeMember<CSSPrimitiveValue> m_radiusY;
 };
 
-class CSSBasicShapePolygonValue final : public CSSBasicShapeValue {
+class CSSBasicShapePolygonValue final : public CSSValue {
 public:
     static PassRefPtrWillBeRawPtr<CSSBasicShapePolygonValue> create() { return adoptRefWillBeNoop(new CSSBasicShapePolygonValue); }
 
@@ -152,14 +117,14 @@
     void setWindRule(WindRule w) { m_windRule = w; }
     WindRule windRule() const { return m_windRule; }
 
-    String customShapeCSSText() const;
+    String customCSSText() const;
     bool equals(const CSSBasicShapePolygonValue&) const;
 
     DECLARE_TRACE_AFTER_DISPATCH();
 
 private:
     CSSBasicShapePolygonValue()
-        : CSSBasicShapeValue(CSSBasicShapePolygonType),
+        : CSSValue(BasicShapePolygonClass),
         m_windRule(RULE_NONZERO)
     { }
 
@@ -167,7 +132,7 @@
     WindRule m_windRule;
 };
 
-class CSSBasicShapeInsetValue final : public CSSBasicShapeValue {
+class CSSBasicShapeInsetValue final : public CSSValue {
 public:
     static PassRefPtrWillBeRawPtr<CSSBasicShapeInsetValue> create() { return adoptRefWillBeNoop(new CSSBasicShapeInsetValue); }
 
@@ -215,14 +180,14 @@
     void setBottomRightRadius(PassRefPtrWillBeRawPtr<CSSValuePair> radius) { m_bottomRightRadius = radius; }
     void setBottomLeftRadius(PassRefPtrWillBeRawPtr<CSSValuePair> radius) { m_bottomLeftRadius = radius; }
 
-    String customShapeCSSText() const;
+    String customCSSText() const;
     bool equals(const CSSBasicShapeInsetValue&) const;
 
     DECLARE_TRACE_AFTER_DISPATCH();
 
 private:
     CSSBasicShapeInsetValue()
-        : CSSBasicShapeValue(CSSBasicShapeInsetType)
+        : CSSValue(BasicShapeInsetClass)
         { }
 
     RefPtrWillBeMember<CSSPrimitiveValue> m_top;
@@ -236,13 +201,11 @@
     RefPtrWillBeMember<CSSValuePair> m_bottomLeftRadius;
 };
 
-DEFINE_CSS_VALUE_TYPE_CASTS(CSSBasicShapeValue, isBasicShapeValue());
-
-DEFINE_TYPE_CASTS(CSSBasicShapeCircleValue, CSSBasicShapeValue, shape, shape->isCircle(), shape.isCircle());
-DEFINE_TYPE_CASTS(CSSBasicShapeEllipseValue, CSSBasicShapeValue, shape, shape->isEllipse(), shape.isEllipse());
-DEFINE_TYPE_CASTS(CSSBasicShapePolygonValue, CSSBasicShapeValue, shape, shape->isPolygon(), shape.isPolygon());
-DEFINE_TYPE_CASTS(CSSBasicShapeInsetValue, CSSBasicShapeValue, shape, shape->isInset(), shape.isInset());
+DEFINE_CSS_VALUE_TYPE_CASTS(CSSBasicShapeCircleValue, isBasicShapeCircleValue());
+DEFINE_CSS_VALUE_TYPE_CASTS(CSSBasicShapeEllipseValue, isBasicShapeEllipseValue());
+DEFINE_CSS_VALUE_TYPE_CASTS(CSSBasicShapePolygonValue, isBasicShapePolygonValue());
+DEFINE_CSS_VALUE_TYPE_CASTS(CSSBasicShapeInsetValue, isBasicShapeInsetValue());
 
 } // namespace blink
 
-#endif // CSSBasicShapeValue_h
+#endif // CSSBasicShapeValues_h
diff --git a/third_party/WebKit/Source/core/css/CSSValue.cpp b/third_party/WebKit/Source/core/css/CSSValue.cpp
index c3a6af0..2d0678b5 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSValue.cpp
@@ -27,7 +27,7 @@
 #include "config.h"
 #include "core/css/CSSValue.h"
 
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSBorderImageSliceValue.h"
 #include "core/css/CSSCanvasValue.h"
 #include "core/css/CSSContentDistributionValue.h"
@@ -95,8 +95,14 @@
 {
     if (m_classType == other.m_classType) {
         switch (classType()) {
-        case BasicShapeClass:
-            return compareCSSValues<CSSBasicShapeValue>(*this, other);
+        case BasicShapeCircleClass:
+            return compareCSSValues<CSSBasicShapeCircleValue>(*this, other);
+        case BasicShapeEllipseClass:
+            return compareCSSValues<CSSBasicShapeEllipseValue>(*this, other);
+        case BasicShapePolygonClass:
+            return compareCSSValues<CSSBasicShapePolygonValue>(*this, other);
+        case BasicShapeInsetClass:
+            return compareCSSValues<CSSBasicShapeInsetValue>(*this, other);
         case BorderImageSliceClass:
             return compareCSSValues<CSSBorderImageSliceValue>(*this, other);
         case CanvasClass:
@@ -165,8 +171,14 @@
 String CSSValue::cssText() const
 {
     switch (classType()) {
-    case BasicShapeClass:
-        return toCSSBasicShapeValue(this)->customCSSText();
+    case BasicShapeCircleClass:
+        return toCSSBasicShapeCircleValue(this)->customCSSText();
+    case BasicShapeEllipseClass:
+        return toCSSBasicShapeEllipseValue(this)->customCSSText();
+    case BasicShapePolygonClass:
+        return toCSSBasicShapePolygonValue(this)->customCSSText();
+    case BasicShapeInsetClass:
+        return toCSSBasicShapeInsetValue(this)->customCSSText();
     case BorderImageSliceClass:
         return toCSSBorderImageSliceValue(this)->customCSSText();
     case CanvasClass:
@@ -233,8 +245,17 @@
 void CSSValue::destroy()
 {
     switch (classType()) {
-    case BasicShapeClass:
-        delete toCSSBasicShapeValue(this);
+    case BasicShapeCircleClass:
+        delete toCSSBasicShapeCircleValue(this);
+        return;
+    case BasicShapeEllipseClass:
+        delete toCSSBasicShapeEllipseValue(this);
+        return;
+    case BasicShapePolygonClass:
+        delete toCSSBasicShapePolygonValue(this);
+        return;
+    case BasicShapeInsetClass:
+        delete toCSSBasicShapeInsetValue(this);
         return;
     case BorderImageSliceClass:
         delete toCSSBorderImageSliceValue(this);
@@ -330,8 +351,17 @@
 void CSSValue::finalizeGarbageCollectedObject()
 {
     switch (classType()) {
-    case BasicShapeClass:
-        toCSSBasicShapeValue(this)->~CSSBasicShapeValue();
+    case BasicShapeCircleClass:
+        toCSSBasicShapeCircleValue(this)->~CSSBasicShapeCircleValue();
+        return;
+    case BasicShapeEllipseClass:
+        toCSSBasicShapeEllipseValue(this)->~CSSBasicShapeEllipseValue();
+        return;
+    case BasicShapePolygonClass:
+        toCSSBasicShapePolygonValue(this)->~CSSBasicShapePolygonValue();
+        return;
+    case BasicShapeInsetClass:
+        toCSSBasicShapeInsetValue(this)->~CSSBasicShapeInsetValue();
         return;
     case BorderImageSliceClass:
         toCSSBorderImageSliceValue(this)->~CSSBorderImageSliceValue();
@@ -427,8 +457,17 @@
 DEFINE_TRACE(CSSValue)
 {
     switch (classType()) {
-    case BasicShapeClass:
-        toCSSBasicShapeValue(this)->traceAfterDispatch(visitor);
+    case BasicShapeCircleClass:
+        toCSSBasicShapeCircleValue(this)->traceAfterDispatch(visitor);
+        return;
+    case BasicShapeEllipseClass:
+        toCSSBasicShapeEllipseValue(this)->traceAfterDispatch(visitor);
+        return;
+    case BasicShapePolygonClass:
+        toCSSBasicShapePolygonValue(this)->traceAfterDispatch(visitor);
+        return;
+    case BasicShapeInsetClass:
+        toCSSBasicShapeInsetValue(this)->traceAfterDispatch(visitor);
         return;
     case BorderImageSliceClass:
         toCSSBorderImageSliceValue(this)->traceAfterDispatch(visitor);
diff --git a/third_party/WebKit/Source/core/css/CSSValue.h b/third_party/WebKit/Source/core/css/CSSValue.h
index 55e4cb7..bbc3742 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.h
+++ b/third_party/WebKit/Source/core/css/CSSValue.h
@@ -64,7 +64,12 @@
 
     bool isBaseValueList() const { return m_classType == ValueListClass; }
 
-    bool isBasicShapeValue() const { return m_classType == BasicShapeClass; }
+    bool isBasicShapeValue() const { return m_classType >= BasicShapeCircleClass && m_classType <= BasicShapeInsetClass; }
+    bool isBasicShapeCircleValue() const { return m_classType == BasicShapeCircleClass; }
+    bool isBasicShapeEllipseValue() const { return m_classType == BasicShapeEllipseClass; }
+    bool isBasicShapePolygonValue() const { return m_classType == BasicShapePolygonClass; }
+    bool isBasicShapeInsetValue() const { return m_classType == BasicShapeInsetClass; }
+
     bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
     bool isCanvasValue() const { return m_classType == CanvasClass; }
     bool isCounterValue() const { return m_classType == CounterClass; }
@@ -115,11 +120,17 @@
     static const size_t ClassTypeBits = 6;
     enum ClassType {
         PrimitiveClass,
-        BasicShapeClass,
         CounterClass,
         QuadClass,
         ValuePairClass,
 
+        // Basic shape classes.
+        // TODO(sashab): Represent these as a single subclass, BasicShapeClass.
+        BasicShapeCircleClass,
+        BasicShapeEllipseClass,
+        BasicShapePolygonClass,
+        BasicShapeInsetClass,
+
         // Image classes.
         ImageClass,
         CursorImageClass,
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index d1de635..e4f1a57 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -27,7 +27,7 @@
 
 #include "core/StylePropertyShorthand.h"
 #include "core/css/BasicShapeFunctions.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSBorderImage.h"
 #include "core/css/CSSBorderImageSliceValue.h"
 #include "core/css/CSSCounterValue.h"
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index b8661ea5..f4aa52a2 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -126,6 +126,112 @@
     return contents;
 }
 
+class CalcParseScope {
+    STACK_ALLOCATED();
+
+public:
+    explicit CalcParseScope(CSSParserTokenRange& range, ValueRange valueRange = ValueRangeAll)
+        : m_sourceRange(range)
+        , m_range(range)
+    {
+        const CSSParserToken& token = range.peek();
+        if (token.functionId() == CSSValueCalc || token.functionId() == CSSValueWebkitCalc)
+            m_calcValue = CSSCalcValue::create(consumeFunction(m_range), valueRange);
+    }
+
+    const CSSCalcValue* value() const { return m_calcValue.get(); }
+    PassRefPtrWillBeRawPtr<CSSPrimitiveValue> releaseValue()
+    {
+        m_sourceRange = m_range;
+        return CSSPrimitiveValue::create(m_calcValue.release());
+    }
+    PassRefPtrWillBeRawPtr<CSSPrimitiveValue> releaseNumber()
+    {
+        m_sourceRange = m_range;
+        CSSPrimitiveValue::UnitType unitType = m_calcValue->isInt() ? CSSPrimitiveValue::UnitType::Integer : CSSPrimitiveValue::UnitType::Number;
+        return cssValuePool().createValue(m_calcValue->doubleValue(), unitType);
+    }
+
+private:
+    CSSParserTokenRange& m_sourceRange;
+    CSSParserTokenRange m_range;
+    RefPtrWillBeMember<CSSCalcValue> m_calcValue;
+};
+
+static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, CSSParserMode cssParserMode, double minimumValue = std::numeric_limits<int>::min())
+{
+    const CSSParserToken& token = range.peek();
+    if (token.type() == NumberToken) {
+        if (token.numericValueType() == NumberValueType || token.numericValue() < minimumValue)
+            return nullptr;
+        return cssValuePool().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
+    }
+    CalcParseScope calcScope(range);
+    if (const CSSCalcValue* calculation = calcScope.value()) {
+        if (calculation->category() != CalcNumber || !calculation->isInt())
+            return nullptr;
+        double value = calculation->doubleValue();
+        if (value < minimumValue)
+            return nullptr;
+        return calcScope.releaseNumber();
+    }
+    return nullptr;
+}
+
+inline bool shouldAcceptUnitlessValues(double fValue, CSSParserMode cssParserMode, UnitlessQuirk unitless)
+{
+    // Quirks mode for certain properties and presentation attributes accept unit-less values for certain units.
+    return !fValue // 0 can always be unitless.
+        || isUnitLessLengthParsingEnabledForMode(cssParserMode) // HTML and SVG attribute values can always be unitless.
+        || (cssParserMode == HTMLQuirksMode && (unitless == UnitlessQuirk::Allow));
+}
+
+static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless = UnitlessQuirk::Forbid)
+{
+    const CSSParserToken& token = range.peek();
+    if (token.type() == DimensionToken) {
+        switch (token.unitType()) {
+        case CSSPrimitiveValue::UnitType::QuirkyEms:
+            if (cssParserMode != UASheetMode)
+                return nullptr;
+        /* fallthrough intentional */
+        case CSSPrimitiveValue::UnitType::Ems:
+        case CSSPrimitiveValue::UnitType::Rems:
+        case CSSPrimitiveValue::UnitType::Chs:
+        case CSSPrimitiveValue::UnitType::Exs:
+        case CSSPrimitiveValue::UnitType::Pixels:
+        case CSSPrimitiveValue::UnitType::Centimeters:
+        case CSSPrimitiveValue::UnitType::Millimeters:
+        case CSSPrimitiveValue::UnitType::Inches:
+        case CSSPrimitiveValue::UnitType::Points:
+        case CSSPrimitiveValue::UnitType::Picas:
+        case CSSPrimitiveValue::UnitType::ViewportWidth:
+        case CSSPrimitiveValue::UnitType::ViewportHeight:
+        case CSSPrimitiveValue::UnitType::ViewportMin:
+        case CSSPrimitiveValue::UnitType::ViewportMax:
+            break;
+        default:
+            return nullptr;
+        }
+        if (valueRange == ValueRangeNonNegative && token.numericValue() < 0)
+            return nullptr;
+        return cssValuePool().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
+    }
+    if (token.type() == NumberToken) {
+        if (!shouldAcceptUnitlessValues(token.numericValue(), cssParserMode, unitless)
+            || (valueRange == ValueRangeNonNegative && token.numericValue() < 0))
+            return nullptr;
+        return cssValuePool().createValue(range.consumeIncludingWhitespace().numericValue(), CSSPrimitiveValue::UnitType::Pixels);
+    }
+    CalcParseScope calcScope(range, valueRange);
+    if (const CSSCalcValue* calculation = calcScope.value()) {
+        if (calculation->category() != CalcLength)
+            return nullptr;
+        return calcScope.releaseValue();
+    }
+    return nullptr;
+}
+
 static inline bool isCSSWideKeyword(const CSSValueID& id)
 {
     return id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset || id == CSSValueDefault;
@@ -396,6 +502,22 @@
     return list.release();
 }
 
+static PassRefPtrWillBeRawPtr<CSSValue> consumeSpacing(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    if (range.peek().id() == CSSValueNormal)
+        return consumeIdent(range);
+    // TODO(timloh): Don't allow unitless values, and allow <percentage>s in word-spacing.
+    return consumeLength(range, cssParserMode, ValueRangeAll, UnitlessQuirk::Allow);
+}
+
+static PassRefPtrWillBeRawPtr<CSSValue> consumeTabSize(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+{
+    RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = consumeInteger(range, cssParserMode, 0);
+    if (parsedValue)
+        return parsedValue;
+    return consumeLength(range, cssParserMode, ValueRangeNonNegative);
+}
+
 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID propId)
 {
     m_range.consumeWhitespace();
@@ -418,6 +540,11 @@
         return consumeFontFamily(m_range);
     case CSSPropertyFontWeight:
         return consumeFontWeight(m_range);
+    case CSSPropertyLetterSpacing:
+    case CSSPropertyWordSpacing:
+        return consumeSpacing(m_range, m_context.mode());
+    case CSSPropertyTabSize:
+        return consumeTabSize(m_range, m_context.mode());
     default:
         return nullptr;
     }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
index 51de8672..44515ad 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -52,6 +52,11 @@
 class CSSValueList;
 class StylePropertyShorthand;
 
+enum class UnitlessQuirk {
+    Allow,
+    Forbid
+};
+
 // Inputs: PropertyID, isImportant bool, CSSParserValueList.
 // Outputs: Vector of CSSProperties
 
@@ -180,7 +185,7 @@
 
     PassRefPtrWillBeRawPtr<CSSValue> parseShapeProperty(CSSPropertyID propId);
     PassRefPtrWillBeRawPtr<CSSValue> parseBasicShapeAndOrBox();
-    PassRefPtrWillBeRawPtr<CSSBasicShapeValue> parseBasicShape();
+    PassRefPtrWillBeRawPtr<CSSValue> parseBasicShape();
     PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseShapeRadius(CSSParserValue*);
 
     PassRefPtrWillBeRawPtr<CSSBasicShapeCircleValue> parseBasicShapeCircle(CSSParserValueList* args);
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
index 555573c..9cf25ef 100644
--- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp
@@ -28,7 +28,7 @@
 #include "core/css/parser/CSSPropertyParser.h"
 
 #include "core/StylePropertyShorthand.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSBorderImage.h"
 #include "core/css/CSSCanvasValue.h"
 #include "core/css/CSSContentDistributionValue.h"
@@ -691,14 +691,6 @@
             validPrimitive = validUnit(value, FLength | FNonNeg | unitless);
         break;
 
-    case CSSPropertyLetterSpacing:       // normal | <length> | inherit
-    case CSSPropertyWordSpacing:         // normal | <length> | inherit
-        if (id == CSSValueNormal)
-            validPrimitive = true;
-        else
-            validPrimitive = validUnit(value, FLength | FUnitlessQuirk);
-        break;
-
     case CSSPropertyTextIndent:
         parsedValue = parseTextIndent();
         break;
@@ -912,10 +904,6 @@
         addProperty(propId, CSSValuePair::create(parsedValue1.release(), parsedValue2.release(), CSSValuePair::DropIdenticalValues), important);
         return true;
     }
-    case CSSPropertyTabSize:
-        // May be specified as a unit-less non-negative integer or length indicating number of space characters.
-        validPrimitive = validUnit(value, FInteger | FLength | FNonNeg);
-        break;
     case CSSPropertyBorderRadius:
     case CSSPropertyAliasWebkitBorderRadius:
         return parseBorderRadius(unresolvedProperty, important);
@@ -1424,6 +1412,9 @@
     case CSSPropertyFontVariant:
     case CSSPropertyFontFamily:
     case CSSPropertyFontWeight:
+    case CSSPropertyLetterSpacing:
+    case CSSPropertyWordSpacing:
+    case CSSPropertyTabSize:
         validPrimitive = false;
         break;
 
@@ -3605,7 +3596,7 @@
         double flexValue = currentValue->fValue;
 
         // Fractional unit is a non-negative dimension.
-        if (flexValue <= 0)
+        if (flexValue < 0)
             return nullptr;
 
         return cssValuePool().createValue(flexValue, CSSPrimitiveValue::UnitType::Fraction);
@@ -4352,7 +4343,7 @@
         valueId = value->id;
         if (value->m_unit == CSSParserValue::Function && !shapeFound) {
             // parseBasicShape already asks for the next value list item.
-            RefPtrWillBeRawPtr<CSSBasicShapeValue> shapeValue = parseBasicShape();
+            RefPtrWillBeRawPtr<CSSValue> shapeValue = parseBasicShape();
             if (!shapeValue)
                 return nullptr;
             list->append(shapeValue.release());
@@ -4373,7 +4364,7 @@
     return list.release();
 }
 
-PassRefPtrWillBeRawPtr<CSSBasicShapeValue> CSSPropertyParser::parseBasicShape()
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseBasicShape()
 {
     CSSParserValue* value = m_valueList->current();
     ASSERT(value->m_unit == CSSParserValue::Function);
@@ -4382,7 +4373,7 @@
     if (!args)
         return nullptr;
 
-    RefPtrWillBeRawPtr<CSSBasicShapeValue> shape = nullptr;
+    RefPtrWillBeRawPtr<CSSValue> shape = nullptr;
     if (value->function->id == CSSValueCircle)
         shape = parseBasicShapeCircle(args);
     else if (value->function->id == CSSValueEllipse)
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index 0887d81..3a063cb 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -28,7 +28,7 @@
 #include "core/css/resolver/StyleBuilderConverter.h"
 
 #include "core/css/BasicShapeFunctions.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSContentDistributionValue.h"
 #include "core/css/CSSFontFeatureValue.h"
 #include "core/css/CSSFunctionValue.h"
@@ -816,7 +816,7 @@
     for (unsigned i = 0; i < valueList->length(); ++i) {
         const CSSValue& value = *valueList->item(i);
         if (value.isBasicShapeValue()) {
-            shape = basicShapeForValue(state, toCSSBasicShapeValue(value));
+            shape = basicShapeForValue(state, value);
         } else {
             cssBox = CSSBoxType(toCSSPrimitiveValue(value));
         }
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
index dcd8f6b..b0ece3e 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -43,7 +43,7 @@
 #include "core/StyleBuilderFunctions.h"
 #include "core/StylePropertyShorthand.h"
 #include "core/css/BasicShapeFunctions.h"
-#include "core/css/CSSBasicShapeValue.h"
+#include "core/css/CSSBasicShapeValues.h"
 #include "core/css/CSSCounterValue.h"
 #include "core/css/CSSCursorImageValue.h"
 #include "core/css/CSSFunctionValue.h"
@@ -567,7 +567,7 @@
 void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverState& state, CSSValue* value)
 {
     if (value->isBasicShapeValue()) {
-        state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, toCSSBasicShapeValue(*value))));
+        state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, *value)));
     }
     if (value->isPrimitiveValue()) {
         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
diff --git a/third_party/WebKit/Source/core/dom/AXObjectCache.h b/third_party/WebKit/Source/core/dom/AXObjectCache.h
index 79618c4..973fe8d6 100644
--- a/third_party/WebKit/Source/core/dom/AXObjectCache.h
+++ b/third_party/WebKit/Source/core/dom/AXObjectCache.h
@@ -62,6 +62,7 @@
         AXChildrenChanged,
         AXFocusedUIElementChanged,
         AXHide,
+        AXHover,
         AXInvalidStatusChanged,
         AXLayoutComplete,
         AXLiveRegionChanged,
@@ -135,6 +136,8 @@
     virtual const AtomicString& computedRoleForNode(Node*) = 0;
     virtual String computedNameForNode(Node*) = 0;
 
+    virtual void onTouchAccessibilityHover(const IntPoint&) = 0;
+
     typedef AXObjectCache* (*AXObjectCacheCreateFunction)(Document&);
     static void init(AXObjectCacheCreateFunction);
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 98cd8dd6..99ba96c 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -575,7 +575,7 @@
     m_userActionElements.documentDidRemoveLastRef();
     m_associatedFormControls.clear();
 
-    m_scriptRunner.clear();
+    m_scriptRunner->dispose();
     detachParser();
 
     m_registrationContext.clear();
@@ -2373,7 +2373,7 @@
 
     if (m_frame)
         m_frame->loader().didExplicitOpen();
-    if (m_loadEventProgress != LoadEventInProgress && m_loadEventProgress != UnloadEventInProgress)
+    if (m_loadEventProgress != LoadEventInProgress && pageDismissalEventBeingDispatched() == NoDismissal)
         m_loadEventProgress = LoadEventNotRun;
 }
 
@@ -5651,7 +5651,7 @@
     return wrapper;
 }
 
-bool Document::isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck privilegeContextCheck) const
+bool Document::isSecureContext(String& errorMessage, const SecureContextCheck privilegeContextCheck) const
 {
     if (SecurityContext::isSandboxed(SandboxOrigin)) {
         if (!SecurityOrigin::create(url())->isPotentiallyTrustworthy(errorMessage))
@@ -5661,7 +5661,7 @@
             return false;
     }
 
-    if (privilegeContextCheck == StandardPrivilegeCheck) {
+    if (privilegeContextCheck == StandardSecureContextCheck) {
         Document* context = parentDocument();
         while (context) {
             // Skip to the next ancestor if it's a srcdoc.
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 66e1ce94..0626892 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -305,7 +305,6 @@
 
     String defaultCharset() const;
 
-    AtomicString charset() const { return Document::encodingName(); }
     AtomicString characterSet() const { return Document::encodingName(); }
 
     AtomicString encodingName() const;
@@ -1027,7 +1026,7 @@
 
     NthIndexCache* nthIndexCache() const { return m_nthIndexCache; }
 
-    bool isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck = StandardPrivilegeCheck) const override;
+    bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const override;
 
     ClientHintsPreferences& clientHintsPreferences() { return m_clientHintsPreferences; }
 
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index 5c90a4d..a49f218 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -38,7 +38,8 @@
     readonly attribute DOMString compatMode;
 
     readonly attribute DOMString characterSet;
-    [MeasureAs=DocumentInputEncoding, ImplementedAs=characterSet] readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
+    [ImplementedAs=characterSet] readonly attribute DOMString charset; // legacy alias of .characterSet
+    [ImplementedAs=characterSet] readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
     readonly attribute DOMString contentType;
 
     readonly attribute DocumentType? doctype;
@@ -201,7 +202,6 @@
     readonly attribute VisibilityState visibilityState;
 
     // Non-standard APIs
-    [MeasureAs=DocumentCharset] readonly attribute DOMString charset;
     [MeasureAs=DocumentDefaultCharset, TreatReturnedNullStringAs=Undefined] readonly attribute DOMString defaultCharset;
     [MeasureAs=DocumentCaretRangeFromPoint] Range caretRangeFromPoint([Default=Undefined] optional long x, [Default=Undefined] optional long y);
     [CallWith=ScriptState, DeprecateAs=DocumentGetCSSCanvasContext] any getCSSCanvasContext(DOMString contextId, DOMString name, long width, long height);
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
index df8a50a..643e88ef 100644
--- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.cpp
@@ -165,7 +165,7 @@
             return true;
         if (nextState == InPerformLayout)
             return true;
-        // We can redundant arrive in the layout clean state. This situation
+        // We can redundantly arrive in the layout clean state. This situation
         // can happen when we call layout recursively and we unwind the stack.
         if (nextState == LayoutClean)
             return true;
@@ -195,14 +195,24 @@
             return true;
         if (nextState == InCompositingUpdate)
             return true;
-        if (nextState == InPaintForSlimmingPaintV2 && RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+        if (nextState == InPaint && RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
             return true;
         break;
-    case InPaintForSlimmingPaintV2:
-        if (nextState == PaintForSlimmingPaintV2Clean && RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+    case InPaint:
+        if (nextState == PaintClean && RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
             return true;
         break;
-    case PaintForSlimmingPaintV2Clean:
+    case PaintClean:
+        if (!RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
+            break;
+        if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+            if (nextState == InStyleRecalc)
+                return true;
+            if (nextState == InPreLayout)
+                return true;
+            if (nextState == InCompositingUpdate)
+                return true;
+        }
         if (nextState == InCompositingForSlimmingPaintV2 && RuntimeEnabledFeatures::slimmingPaintV2Enabled())
             return true;
         break;
@@ -245,7 +255,7 @@
         || m_state == LayoutClean
         || m_state == CompositingClean
         || m_state == PaintInvalidationClean
-        || (m_state == PaintForSlimmingPaintV2Clean && RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+        || (m_state == PaintClean && RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
         || (m_state == CompositingForSlimmingPaintV2Clean && RuntimeEnabledFeatures::slimmingPaintV2Enabled());
 }
 
diff --git a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
index fae9797b..fe20cc9 100644
--- a/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
+++ b/third_party/WebKit/Source/core/dom/DocumentLifecycle.h
@@ -67,13 +67,16 @@
         InPaintInvalidation,
         PaintInvalidationClean,
 
-        InPaintForSlimmingPaintV2,
-        PaintForSlimmingPaintV2Clean,
+        // When RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled
+        // (implied by slimmingPaintV2Enabled).
+        InPaint,
+        PaintClean,
 
+        // When RuntimeEnabledFeatures::slimmingPaintV2Enabled.
         InCompositingForSlimmingPaintV2,
         CompositingForSlimmingPaintV2Clean,
 
-        // Once the document starts shuting down, we cannot return
+        // Once the document starts shutting down, we cannot return
         // to the style/layout/compositing states.
         Stopping,
         Stopped,
@@ -167,7 +170,7 @@
     return m_state != InStyleRecalc
         && m_state != InPerformLayout
         && m_state != InCompositingUpdate
-        && m_state != InPaintForSlimmingPaintV2
+        && m_state != InPaint
         && m_state != InCompositingForSlimmingPaintV2;
 }
 
@@ -191,7 +194,7 @@
         || m_state == LayoutClean
         || m_state == CompositingClean
         || m_state == PaintInvalidationClean
-        || m_state == PaintForSlimmingPaintV2Clean
+        || m_state == PaintClean
         || m_state == CompositingForSlimmingPaintV2Clean
         || m_state == Stopping;
 }
@@ -201,7 +204,7 @@
     return m_state != InPerformLayout
         && m_state != InCompositingUpdate
         && m_state != InPaintInvalidation
-        && m_state != InPaintForSlimmingPaintV2
+        && m_state != InPaint
         && m_state != InCompositingForSlimmingPaintV2;
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ExecutionContext.h b/third_party/WebKit/Source/core/dom/ExecutionContext.h
index 2221a6e..c26e5c6 100644
--- a/third_party/WebKit/Source/core/dom/ExecutionContext.h
+++ b/third_party/WebKit/Source/core/dom/ExecutionContext.h
@@ -63,12 +63,12 @@
 public:
     DECLARE_VIRTUAL_TRACE();
 
-    // Used to specify whether |isPrivilegedContext| should walk the
+    // Used to specify whether |isSecureContext| should walk the
     // ancestor tree to decide whether to restrict usage of a powerful
     // feature.
-    enum PrivilegeContextCheck {
-        StandardPrivilegeCheck,
-        WebCryptoPrivilegeCheck
+    enum SecureContextCheck {
+        StandardSecureContextCheck,
+        WebCryptoSecureContextCheck
     };
 
     virtual bool isDocument() const { return false; }
@@ -156,7 +156,7 @@
 
     // Decides whether this context is privileged, as described in
     // https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-privileged.
-    virtual bool isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck = StandardPrivilegeCheck) const = 0;
+    virtual bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const = 0;
 
     virtual void setReferrerPolicy(ReferrerPolicy);
     ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; }
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.cpp b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
index 110dec35..f4ea213 100644
--- a/third_party/WebKit/Source/core/dom/Fullscreen.cpp
+++ b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
@@ -200,11 +200,11 @@
 
 void Fullscreen::requestFullscreen(Element& element, RequestType requestType)
 {
-    // It is required by isPrivilegedContext() but isn't
+    // It is required by isSecureContext() but isn't
     // actually used. This could be used later if a warning is shown in the
     // developer console.
     String errorMessage;
-    if (document()->isPrivilegedContext(errorMessage)) {
+    if (document()->isSecureContext(errorMessage)) {
         UseCounter::count(document(), UseCounter::FullscreenSecureOrigin);
     } else {
         UseCounter::count(document(), UseCounter::FullscreenInsecureOrigin);
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index e9b822670..a2a74db 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -150,67 +150,70 @@
     size_t elementsWithRareData = 0;
     size_t elementsWithNamedNodeMap = 0;
 
-    for (Node* node : liveNodeSet()) {
-        if (node->hasRareData()) {
-            ++nodesWithRareData;
-            if (node->isElementNode()) {
-                ++elementsWithRareData;
-                if (toElement(node)->hasNamedNodeMap())
-                    ++elementsWithNamedNodeMap;
+    {
+        ScriptForbiddenScope forbidScriptDuringRawIteration;
+        for (Node* node : liveNodeSet()) {
+            if (node->hasRareData()) {
+                ++nodesWithRareData;
+                if (node->isElementNode()) {
+                    ++elementsWithRareData;
+                    if (toElement(node)->hasNamedNodeMap())
+                        ++elementsWithNamedNodeMap;
+                }
             }
-        }
 
-        switch (node->nodeType()) {
-        case ELEMENT_NODE: {
-            ++elementNodes;
+            switch (node->nodeType()) {
+            case ELEMENT_NODE: {
+                ++elementNodes;
 
-            // Tag stats
-            Element* element = toElement(node);
-            HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
-            if (!result.isNewEntry)
-                result.storedValue->value++;
+                // Tag stats
+                Element* element = toElement(node);
+                HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
+                if (!result.isNewEntry)
+                    result.storedValue->value++;
 
-            if (const ElementData* elementData = element->elementData()) {
-                attributes += elementData->attributes().size();
-                ++elementsWithAttributeStorage;
+                if (const ElementData* elementData = element->elementData()) {
+                    attributes += elementData->attributes().size();
+                    ++elementsWithAttributeStorage;
+                }
+                break;
             }
-            break;
-        }
-        case ATTRIBUTE_NODE: {
-            ++attrNodes;
-            break;
-        }
-        case TEXT_NODE: {
-            ++textNodes;
-            break;
-        }
-        case CDATA_SECTION_NODE: {
-            ++cdataNodes;
-            break;
-        }
-        case COMMENT_NODE: {
-            ++commentNodes;
-            break;
-        }
-        case PROCESSING_INSTRUCTION_NODE: {
-            ++piNodes;
-            break;
-        }
-        case DOCUMENT_NODE: {
-            ++documentNodes;
-            break;
-        }
-        case DOCUMENT_TYPE_NODE: {
-            ++docTypeNodes;
-            break;
-        }
-        case DOCUMENT_FRAGMENT_NODE: {
-            if (node->isShadowRoot())
-                ++shadowRootNodes;
-            else
-                ++fragmentNodes;
-            break;
-        }
+            case ATTRIBUTE_NODE: {
+                ++attrNodes;
+                break;
+            }
+            case TEXT_NODE: {
+                ++textNodes;
+                break;
+            }
+            case CDATA_SECTION_NODE: {
+                ++cdataNodes;
+                break;
+            }
+            case COMMENT_NODE: {
+                ++commentNodes;
+                break;
+            }
+            case PROCESSING_INSTRUCTION_NODE: {
+                ++piNodes;
+                break;
+            }
+            case DOCUMENT_NODE: {
+                ++documentNodes;
+                break;
+            }
+            case DOCUMENT_TYPE_NODE: {
+                ++docTypeNodes;
+                break;
+            }
+            case DOCUMENT_FRAGMENT_NODE: {
+                if (node->isShadowRoot())
+                    ++shadowRootNodes;
+                else
+                    ++fragmentNodes;
+                break;
+            }
+            }
         }
     }
 
@@ -638,6 +641,7 @@
             shadow->distributeIfNeeded();
     }
 
+    ASSERT(ScriptForbiddenScope::isScriptForbidden());
     for (Node* child = firstChild(); child; child = child->nextSibling()) {
         if (child->childNeedsDistributionRecalc())
             child->recalcDistribution();
@@ -665,6 +669,7 @@
 
 void Node::markAncestorsWithChildNeedsStyleInvalidation()
 {
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* node = parentOrShadowHostNode(); node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
         node->setChildNeedsStyleInvalidation();
     document().scheduleLayoutTreeUpdateIfNeeded();
@@ -672,6 +677,7 @@
 
 void Node::markAncestorsWithChildNeedsDistributionRecalc()
 {
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* node = this; node && !node->childNeedsDistributionRecalc(); node = node->parentOrShadowHostNode())
         node->setChildNeedsDistributionRecalc();
     document().scheduleLayoutTreeUpdateIfNeeded();
@@ -749,7 +755,7 @@
 
 unsigned Node::nodeIndex() const
 {
-    Node* tempNode = previousSibling();
+    const Node* tempNode = previousSibling();
     unsigned count = 0;
     for (count = 0; tempNode; count++)
         tempNode = tempNode->previousSibling();
@@ -906,6 +912,7 @@
 
 void Node::reattachWhitespaceSiblingsIfNeeded(Text* start)
 {
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) {
         if (sibling->isTextNode() && toText(sibling)->containsOnlyWhitespace()) {
             bool hadLayoutObject = !!sibling->layoutObject();
@@ -1027,14 +1034,14 @@
 
 Element* Node::rootEditableElement() const
 {
-    Element* result = nullptr;
-    for (Node* n = const_cast<Node*>(this); n && n->hasEditableStyle(); n = n->parentNode()) {
+    const Node* result = nullptr;
+    for (const Node* n = this; n && n->hasEditableStyle(); n = n->parentNode()) {
         if (n->isElementNode())
-            result = toElement(n);
+            result = n;
         if (isHTMLBodyElement(*n))
             break;
     }
-    return result;
+    return toElement(const_cast<Node*>(result));
 }
 
 // FIXME: End of obviously misplaced HTML editing functions.  Try to move these out of Node.
@@ -1255,7 +1262,7 @@
         return String();
 
     StringBuilder content;
-    for (Node& node : NodeTraversal::inclusiveDescendantsOf(*this)) {
+    for (const Node& node : NodeTraversal::inclusiveDescendantsOf(*this)) {
         if (isHTMLBRElement(node) && convertBRsToNewlines) {
             content.append('\n');
         } else if (node.isTextNode()) {
@@ -1399,7 +1406,7 @@
                 if (!child1->isShadowRoot())
                     return Node::DOCUMENT_POSITION_PRECEDING | connection;
 
-                for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot()) {
+                for (const ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot()) {
                     if (child == child1) {
                         return Node::DOCUMENT_POSITION_FOLLOWING | connection;
                     }
@@ -1414,7 +1421,7 @@
                 return DOCUMENT_POSITION_PRECEDING | connection;
 
             // Otherwise we need to see which node occurs first.  Crawl backwards from child2 looking for child1.
-            for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
+            for (const Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
                 if (child == child1)
                     return DOCUMENT_POSITION_FOLLOWING | connection;
             }
@@ -1513,7 +1520,7 @@
         const Node* node = chain[index - 1];
         if (node->isShadowRoot()) {
             int count = 0;
-            for (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
+            for (const ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
                 ++count;
             WTFLogAlways("/#shadow-root[%d]", count);
             continue;
@@ -1528,7 +1535,7 @@
             bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
             if (node->previousSibling() || node->nextSibling()) {
                 int count = 0;
-                for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling()) {
+                for (const Node* previous = node->previousSibling(); previous; previous = previous->previousSibling()) {
                     if (previous->nodeName() == node->nodeName()) {
                         ++count;
                     }
@@ -1557,7 +1564,7 @@
 
 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
 {
-    for (Node& node : NodeTraversal::inclusiveDescendantsOf(*rootNode)) {
+    for (const Node& node : NodeTraversal::inclusiveDescendantsOf(*rootNode)) {
         StringBuilder indent;
         if (node == markedNode1)
             indent.append(markedLabel1);
@@ -1669,13 +1676,13 @@
         if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
             showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t");
     }
-    for (Node* child = node->firstChild(); child; child = child->nextSibling())
+    for (const Node* child = node->firstChild(); child; child = child->nextSibling())
         showSubTreeAcrossFrame(child, markedNode, indent + "\t");
 }
 
 void Node::showTreeForThisAcrossFrame() const
 {
-    Node* rootNode = const_cast<Node*>(this);
+    const Node* rootNode = this;
     while (parentOrShadowHostOrFrameOwner(rootNode))
         rootNode = parentOrShadowHostOrFrameOwner(rootNode);
     showSubTreeAcrossFrame(rootNode, this, "");
@@ -1687,18 +1694,20 @@
 
 Element* Node::enclosingLinkEventParentOrSelf() const
 {
-    for (Node* node = const_cast<Node*>(this); node; node = ComposedTreeTraversal::parent(*node)) {
+    const Node* result = nullptr;
+    for (const Node* node = this; node; node = ComposedTreeTraversal::parent(*node)) {
         // For imagemaps, the enclosing link node is the associated area element not the image itself.
         // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
         // for them.
         if (node->isLink() && !isHTMLImageElement(*node)) {
             // Casting to Element is safe because only HTMLAnchorElement, HTMLImageElement and
             // SVGAElement can return true for isLink().
-            return toElement(node);
+            result = node;
+            break;
         }
     }
 
-    return nullptr;
+    return toElement(const_cast<Node*>(result));
 }
 
 const AtomicString& Node::interfaceName() const
@@ -1791,6 +1800,7 @@
 
 void Node::removeAllEventListenersRecursively()
 {
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node& node : NodeTraversal::startsAt(this)) {
         node.removeAllEventListeners();
         for (ShadowRoot* root = node.youngestShadowRoot(); root; root = root->olderShadowRoot())
@@ -1873,6 +1883,7 @@
     ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
     collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName);
     collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName);
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* node = parentNode(); node; node = node->parentNode()) {
         collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName);
         collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName);
@@ -1943,6 +1954,7 @@
     if (!document().hasMutationObservers())
         return;
 
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* node = parentNode(); node; node = node->parentNode()) {
         if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>* registry = node->mutationObserverRegistry()) {
             const size_t size = registry->size();
@@ -2194,6 +2206,7 @@
     if (!count)
         return;
 
+    ScriptForbiddenScope forbidScriptDuringRawIteration;
     for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
         node->incrementConnectedSubframeCount(count);
 }
diff --git a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
index 0b558ec..2692c0d 100644
--- a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
+++ b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
@@ -112,7 +112,7 @@
     Timer<PresentationAttributeCacheCleaner> m_cleanTimer;
 };
 
-static bool attributeNameSort(const pair<StringImpl*, AtomicString>& p1, const pair<StringImpl*, AtomicString>& p2)
+static bool attributeNameSort(const std::pair<StringImpl*, AtomicString>& p1, const std::pair<StringImpl*, AtomicString>& p2)
 {
     // Sort based on the attribute name pointers. It doesn't matter what the order is as long as it is always the same.
     return p1.first < p2.first;
diff --git a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
index cbe3e6c..d540c302 100644
--- a/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
+++ b/third_party/WebKit/Source/core/dom/ProcessingInstruction.cpp
@@ -172,7 +172,7 @@
         if (RuntimeEnabledFeatures::xsltEnabled())
             resource = XSLStyleSheetResource::fetch(request, document().fetcher());
     } else {
-        request.setCharset(charset.isEmpty() ? document().charset() : charset);
+        request.setCharset(charset.isEmpty() ? document().characterSet() : charset);
         resource = CSSStyleSheetResource::fetch(request, document().fetcher());
     }
 
diff --git a/third_party/WebKit/Source/core/dom/QualifiedName.cpp b/third_party/WebKit/Source/core/dom/QualifiedName.cpp
index 32a0849c..c709861 100644
--- a/third_party/WebKit/Source/core/dom/QualifiedName.cpp
+++ b/third_party/WebKit/Source/core/dom/QualifiedName.cpp
@@ -41,18 +41,7 @@
 
 static_assert(sizeof(QualifiedName::QualifiedNameImpl) == sizeof(SameSizeAsQualifiedNameImpl), "QualifiedNameImpl should stay small");
 
-static const int staticQualifiedNamesCount = HTMLNames::HTMLTagsCount + HTMLNames::HTMLAttrsCount
-    + MathMLNames::MathMLTagsCount + MathMLNames::MathMLAttrsCount
-    + SVGNames::SVGTagsCount + SVGNames::SVGAttrsCount
-    + XLinkNames::XLinkAttrsCount
-    + XMLNSNames::XMLNSAttrsCount
-    + XMLNames::XMLAttrsCount;
-
-struct QualifiedNameHashTraits : public HashTraits<QualifiedName::QualifiedNameImpl*> {
-    static const unsigned minimumTableSize = WTF::HashTableCapacityForSize<staticQualifiedNamesCount>::value;
-};
-
-typedef HashSet<QualifiedName::QualifiedNameImpl*, QualifiedNameHash, QualifiedNameHashTraits> QualifiedNameCache;
+using QualifiedNameCache = HashSet<QualifiedName::QualifiedNameImpl*, QualifiedNameHash>;
 
 static QualifiedNameCache& qualifiedNameCache()
 {
@@ -115,9 +104,10 @@
 DEFINE_GLOBAL(QualifiedName, anyName, nullAtom, starAtom, starAtom)
 DEFINE_GLOBAL(QualifiedName, nullName, nullAtom, nullAtom, nullAtom)
 
-void QualifiedName::init()
+void QualifiedName::initAndReserveCapacityForSize(unsigned size)
 {
     ASSERT(starAtom.impl());
+    qualifiedNameCache().reserveCapacityForSize(size + 2 /*starAtom and nullAtom */);
     new ((void*)&anyName) QualifiedName(nullAtom, starAtom, starAtom, true );
     new ((void*)&nullName) QualifiedName(nullAtom, nullAtom, nullAtom, true );
 }
diff --git a/third_party/WebKit/Source/core/dom/QualifiedName.h b/third_party/WebKit/Source/core/dom/QualifiedName.h
index 0e48ab7..f48b315 100644
--- a/third_party/WebKit/Source/core/dom/QualifiedName.h
+++ b/third_party/WebKit/Source/core/dom/QualifiedName.h
@@ -127,7 +127,7 @@
     QualifiedNameImpl* impl() const { return m_impl.get(); }
 
     // Init routine for globals
-    static void init();
+    static void initAndReserveCapacityForSize(unsigned size);
 
     static const QualifiedName& null();
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 7a16bd0..e63ea29d 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -229,7 +229,7 @@
     if (!client->charsetAttributeValue().isEmpty())
         m_characterEncoding = client->charsetAttributeValue();
     else
-        m_characterEncoding = elementDocument.charset();
+        m_characterEncoding = elementDocument.characterSet();
 
     if (client->hasSourceAttribute()) {
         FetchRequest::DeferOption defer = FetchRequest::NoDefer;
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
index 74880972..c4ef3e7f 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
@@ -48,6 +48,13 @@
 ScriptRunner::~ScriptRunner()
 {
 #if !ENABLE(OILPAN)
+    dispose();
+#endif
+}
+
+#if !ENABLE(OILPAN)
+void ScriptRunner::dispose()
+{
     // Make sure that ScriptLoaders don't keep their PendingScripts alive.
     for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder)
         scriptLoader->detach();
@@ -55,8 +62,12 @@
         scriptLoader->detach();
     for (ScriptLoader* scriptLoader : m_pendingAsyncScripts)
         scriptLoader->detach();
-#endif
+
+    m_scriptsToExecuteInOrder.clear();
+    m_scriptsToExecuteSoon.clear();
+    m_pendingAsyncScripts.clear();
 }
+#endif
 
 void ScriptRunner::addPendingAsyncScript(ScriptLoader* scriptLoader)
 {
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunner.h b/third_party/WebKit/Source/core/dom/ScriptRunner.h
index 5a3d66d..f39b73d 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunner.h
+++ b/third_party/WebKit/Source/core/dom/ScriptRunner.h
@@ -48,6 +48,9 @@
         return adoptPtrWillBeNoop(new ScriptRunner(document));
     }
     ~ScriptRunner();
+#if !ENABLE(OILPAN)
+    void dispose();
+#endif
 
     enum ExecutionType { ASYNC_EXECUTION, IN_ORDER_EXECUTION };
     void queueScriptForExecution(ScriptLoader*, ExecutionType);
@@ -82,6 +85,6 @@
     OwnPtr<CancellableTaskFactory> m_executeScriptsTaskFactory;
 };
 
-}
+} // namespace blink
 
-#endif
+#endif // ScriptRunner_h
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
index 813273a..f5cf582 100644
--- a/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptRunnerTest.cpp
@@ -77,7 +77,7 @@
         m_tasks->append(adoptPtr(task));
     }
 
-    void postDelayedTask(const WebTraceLocation&, Task* task, long long delayMs) override
+    void postDelayedTask(const WebTraceLocation&, Task* task, double delayMs) override
     {
         ASSERT_NOT_REACHED();
     }
diff --git a/third_party/WebKit/Source/core/editing/EditingStrategy.h b/third_party/WebKit/Source/core/editing/EditingStrategy.h
index 9a53320..c6256ea 100644
--- a/third_party/WebKit/Source/core/editing/EditingStrategy.h
+++ b/third_party/WebKit/Source/core/editing/EditingStrategy.h
@@ -13,7 +13,7 @@
 namespace blink {
 
 template <typename Strategy>
-class PositionAlgorithm;
+class PositionTemplate;
 
 template <typename Strategy>
 class PositionIteratorAlgorithm;
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 31da42b..4a0cebe 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -325,20 +325,20 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> nextCandidateAlgorithm(const PositionAlgorithm<Strategy>& position)
+PositionTemplate<Strategy> nextCandidateAlgorithm(const PositionTemplate<Strategy>& position)
 {
     PositionIteratorAlgorithm<Strategy> p(position);
 
     p.increment();
     while (!p.atEnd()) {
-        PositionAlgorithm<Strategy> candidate = p.computePosition();
+        PositionTemplate<Strategy> candidate = p.computePosition();
         if (isVisuallyEquivalentCandidate(candidate))
             return candidate;
 
         p.increment();
     }
 
-    return PositionAlgorithm<Strategy>();
+    return PositionTemplate<Strategy>();
 }
 
 Position nextCandidate(const Position& position)
@@ -355,24 +355,24 @@
 // for returning position which |downstream()| not equal to initial position's
 // |downstream()|.
 template <typename Strategy>
-static PositionAlgorithm<Strategy> nextVisuallyDistinctCandidateAlgorithm(const PositionAlgorithm<Strategy>& position)
+static PositionTemplate<Strategy> nextVisuallyDistinctCandidateAlgorithm(const PositionTemplate<Strategy>& position)
 {
     if (position.isNull())
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     PositionIteratorAlgorithm<Strategy> p(position);
-    const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(position);
+    const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition(position);
 
     p.increment();
     while (!p.atEnd()) {
-        PositionAlgorithm<Strategy> candidate = p.computePosition();
+        PositionTemplate<Strategy> candidate = p.computePosition();
         if (isVisuallyEquivalentCandidate(candidate) && mostForwardCaretPosition(candidate) != downstreamStart)
             return candidate;
 
         p.increment();
     }
 
-    return PositionAlgorithm<Strategy>();
+    return PositionTemplate<Strategy>();
 }
 
 Position nextVisuallyDistinctCandidate(const Position& position)
@@ -386,20 +386,20 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> previousCandidateAlgorithm(const PositionAlgorithm<Strategy>& position)
+PositionTemplate<Strategy> previousCandidateAlgorithm(const PositionTemplate<Strategy>& position)
 {
     PositionIteratorAlgorithm<Strategy> p(position);
 
     p.decrement();
     while (!p.atStart()) {
-        PositionAlgorithm<Strategy> candidate = p.computePosition();
+        PositionTemplate<Strategy> candidate = p.computePosition();
         if (isVisuallyEquivalentCandidate(candidate))
             return candidate;
 
         p.decrement();
     }
 
-    return PositionAlgorithm<Strategy>();
+    return PositionTemplate<Strategy>();
 }
 
 Position previousCandidate(const Position& position)
@@ -416,24 +416,24 @@
 // for returning position which |downstream()| not equal to initial position's
 // |downstream()|.
 template <typename Strategy>
-PositionAlgorithm<Strategy> previousVisuallyDistinctCandidateAlgorithm(const PositionAlgorithm<Strategy>& position)
+PositionTemplate<Strategy> previousVisuallyDistinctCandidateAlgorithm(const PositionTemplate<Strategy>& position)
 {
     if (position.isNull())
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     PositionIteratorAlgorithm<Strategy> p(position);
-    PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(position);
+    PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition(position);
 
     p.decrement();
     while (!p.atStart()) {
-        PositionAlgorithm<Strategy> candidate = p.computePosition();
+        PositionTemplate<Strategy> candidate = p.computePosition();
         if (isVisuallyEquivalentCandidate(candidate) && mostForwardCaretPosition(candidate) != downstreamStart)
             return candidate;
 
         p.decrement();
     }
 
-    return PositionAlgorithm<Strategy>();
+    return PositionTemplate<Strategy>();
 }
 
 Position previousVisuallyDistinctCandidate(const Position& position)
@@ -457,27 +457,27 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(const PositionAlgorithm<Strategy>& position, Node* highestRoot)
+PositionTemplate<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(const PositionTemplate<Strategy>& position, Node* highestRoot)
 {
     // position falls before highestRoot.
-    if (position.compareTo(PositionAlgorithm<Strategy>::firstPositionInNode(highestRoot)) == -1 && highestRoot->hasEditableStyle())
-        return PositionAlgorithm<Strategy>::firstPositionInNode(highestRoot);
+    if (position.compareTo(PositionTemplate<Strategy>::firstPositionInNode(highestRoot)) == -1 && highestRoot->hasEditableStyle())
+        return PositionTemplate<Strategy>::firstPositionInNode(highestRoot);
 
-    PositionAlgorithm<Strategy> editablePosition = position;
+    PositionTemplate<Strategy> editablePosition = position;
 
     if (position.anchorNode()->treeScope() != highestRoot->treeScope()) {
         Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(editablePosition.anchorNode());
         if (!shadowAncestor)
-            return PositionAlgorithm<Strategy>();
+            return PositionTemplate<Strategy>();
 
-        editablePosition = PositionAlgorithm<Strategy>::afterNode(shadowAncestor);
+        editablePosition = PositionTemplate<Strategy>::afterNode(shadowAncestor);
     }
 
     while (editablePosition.anchorNode() && !isEditablePosition(editablePosition) && editablePosition.anchorNode()->isDescendantOf(highestRoot))
-        editablePosition = isAtomicNode(editablePosition.anchorNode()) ? PositionAlgorithm<Strategy>::inParentAfterNode(*editablePosition.anchorNode()) : nextVisuallyDistinctCandidate(editablePosition);
+        editablePosition = isAtomicNode(editablePosition.anchorNode()) ? PositionTemplate<Strategy>::inParentAfterNode(*editablePosition.anchorNode()) : nextVisuallyDistinctCandidate(editablePosition);
 
     if (editablePosition.anchorNode() && editablePosition.anchorNode() != highestRoot && !editablePosition.anchorNode()->isDescendantOf(highestRoot))
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     return editablePosition;
 }
@@ -503,27 +503,27 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> lastEditablePositionBeforePositionInRootAlgorithm(const PositionAlgorithm<Strategy>& position, Node* highestRoot)
+PositionTemplate<Strategy> lastEditablePositionBeforePositionInRootAlgorithm(const PositionTemplate<Strategy>& position, Node* highestRoot)
 {
     // When position falls after highestRoot, the result is easy to compute.
-    if (position.compareTo(PositionAlgorithm<Strategy>::lastPositionInNode(highestRoot)) == 1)
-        return PositionAlgorithm<Strategy>::lastPositionInNode(highestRoot);
+    if (position.compareTo(PositionTemplate<Strategy>::lastPositionInNode(highestRoot)) == 1)
+        return PositionTemplate<Strategy>::lastPositionInNode(highestRoot);
 
-    PositionAlgorithm<Strategy> editablePosition = position;
+    PositionTemplate<Strategy> editablePosition = position;
 
     if (position.anchorNode()->treeScope() != highestRoot->treeScope()) {
         Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(editablePosition.anchorNode());
         if (!shadowAncestor)
-            return PositionAlgorithm<Strategy>();
+            return PositionTemplate<Strategy>();
 
-        editablePosition = PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(shadowAncestor);
+        editablePosition = PositionTemplate<Strategy>::firstPositionInOrBeforeNode(shadowAncestor);
     }
 
     while (editablePosition.anchorNode() && !isEditablePosition(editablePosition) && editablePosition.anchorNode()->isDescendantOf(highestRoot))
-        editablePosition = isAtomicNode(editablePosition.anchorNode()) ? PositionAlgorithm<Strategy>::inParentBeforeNode(*editablePosition.anchorNode()) : previousVisuallyDistinctCandidate(editablePosition);
+        editablePosition = isAtomicNode(editablePosition.anchorNode()) ? PositionTemplate<Strategy>::inParentBeforeNode(*editablePosition.anchorNode()) : previousVisuallyDistinctCandidate(editablePosition);
 
     if (editablePosition.anchorNode() && editablePosition.anchorNode() != highestRoot && !editablePosition.anchorNode()->isDescendantOf(highestRoot))
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
     return editablePosition;
 }
 
@@ -553,7 +553,7 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> previousPositionOfAlgorithm(const PositionAlgorithm<Strategy>& position, PositionMoveType moveType)
+PositionTemplate<Strategy> previousPositionOfAlgorithm(const PositionTemplate<Strategy>& position, PositionMoveType moveType)
 {
     Node* const node = position.anchorNode();
     if (!node)
@@ -563,9 +563,9 @@
 
     if (offset > 0) {
         if (editingIgnoresContent(node))
-            return PositionAlgorithm<Strategy>::beforeNode(node);
+            return PositionTemplate<Strategy>::beforeNode(node);
         if (Node* child = Strategy::childAt(*node, offset - 1))
-            return PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(child);
+            return PositionTemplate<Strategy>::lastPositionInOrAfterNode(child);
 
         // There are two reasons child might be 0:
         //   1) The node is node like a text node that is not an element, and
@@ -575,20 +575,20 @@
         //      no child. Going from 1 to 0 is correct.
         switch (moveType) {
         case PositionMoveType::CodePoint:
-            return PositionAlgorithm<Strategy>(node, offset - 1);
+            return PositionTemplate<Strategy>(node, offset - 1);
         case PositionMoveType::Character:
-            return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffset(node, offset));
+            return PositionTemplate<Strategy>(node, uncheckedPreviousOffset(node, offset));
         case PositionMoveType::BackwardDeletion:
-            return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
+            return PositionTemplate<Strategy>(node, uncheckedPreviousOffsetForBackwardDeletion(node, offset));
         }
     }
 
     if (ContainerNode* parent = Strategy::parent(*node)) {
         if (editingIgnoresContent(parent))
-            return PositionAlgorithm<Strategy>::beforeNode(parent);
+            return PositionTemplate<Strategy>::beforeNode(parent);
         // TODO(yosin) We should use |Strategy::index(Node&)| instead of
         // |Node::nodeIndex()|.
-        return PositionAlgorithm<Strategy>(parent, node->nodeIndex());
+        return PositionTemplate<Strategy>(parent, node->nodeIndex());
     }
     return position;
 }
@@ -604,7 +604,7 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> nextPositionOfAlgorithm(const PositionAlgorithm<Strategy>& position, PositionMoveType moveType)
+PositionTemplate<Strategy> nextPositionOfAlgorithm(const PositionTemplate<Strategy>& position, PositionMoveType moveType)
 {
     ASSERT(moveType != PositionMoveType::BackwardDeletion);
 
@@ -615,7 +615,7 @@
     const int offset = position.computeEditingOffset();
 
     if (Node* child = Strategy::childAt(*node, offset))
-        return PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(child);
+        return PositionTemplate<Strategy>::firstPositionInOrBeforeNode(child);
 
     // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of
     // DOM tree version.
@@ -626,11 +626,11 @@
         //      is correct.
         //   2) The new offset is a bogus offset like (<br>, 1), and there is no
         //      child. Going from 0 to 1 is correct.
-        return PositionAlgorithm<Strategy>::editingPositionOf(node, (moveType == PositionMoveType::Character) ? uncheckedNextOffset(node, offset) : offset + 1);
+        return PositionTemplate<Strategy>::editingPositionOf(node, (moveType == PositionMoveType::Character) ? uncheckedNextOffset(node, offset) : offset + 1);
     }
 
     if (ContainerNode* parent = Strategy::parent(*node))
-        return PositionAlgorithm<Strategy>::editingPositionOf(parent, Strategy::index(*node) + 1);
+        return PositionTemplate<Strategy>::editingPositionOf(parent, Strategy::index(*node) + 1);
     return position;
 }
 
@@ -666,7 +666,7 @@
 }
 
 template <typename Strategy>
-Element* enclosingBlockAlgorithm(const PositionAlgorithm<Strategy>& position, EditingBoundaryCrossingRule rule)
+Element* enclosingBlockAlgorithm(const PositionTemplate<Strategy>& position, EditingBoundaryCrossingRule rule)
 {
     Node* enclosingNode = enclosingNodeOfType(position, isEnclosingBlock, rule);
     return enclosingNode && enclosingNode->isElementNode() ? toElement(enclosingNode) : nullptr;
@@ -711,9 +711,9 @@
 }
 
 template <typename Strategy>
-TextDirection directionOfEnclosingBlockAlgorithm(const PositionAlgorithm<Strategy>& position)
+TextDirection directionOfEnclosingBlockAlgorithm(const PositionTemplate<Strategy>& position)
 {
-    Element* enclosingBlockElement = enclosingBlock(PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(position.computeContainerNode()), CannotCrossEditingBoundary);
+    Element* enclosingBlockElement = enclosingBlock(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(position.computeContainerNode()), CannotCrossEditingBoundary);
     if (!enclosingBlockElement)
         return LTR;
     LayoutObject* layoutObject = enclosingBlockElement->layoutObject();
@@ -870,7 +870,7 @@
 template <typename Strategy>
 static Element* isFirstPositionAfterTableAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
 {
-    const PositionAlgorithm<Strategy> upstream(mostBackwardCaretPosition(visiblePosition.deepEquivalent()));
+    const PositionTemplate<Strategy> upstream(mostBackwardCaretPosition(visiblePosition.deepEquivalent()));
     if (isRenderedTableElement(upstream.anchorNode()) && upstream.atLastEditingPositionForNode())
         return toElement(upstream.anchorNode());
 
@@ -1002,7 +1002,7 @@
 }
 
 template <typename Strategy>
-static Node* enclosingNodeOfTypeAlgorithm(const PositionAlgorithm<Strategy>& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
+static Node* enclosingNodeOfTypeAlgorithm(const PositionTemplate<Strategy>& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
 {
     // TODO(yosin) support CanSkipCrossEditingBoundary
     ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
@@ -1560,8 +1560,8 @@
 
     // TODO(yosin) We should not call |parentAnchoredEquivalent()|, it is
     // redundant.
-    const PositionAlgorithm<Strategy> normalizedStart = mostForwardCaretPosition(range.startPosition()).parentAnchoredEquivalent();
-    const PositionAlgorithm<Strategy> normalizedEnd = mostBackwardCaretPosition(range.endPosition()).parentAnchoredEquivalent();
+    const PositionTemplate<Strategy> normalizedStart = mostForwardCaretPosition(range.startPosition()).parentAnchoredEquivalent();
+    const PositionTemplate<Strategy> normalizedEnd = mostBackwardCaretPosition(range.endPosition()).parentAnchoredEquivalent();
     // The order of the positions of |start| and |end| can be swapped after
     // upstream/downstream. e.g. editing/pasteboard/copy-display-none.html
     if (normalizedStart.compareTo(normalizedEnd) > 0)
diff --git a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
index 1f3acaa..a578146a 100644
--- a/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
+++ b/third_party/WebKit/Source/core/editing/EphemeralRange.cpp
@@ -13,7 +13,7 @@
 namespace blink {
 
 template <typename Strategy>
-EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end)
+EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end)
     : m_startPosition(start)
     , m_endPosition(end)
 #if ENABLE(ASSERT)
@@ -38,7 +38,7 @@
 }
 
 template <typename Strategy>
-EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(const PositionAlgorithm<Strategy>& position)
+EphemeralRangeTemplate<Strategy>::EphemeralRangeTemplate(const PositionTemplate<Strategy>& position)
     : EphemeralRangeTemplate(position, position)
 {
 }
@@ -97,14 +97,14 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> EphemeralRangeTemplate<Strategy>::startPosition() const
+PositionTemplate<Strategy> EphemeralRangeTemplate<Strategy>::startPosition() const
 {
     ASSERT(isValid());
     return m_startPosition;
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> EphemeralRangeTemplate<Strategy>::endPosition() const
+PositionTemplate<Strategy> EphemeralRangeTemplate<Strategy>::endPosition() const
 {
     ASSERT(isValid());
     return m_endPosition;
@@ -120,7 +120,7 @@
 template <typename Strategy>
 EphemeralRangeTemplate<Strategy> EphemeralRangeTemplate<Strategy>::rangeOfContents(const Node& node)
 {
-    return EphemeralRangeTemplate<Strategy>(PositionAlgorithm<Strategy>::firstPositionInNode(&const_cast<Node&>(node)), PositionAlgorithm<Strategy>::lastPositionInNode(&const_cast<Node&>(node)));
+    return EphemeralRangeTemplate<Strategy>(PositionTemplate<Strategy>::firstPositionInNode(&const_cast<Node&>(node)), PositionTemplate<Strategy>::lastPositionInNode(&const_cast<Node&>(node)));
 }
 
 #if ENABLE(ASSERT)
diff --git a/third_party/WebKit/Source/core/editing/EphemeralRange.h b/third_party/WebKit/Source/core/editing/EphemeralRange.h
index 5d41069..e70ce8a 100644
--- a/third_party/WebKit/Source/core/editing/EphemeralRange.h
+++ b/third_party/WebKit/Source/core/editing/EphemeralRange.h
@@ -38,10 +38,10 @@
 class CORE_TEMPLATE_CLASS_EXPORT EphemeralRangeTemplate final {
     STACK_ALLOCATED();
 public:
-    EphemeralRangeTemplate(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end);
+    EphemeralRangeTemplate(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end);
     EphemeralRangeTemplate(const EphemeralRangeTemplate& other);
     // |position| should be |Position::isNull()| or in-document.
-    explicit EphemeralRangeTemplate(const PositionAlgorithm<Strategy>& /* position */);
+    explicit EphemeralRangeTemplate(const PositionTemplate<Strategy>& /* position */);
     // When |range| is nullptr, |EphemeralRangeTemplate| is |isNull()|.
     explicit EphemeralRangeTemplate(const Range* /* range */);
     EphemeralRangeTemplate();
@@ -53,8 +53,8 @@
     bool operator!=(const EphemeralRangeTemplate<Strategy>& other) const;
 
     Document& document() const;
-    PositionAlgorithm<Strategy> startPosition() const;
-    PositionAlgorithm<Strategy> endPosition() const;
+    PositionTemplate<Strategy> startPosition() const;
+    PositionTemplate<Strategy> endPosition() const;
 
     // Returns true if |m_startPositoin| == |m_endPosition| or |isNull()|.
     bool isCollapsed() const;
@@ -72,14 +72,14 @@
     }
 
     // |node| should be in-document and valid for anchor node of
-    // |PositionAlgorithm<Strategy>|.
+    // |PositionTemplate<Strategy>|.
     static EphemeralRangeTemplate<Strategy> rangeOfContents(const Node& /* node */);
 
 private:
     bool isValid() const;
 
-    PositionAlgorithm<Strategy> m_startPosition;
-    PositionAlgorithm<Strategy> m_endPosition;
+    PositionTemplate<Strategy> m_startPosition;
+    PositionTemplate<Strategy> m_endPosition;
 #if ENABLE(ASSERT)
     uint64_t m_domTreeVersion;
 #endif
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index 3fd8f6b..92dd256 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -737,9 +737,9 @@
     if (visibleStart.isNull() || visibleEnd.isNull())
         return false;
 
-    const PositionAlgorithm<Strategy> start = visibleStart.deepEquivalent();
-    const PositionAlgorithm<Strategy> end = visibleEnd.deepEquivalent();
-    const PositionAlgorithm<Strategy> pos = visiblePos.deepEquivalent();
+    const PositionTemplate<Strategy> start = visibleStart.deepEquivalent();
+    const PositionTemplate<Strategy> end = visibleEnd.deepEquivalent();
+    const PositionTemplate<Strategy> pos = visiblePos.deepEquivalent();
     return start.compareTo(pos) <= 0 && pos.compareTo(end) <= 0;
 }
 
diff --git a/third_party/WebKit/Source/core/editing/PendingSelection.cpp b/third_party/WebKit/Source/core/editing/PendingSelection.cpp
index 2b95119..e9e796c 100644
--- a/third_party/WebKit/Source/core/editing/PendingSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/PendingSelection.cpp
@@ -45,13 +45,13 @@
 template <typename Strategy>
 static bool isSelectionInDocument(const VisibleSelectionTemplate<Strategy>& visibleSelection, const Document& document)
 {
-    const PositionAlgorithm<Strategy> start = visibleSelection.start();
+    const PositionTemplate<Strategy> start = visibleSelection.start();
     if (start.isNotNull() && (!start.inDocument() || start.document() != document))
         return false;
-    const PositionAlgorithm<Strategy> end = visibleSelection.end();
+    const PositionTemplate<Strategy> end = visibleSelection.end();
     if (end.isNotNull() && (!end.inDocument() || end.document() != document))
         return false;
-    const PositionAlgorithm<Strategy> extent = visibleSelection.extent();
+    const PositionTemplate<Strategy> extent = visibleSelection.extent();
     if (extent.isNotNull() && (!extent.inDocument() || extent.document() != document))
         return false;
     return true;
@@ -60,8 +60,8 @@
 template <typename Strategy>
 VisibleSelectionTemplate<Strategy> PendingSelection::calcVisibleSelectionAlgorithm(const VisibleSelectionTemplate<Strategy>& originalSelection) const
 {
-    const PositionAlgorithm<Strategy> start = originalSelection.start();
-    const PositionAlgorithm<Strategy> end = originalSelection.end();
+    const PositionTemplate<Strategy> start = originalSelection.start();
+    const PositionTemplate<Strategy> end = originalSelection.end();
     SelectionType selectionType = originalSelection.selectionType();
     const TextAffinity affinity = originalSelection.affinity();
 
@@ -70,7 +70,7 @@
     if (enclosingTextFormControl(start.computeContainerNode())) {
         // TODO(yosin) We should use |PositionMoveType::Character| to avoid
         // ending paint at middle of character.
-        PositionAlgorithm<Strategy> endPosition = paintBlockCursor ? nextPositionOf(originalSelection.extent(), PositionMoveType::CodePoint) : end;
+        PositionTemplate<Strategy> endPosition = paintBlockCursor ? nextPositionOf(originalSelection.extent(), PositionMoveType::CodePoint) : end;
         selection.setWithoutValidation(start, endPosition);
         return selection;
     }
@@ -116,11 +116,11 @@
     // If we pass [foo, 3] as the start of the selection, the selection painting
     // code will think that content on the line containing 'foo' is selected
     // and will fill the gap before 'bar'.
-    PositionAlgorithm<Strategy> startPos = selection.start();
-    PositionAlgorithm<Strategy> candidate = mostForwardCaretPosition(startPos);
+    PositionTemplate<Strategy> startPos = selection.start();
+    PositionTemplate<Strategy> candidate = mostForwardCaretPosition(startPos);
     if (isVisuallyEquivalentCandidate(candidate))
         startPos = candidate;
-    PositionAlgorithm<Strategy> endPos = selection.end();
+    PositionTemplate<Strategy> endPos = selection.end();
     candidate = mostBackwardCaretPosition(endPos);
     if (isVisuallyEquivalentCandidate(candidate))
         endPos = candidate;
diff --git a/third_party/WebKit/Source/core/editing/Position.cpp b/third_party/WebKit/Source/core/editing/Position.cpp
index f1c6789e..643f6f66 100644
--- a/third_party/WebKit/Source/core/editing/Position.cpp
+++ b/third_party/WebKit/Source/core/editing/Position.cpp
@@ -44,7 +44,7 @@
 #endif
 
 template <typename Strategy>
-const TreeScope* PositionAlgorithm<Strategy>::commonAncestorTreeScope(const PositionAlgorithm<Strategy>& a, const PositionAlgorithm<Strategy>& b)
+const TreeScope* PositionTemplate<Strategy>::commonAncestorTreeScope(const PositionTemplate<Strategy>& a, const PositionTemplate<Strategy>& b)
 {
     if (!a.computeContainerNode() || !b.computeContainerNode())
         return nullptr;
@@ -53,23 +53,23 @@
 
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::editingPositionOf(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::editingPositionOf(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset)
 {
     if (!anchorNode || anchorNode->isTextNode())
-        return PositionAlgorithm<Strategy>(anchorNode, offset);
+        return PositionTemplate<Strategy>(anchorNode, offset);
 
     if (!Strategy::editingIgnoresContent(anchorNode.get()))
-        return PositionAlgorithm<Strategy>(anchorNode, offset);
+        return PositionTemplate<Strategy>(anchorNode, offset);
 
     if (offset == 0)
-        return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::BeforeAnchor);
+        return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::BeforeAnchor);
 
     ASSERT(offset == Strategy::lastOffsetForEditing(anchorNode.get()));
-    return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::AfterAnchor);
+    return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::AfterAnchor);
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy>::PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anchorNode, PositionAnchorType anchorType)
+PositionTemplate<Strategy>::PositionTemplate(PassRefPtrWillBeRawPtr<Node> anchorNode, PositionAnchorType anchorType)
     : m_anchorNode(anchorNode)
     , m_offset(0)
     , m_anchorType(anchorType)
@@ -87,7 +87,7 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy>::PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset)
+PositionTemplate<Strategy>::PositionTemplate(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset)
     : m_anchorNode(anchorNode)
     , m_offset(offset)
     , m_anchorType(PositionAnchorType::OffsetInAnchor)
@@ -100,7 +100,7 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy>::PositionAlgorithm(const PositionAlgorithm& other)
+PositionTemplate<Strategy>::PositionTemplate(const PositionTemplate& other)
     : m_anchorNode(other.m_anchorNode)
     , m_offset(other.m_offset)
     , m_anchorType(other.m_anchorType)
@@ -110,7 +110,7 @@
 // --
 
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::computeContainerNode() const
+Node* PositionTemplate<Strategy>::computeContainerNode() const
 {
     if (!m_anchorNode)
         return 0;
@@ -129,7 +129,7 @@
 }
 
 template <typename Strategy>
-int PositionAlgorithm<Strategy>::computeOffsetInContainerNode() const
+int PositionTemplate<Strategy>::computeOffsetInContainerNode() const
 {
     if (!m_anchorNode)
         return 0;
@@ -153,16 +153,16 @@
 // Neighbor-anchored positions are invalid DOM positions, so they need to be
 // fixed up before handing them off to the Range object.
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::parentAnchoredEquivalent() const
+PositionTemplate<Strategy> PositionTemplate<Strategy>::parentAnchoredEquivalent() const
 {
     if (!m_anchorNode)
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     // FIXME: This should only be necessary for legacy positions, but is also needed for positions before and after Tables
     if (m_offset == 0 && !isAfterAnchorOrAfterChildren()) {
         if (Strategy::parent(*m_anchorNode) && (Strategy::editingIgnoresContent(m_anchorNode.get()) || isRenderedHTMLTableElement(m_anchorNode.get())))
             return inParentBeforeNode(*m_anchorNode);
-        return PositionAlgorithm<Strategy>(m_anchorNode.get(), 0);
+        return PositionTemplate<Strategy>(m_anchorNode.get(), 0);
     }
     if (!m_anchorNode->offsetInCharacters()
         && (isAfterAnchorOrAfterChildren() || static_cast<unsigned>(m_offset) == m_anchorNode->countChildren())
@@ -171,20 +171,20 @@
         return inParentAfterNode(*m_anchorNode);
     }
 
-    return PositionAlgorithm<Strategy>(computeContainerNode(), computeOffsetInContainerNode());
+    return PositionTemplate<Strategy>(computeContainerNode(), computeOffsetInContainerNode());
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::toOffsetInAnchor() const
+PositionTemplate<Strategy> PositionTemplate<Strategy>::toOffsetInAnchor() const
 {
     if (isNull())
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
-    return PositionAlgorithm<Strategy>(computeContainerNode(), computeOffsetInContainerNode());
+    return PositionTemplate<Strategy>(computeContainerNode(), computeOffsetInContainerNode());
 }
 
 template <typename Strategy>
-int PositionAlgorithm<Strategy>::computeEditingOffset() const
+int PositionTemplate<Strategy>::computeEditingOffset() const
 {
     if (isAfterAnchorOrAfterChildren())
         return Strategy::lastOffsetForEditing(m_anchorNode.get());
@@ -192,7 +192,7 @@
 }
 
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::computeNodeBeforePosition() const
+Node* PositionTemplate<Strategy>::computeNodeBeforePosition() const
 {
     if (!m_anchorNode)
         return 0;
@@ -213,7 +213,7 @@
 }
 
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::computeNodeAfterPosition() const
+Node* PositionTemplate<Strategy>::computeNodeAfterPosition() const
 {
     if (!m_anchorNode)
         return 0;
@@ -236,7 +236,7 @@
 
 // An implementation of |Range::firstNode()|.
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::nodeAsRangeFirstNode() const
+Node* PositionTemplate<Strategy>::nodeAsRangeFirstNode() const
 {
     if (!m_anchorNode)
         return nullptr;
@@ -252,7 +252,7 @@
 }
 
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::nodeAsRangeLastNode() const
+Node* PositionTemplate<Strategy>::nodeAsRangeLastNode() const
 {
     if (isNull())
         return nullptr;
@@ -263,7 +263,7 @@
 
 // An implementation of |Range::pastLastNode()|.
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::nodeAsRangePastLastNode() const
+Node* PositionTemplate<Strategy>::nodeAsRangePastLastNode() const
 {
     if (!m_anchorNode)
         return nullptr;
@@ -277,7 +277,7 @@
 }
 
 template <typename Strategy>
-Node* PositionAlgorithm<Strategy>::commonAncestorContainer(const PositionAlgorithm<Strategy>& other) const
+Node* PositionTemplate<Strategy>::commonAncestorContainer(const PositionTemplate<Strategy>& other) const
 {
     return Strategy::commonAncestor(*computeContainerNode(), *other.computeContainerNode());
 }
@@ -295,13 +295,13 @@
 }
 
 template <typename Strategy>
-int PositionAlgorithm<Strategy>::compareTo(const PositionAlgorithm<Strategy>& other) const
+int PositionTemplate<Strategy>::compareTo(const PositionTemplate<Strategy>& other) const
 {
     return comparePositions(*this, other);
 }
 
 template <typename Strategy>
-bool PositionAlgorithm<Strategy>::atFirstEditingPositionForNode() const
+bool PositionTemplate<Strategy>::atFirstEditingPositionForNode() const
 {
     if (isNull())
         return true;
@@ -324,7 +324,7 @@
 }
 
 template <typename Strategy>
-bool PositionAlgorithm<Strategy>::atLastEditingPositionForNode() const
+bool PositionTemplate<Strategy>::atLastEditingPositionForNode() const
 {
     if (isNull())
         return true;
@@ -337,7 +337,7 @@
 }
 
 template <typename Strategy>
-bool PositionAlgorithm<Strategy>::atStartOfTree() const
+bool PositionTemplate<Strategy>::atStartOfTree() const
 {
     if (isNull())
         return true;
@@ -345,7 +345,7 @@
 }
 
 template <typename Strategy>
-bool PositionAlgorithm<Strategy>::atEndOfTree() const
+bool PositionTemplate<Strategy>::atEndOfTree() const
 {
     if (isNull())
         return true;
@@ -355,7 +355,7 @@
 }
 
 template <typename Strategy>
-void PositionAlgorithm<Strategy>::debugPosition(const char* msg) const
+void PositionTemplate<Strategy>::debugPosition(const char* msg) const
 {
     static const char* const anchorTypes[] = {
         "OffsetInAnchor",
@@ -461,7 +461,7 @@
 #ifndef NDEBUG
 
 template <typename Strategy>
-void PositionAlgorithm<Strategy>::formatForDebugger(char* buffer, unsigned length) const
+void PositionTemplate<Strategy>::formatForDebugger(char* buffer, unsigned length) const
 {
     StringBuilder result;
 
@@ -480,7 +480,7 @@
 }
 
 template <typename Strategy>
-void PositionAlgorithm<Strategy>::showAnchorTypeAndOffset() const
+void PositionTemplate<Strategy>::showAnchorTypeAndOffset() const
 {
     switch (anchorType()) {
     case PositionAnchorType::OffsetInAnchor:
@@ -503,7 +503,7 @@
 }
 
 template <typename Strategy>
-void PositionAlgorithm<Strategy>::showTreeForThis() const
+void PositionTemplate<Strategy>::showTreeForThis() const
 {
     if (!anchorNode())
         return;
@@ -512,7 +512,7 @@
 }
 
 template <typename Strategy>
-void PositionAlgorithm<Strategy>::showTreeForThisInComposedTree() const
+void PositionTemplate<Strategy>::showTreeForThisInComposedTree() const
 {
     if (!anchorNode())
         return;
@@ -522,8 +522,8 @@
 
 #endif
 
-template class CORE_TEMPLATE_EXPORT PositionAlgorithm<EditingStrategy>;
-template class CORE_TEMPLATE_EXPORT PositionAlgorithm<EditingInComposedTreeStrategy>;
+template class CORE_TEMPLATE_EXPORT PositionTemplate<EditingStrategy>;
+template class CORE_TEMPLATE_EXPORT PositionTemplate<EditingInComposedTreeStrategy>;
 
 } // namespace blink
 
diff --git a/third_party/WebKit/Source/core/editing/Position.h b/third_party/WebKit/Source/core/editing/Position.h
index 5821c057..22ed4be7 100644
--- a/third_party/WebKit/Source/core/editing/Position.h
+++ b/third_party/WebKit/Source/core/editing/Position.h
@@ -53,29 +53,29 @@
     AfterChildren,
 };
 
-// Instances of |PositionAlgorithm<Strategy>| are immutable.
+// Instances of |PositionTemplate<Strategy>| are immutable.
 template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT PositionAlgorithm {
+class CORE_TEMPLATE_CLASS_EXPORT PositionTemplate {
     DISALLOW_ALLOCATION();
 public:
 
-    PositionAlgorithm()
+    PositionTemplate()
         : m_offset(0)
         , m_anchorType(PositionAnchorType::OffsetInAnchor)
     {
     }
 
-    static const TreeScope* commonAncestorTreeScope(const PositionAlgorithm<Strategy>&, const PositionAlgorithm<Strategy>& b);
-    static PositionAlgorithm<Strategy> editingPositionOf(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset);
+    static const TreeScope* commonAncestorTreeScope(const PositionTemplate<Strategy>&, const PositionTemplate<Strategy>& b);
+    static PositionTemplate<Strategy> editingPositionOf(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset);
 
     // For creating before/after positions:
-    PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anchorNode, PositionAnchorType);
+    PositionTemplate(PassRefPtrWillBeRawPtr<Node> anchorNode, PositionAnchorType);
 
     // For creating offset positions:
     // FIXME: This constructor should eventually go away. See bug 63040.
-    PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset);
+    PositionTemplate(PassRefPtrWillBeRawPtr<Node> anchorNode, int offset);
 
-    PositionAlgorithm(const PositionAlgorithm&);
+    PositionTemplate(const PositionTemplate&);
 
     PositionAnchorType anchorType() const { return m_anchorType; }
     bool isAfterAnchor() const { return m_anchorType == PositionAnchorType::AfterAnchor; }
@@ -89,13 +89,13 @@
     Node* computeContainerNode() const; // null for a before/after position anchored to a node with no parent
 
     int computeOffsetInContainerNode() const; // O(n) for before/after-anchored positions, O(1) for parent-anchored positions
-    PositionAlgorithm<Strategy> parentAnchoredEquivalent() const; // Convenience method for DOM positions that also fixes up some positions for editing
+    PositionTemplate<Strategy> parentAnchoredEquivalent() const; // Convenience method for DOM positions that also fixes up some positions for editing
 
     // Returns |PositionIsAnchor| type |Position| which is compatible with
     // |RangeBoundaryPoint| as safe to pass |Range| constructor. Return value
     // of this function is different from |parentAnchoredEquivalent()| which
     // returns editing specific position.
-    PositionAlgorithm<Strategy> toOffsetInAnchor() const;
+    PositionTemplate<Strategy> toOffsetInAnchor() const;
 
     // Inline O(1) access for Positions which callers know to be parent-anchored
     int offsetInContainerNode() const
@@ -132,7 +132,7 @@
     // behave as |Range| boundary point.
     Node* nodeAsRangePastLastNode() const;
 
-    Node* commonAncestorContainer(const PositionAlgorithm<Strategy>&) const;
+    Node* commonAncestorContainer(const PositionTemplate<Strategy>&) const;
 
     Node* anchorNode() const { return m_anchorNode.get(); }
 
@@ -143,7 +143,7 @@
     bool isNotNull() const { return m_anchorNode; }
     bool isOrphan() const { return m_anchorNode && !m_anchorNode->inDocument(); }
 
-    int compareTo(const PositionAlgorithm<Strategy>&) const;
+    int compareTo(const PositionTemplate<Strategy>&) const;
 
     // These can be either inside or just before/after the node, depending on
     // if the node is ignored by editing or not.
@@ -154,17 +154,17 @@
     bool atStartOfTree() const;
     bool atEndOfTree() const;
 
-    static PositionAlgorithm<Strategy> beforeNode(Node* anchorNode);
-    static PositionAlgorithm<Strategy> afterNode(Node* anchorNode);
-    static PositionAlgorithm<Strategy> inParentBeforeNode(const Node& anchorNode);
-    static PositionAlgorithm<Strategy> inParentAfterNode(const Node& anchorNode);
+    static PositionTemplate<Strategy> beforeNode(Node* anchorNode);
+    static PositionTemplate<Strategy> afterNode(Node* anchorNode);
+    static PositionTemplate<Strategy> inParentBeforeNode(const Node& anchorNode);
+    static PositionTemplate<Strategy> inParentAfterNode(const Node& anchorNode);
     static int lastOffsetInNode(Node* anchorNode);
-    static PositionAlgorithm<Strategy> firstPositionInNode(Node* anchorNode);
-    static PositionAlgorithm<Strategy> lastPositionInNode(Node* anchorNode);
+    static PositionTemplate<Strategy> firstPositionInNode(Node* anchorNode);
+    static PositionTemplate<Strategy> lastPositionInNode(Node* anchorNode);
     static int minOffsetForNode(Node* anchorNode, int offset);
     static bool offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode);
-    static PositionAlgorithm<Strategy> firstPositionInOrBeforeNode(Node* anchorNode);
-    static PositionAlgorithm<Strategy> lastPositionInOrAfterNode(Node* anchorNode);
+    static PositionTemplate<Strategy> firstPositionInOrBeforeNode(Node* anchorNode);
+    static PositionTemplate<Strategy> lastPositionInOrAfterNode(Node* anchorNode);
 
     void debugPosition(const char* msg = "") const;
 
@@ -194,14 +194,14 @@
     PositionAnchorType m_anchorType;
 };
 
-extern template class CORE_EXTERN_TEMPLATE_EXPORT PositionAlgorithm<EditingStrategy>;
-extern template class CORE_EXTERN_TEMPLATE_EXPORT PositionAlgorithm<EditingInComposedTreeStrategy>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT PositionTemplate<EditingStrategy>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT PositionTemplate<EditingInComposedTreeStrategy>;
 
-using Position = PositionAlgorithm<EditingStrategy>;
-using PositionInComposedTree = PositionAlgorithm<EditingInComposedTreeStrategy>;
+using Position = PositionTemplate<EditingStrategy>;
+using PositionInComposedTree = PositionTemplate<EditingInComposedTreeStrategy>;
 
 template <typename Strategy>
-bool operator==(const PositionAlgorithm<Strategy>& a, const PositionAlgorithm<Strategy>& b)
+bool operator==(const PositionTemplate<Strategy>& a, const PositionTemplate<Strategy>& b)
 {
     if (a.isNull())
         return b.isNull();
@@ -220,7 +220,7 @@
 }
 
 template <typename Strategy>
-bool operator!=(const PositionAlgorithm<Strategy>& a, const PositionAlgorithm<Strategy>& b)
+bool operator!=(const PositionTemplate<Strategy>& a, const PositionTemplate<Strategy>& b)
 {
     return !(a == b);
 }
@@ -230,13 +230,13 @@
 // If we ever add a PassPosition we can make these non-inline.
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::inParentBeforeNode(const Node& node)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::inParentBeforeNode(const Node& node)
 {
     // FIXME: This should ASSERT(node.parentNode())
     // At least one caller currently hits this ASSERT though, which indicates
     // that the caller is trying to make a position relative to a disconnected node (which is likely an error)
     // Specifically, editing/deleting/delete-ligature-001.html crashes with ASSERT(node->parentNode())
-    return PositionAlgorithm<Strategy>(Strategy::parent(node), Strategy::index(node));
+    return PositionTemplate<Strategy>(Strategy::parent(node), Strategy::index(node));
 }
 
 inline Position positionInParentBeforeNode(const Node& node)
@@ -245,10 +245,10 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::inParentAfterNode(const Node& node)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::inParentAfterNode(const Node& node)
 {
     ASSERT(node.parentNode());
-    return PositionAlgorithm<Strategy>(Strategy::parent(node), Strategy::index(node) + 1);
+    return PositionTemplate<Strategy>(Strategy::parent(node), Strategy::index(node) + 1);
 }
 
 inline Position positionInParentAfterNode(const Node& node)
@@ -258,10 +258,10 @@
 
 // positionBeforeNode and positionAfterNode return neighbor-anchored positions, construction is O(1)
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::beforeNode(Node* anchorNode)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::beforeNode(Node* anchorNode)
 {
     ASSERT(anchorNode);
-    return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::BeforeAnchor);
+    return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::BeforeAnchor);
 }
 
 inline Position positionBeforeNode(Node* anchorNode)
@@ -270,10 +270,10 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::afterNode(Node* anchorNode)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::afterNode(Node* anchorNode)
 {
     ASSERT(anchorNode);
-    return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::AfterAnchor);
+    return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::AfterAnchor);
 }
 
 inline Position positionAfterNode(Node* anchorNode)
@@ -282,7 +282,7 @@
 }
 
 template <typename Strategy>
-int PositionAlgorithm<Strategy>::lastOffsetInNode(Node* node)
+int PositionTemplate<Strategy>::lastOffsetInNode(Node* node)
 {
     return node->offsetInCharacters() ? node->maxCharacterOffset() : static_cast<int>(Strategy::countChildren(*node));
 }
@@ -294,11 +294,11 @@
 
 // firstPositionInNode and lastPositionInNode return parent-anchored positions, lastPositionInNode construction is O(n) due to countChildren()
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::firstPositionInNode(Node* anchorNode)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::firstPositionInNode(Node* anchorNode)
 {
     if (anchorNode->isTextNode())
-        return PositionAlgorithm<Strategy>(anchorNode, 0);
-    return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::BeforeChildren);
+        return PositionTemplate<Strategy>(anchorNode, 0);
+    return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::BeforeChildren);
 }
 
 inline Position firstPositionInNode(Node* anchorNode)
@@ -307,11 +307,11 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::lastPositionInNode(Node* anchorNode)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::lastPositionInNode(Node* anchorNode)
 {
     if (anchorNode->isTextNode())
-        return PositionAlgorithm<Strategy>(anchorNode, lastOffsetInNode(anchorNode));
-    return PositionAlgorithm<Strategy>(anchorNode, PositionAnchorType::AfterChildren);
+        return PositionTemplate<Strategy>(anchorNode, lastOffsetInNode(anchorNode));
+    return PositionTemplate<Strategy>(anchorNode, PositionAnchorType::AfterChildren);
 }
 
 inline Position lastPositionInNode(Node* anchorNode)
@@ -320,7 +320,7 @@
 }
 
 template <typename Strategy>
-int PositionAlgorithm<Strategy>::minOffsetForNode(Node* anchorNode, int offset)
+int PositionTemplate<Strategy>::minOffsetForNode(Node* anchorNode, int offset)
 {
     if (anchorNode->offsetInCharacters())
         return std::min(offset, anchorNode->maxCharacterOffset());
@@ -338,7 +338,7 @@
 }
 
 template <typename Strategy>
-bool PositionAlgorithm<Strategy>::offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode)
+bool PositionTemplate<Strategy>::offsetIsBeforeLastNodeOffset(int offset, Node* anchorNode)
 {
     if (anchorNode->offsetInCharacters())
         return offset < anchorNode->maxCharacterOffset();
@@ -356,18 +356,18 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(Node* node)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::firstPositionInOrBeforeNode(Node* node)
 {
     if (!node)
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
     return Strategy::editingIgnoresContent(node) ? beforeNode(node) : firstPositionInNode(node);
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(Node* node)
+PositionTemplate<Strategy> PositionTemplate<Strategy>::lastPositionInOrAfterNode(Node* node)
 {
     if (!node)
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
     return Strategy::editingIgnoresContent(node) ? afterNode(node) : lastPositionInNode(node);
 }
 
@@ -376,7 +376,7 @@
 CORE_EXPORT Position toPositionInDOMTree(const PositionInComposedTree&);
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> fromPositionInDOMTree(const Position&);
+PositionTemplate<Strategy> fromPositionInDOMTree(const Position&);
 
 template <>
 inline Position fromPositionInDOMTree<EditingStrategy>(const Position& position)
diff --git a/third_party/WebKit/Source/core/editing/PositionIterator.cpp b/third_party/WebKit/Source/core/editing/PositionIterator.cpp
index dba1ab7..a7b7258 100644
--- a/third_party/WebKit/Source/core/editing/PositionIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/PositionIterator.cpp
@@ -36,7 +36,7 @@
 {
 }
 template <typename Strategy>
-PositionIteratorAlgorithm<Strategy>::PositionIteratorAlgorithm(const PositionAlgorithm<Strategy>& pos)
+PositionIteratorAlgorithm<Strategy>::PositionIteratorAlgorithm(const PositionTemplate<Strategy>& pos)
     : PositionIteratorAlgorithm(pos.anchorNode(), pos.computeEditingOffset())
 {
 }
@@ -50,34 +50,34 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionIteratorAlgorithm<Strategy>::deprecatedComputePosition() const
+PositionTemplate<Strategy> PositionIteratorAlgorithm<Strategy>::deprecatedComputePosition() const
 {
     if (m_nodeAfterPositionInAnchor) {
         ASSERT(Strategy::parent(*m_nodeAfterPositionInAnchor) == m_anchorNode);
         // FIXME: This check is inadaquete because any ancestor could be ignored by editing
         if (Strategy::editingIgnoresContent(Strategy::parent(*m_nodeAfterPositionInAnchor)))
-            return PositionAlgorithm<Strategy>::beforeNode(m_anchorNode);
-        return PositionAlgorithm<Strategy>::inParentBeforeNode(*m_nodeAfterPositionInAnchor);
+            return PositionTemplate<Strategy>::beforeNode(m_anchorNode);
+        return PositionTemplate<Strategy>::inParentBeforeNode(*m_nodeAfterPositionInAnchor);
     }
     if (Strategy::hasChildren(*m_anchorNode))
-        return PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(m_anchorNode);
-    return PositionAlgorithm<Strategy>::editingPositionOf(m_anchorNode, m_offsetInAnchor);
+        return PositionTemplate<Strategy>::lastPositionInOrAfterNode(m_anchorNode);
+    return PositionTemplate<Strategy>::editingPositionOf(m_anchorNode, m_offsetInAnchor);
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> PositionIteratorAlgorithm<Strategy>::computePosition() const
+PositionTemplate<Strategy> PositionIteratorAlgorithm<Strategy>::computePosition() const
 {
     if (m_nodeAfterPositionInAnchor) {
         ASSERT(Strategy::parent(*m_nodeAfterPositionInAnchor) == m_anchorNode);
-        return PositionAlgorithm<Strategy>::inParentBeforeNode(*m_nodeAfterPositionInAnchor);
+        return PositionTemplate<Strategy>::inParentBeforeNode(*m_nodeAfterPositionInAnchor);
     }
     if (Strategy::hasChildren(*m_anchorNode))
-        return PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(m_anchorNode);
+        return PositionTemplate<Strategy>::lastPositionInOrAfterNode(m_anchorNode);
     if (m_anchorNode->isTextNode())
-        return PositionAlgorithm<Strategy>(m_anchorNode, m_offsetInAnchor);
+        return PositionTemplate<Strategy>(m_anchorNode, m_offsetInAnchor);
     if (m_offsetInAnchor)
-        return PositionAlgorithm<Strategy>(m_anchorNode, PositionAnchorType::AfterAnchor);
-    return PositionAlgorithm<Strategy>(m_anchorNode, PositionAnchorType::BeforeAnchor);
+        return PositionTemplate<Strategy>(m_anchorNode, PositionAnchorType::AfterAnchor);
+    return PositionTemplate<Strategy>(m_anchorNode, PositionAnchorType::BeforeAnchor);
 }
 
 template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/editing/PositionIterator.h b/third_party/WebKit/Source/core/editing/PositionIterator.h
index fa3851db..0383cf1 100644
--- a/third_party/WebKit/Source/core/editing/PositionIterator.h
+++ b/third_party/WebKit/Source/core/editing/PositionIterator.h
@@ -41,13 +41,13 @@
 class PositionIteratorAlgorithm {
     STACK_ALLOCATED();
 public:
-    explicit PositionIteratorAlgorithm(const PositionAlgorithm<Strategy>&);
+    explicit PositionIteratorAlgorithm(const PositionTemplate<Strategy>&);
     PositionIteratorAlgorithm();
 
     // Since |deprecatedComputePosition()| is slow, new code should use
     // |computePosition()| instead.
-    PositionAlgorithm<Strategy> deprecatedComputePosition() const;
-    PositionAlgorithm<Strategy> computePosition() const;
+    PositionTemplate<Strategy> deprecatedComputePosition() const;
+    PositionTemplate<Strategy> computePosition() const;
 
     void increment();
     void decrement();
diff --git a/third_party/WebKit/Source/core/editing/PositionWithAffinity.cpp b/third_party/WebKit/Source/core/editing/PositionWithAffinity.cpp
index b4fba3749..004ef80 100644
--- a/third_party/WebKit/Source/core/editing/PositionWithAffinity.cpp
+++ b/third_party/WebKit/Source/core/editing/PositionWithAffinity.cpp
@@ -8,7 +8,7 @@
 namespace blink {
 
 template <typename Strategy>
-PositionWithAffinityTemplate<Strategy>::PositionWithAffinityTemplate(const PositionAlgorithm<Strategy>& position, TextAffinity affinity)
+PositionWithAffinityTemplate<Strategy>::PositionWithAffinityTemplate(const PositionTemplate<Strategy>& position, TextAffinity affinity)
     : m_position(position)
     , m_affinity(affinity)
 {
diff --git a/third_party/WebKit/Source/core/editing/PositionWithAffinity.h b/third_party/WebKit/Source/core/editing/PositionWithAffinity.h
index b2be25ac..be44211 100644
--- a/third_party/WebKit/Source/core/editing/PositionWithAffinity.h
+++ b/third_party/WebKit/Source/core/editing/PositionWithAffinity.h
@@ -17,12 +17,12 @@
 public:
     // TODO(yosin) We should have single parameter constructor not to use
     // default parameter for avoiding include "TextAffinity.h"
-    PositionWithAffinityTemplate(const PositionAlgorithm<Strategy>&, TextAffinity = TextAffinity::Downstream);
+    PositionWithAffinityTemplate(const PositionTemplate<Strategy>&, TextAffinity = TextAffinity::Downstream);
     PositionWithAffinityTemplate();
     ~PositionWithAffinityTemplate();
 
     TextAffinity affinity() const { return m_affinity; }
-    const PositionAlgorithm<Strategy>& position() const { return m_position; }
+    const PositionTemplate<Strategy>& position() const { return m_position; }
 
     // Returns true if both |this| and |other| is null or both |m_position|
     // and |m_affinity| equal.
@@ -38,7 +38,7 @@
     }
 
 private:
-    PositionAlgorithm<Strategy> m_position;
+    PositionTemplate<Strategy> m_position;
     TextAffinity m_affinity;
 };
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index 2f38f94..52e28a7 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -90,14 +90,14 @@
         return selection;
 
     VisibleSelectionTemplate<Strategy> newSelection(selection);
-    newSelection.setBase(mostBackwardCaretPosition(PositionAlgorithm<Strategy>::beforeNode(rootUserSelectAll), CanCrossEditingBoundary));
-    newSelection.setExtent(mostForwardCaretPosition(PositionAlgorithm<Strategy>::afterNode(rootUserSelectAll), CanCrossEditingBoundary));
+    newSelection.setBase(mostBackwardCaretPosition(PositionTemplate<Strategy>::beforeNode(rootUserSelectAll), CanCrossEditingBoundary));
+    newSelection.setExtent(mostForwardCaretPosition(PositionTemplate<Strategy>::afterNode(rootUserSelectAll), CanCrossEditingBoundary));
 
     return newSelection;
 }
 
 template <typename Strategy>
-static int textDistance(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end)
+static int textDistance(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end)
 {
     return TextIteratorAlgorithm<Strategy>::rangeLength(start, end, true);
 }
@@ -141,8 +141,8 @@
     const PositionWithAffinity eventPos = innerNode->layoutObject()->positionForPoint(event.localPoint());
     VisiblePositionTemplate<Strategy> visiblePos = createVisiblePosition(fromPositionInDOMTree<Strategy>(eventPos));
     if (visiblePos.isNull())
-        visiblePos = createVisiblePosition(PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(innerNode));
-    PositionAlgorithm<Strategy> pos = visiblePos.deepEquivalent();
+        visiblePos = createVisiblePosition(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(innerNode));
+    PositionTemplate<Strategy> pos = visiblePos.deepEquivalent();
 
     VisibleSelectionTemplate<Strategy> newSelection = selection().visibleSelection<Strategy>();
     TextGranularity granularity = CharacterGranularity;
@@ -160,8 +160,8 @@
             if (pos.isNotNull()) {
                 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click
                 // deselects when selection was created right-to-left
-                const PositionAlgorithm<Strategy> start = newSelection.start();
-                const PositionAlgorithm<Strategy> end = newSelection.end();
+                const PositionTemplate<Strategy> start = newSelection.start();
+                const PositionTemplate<Strategy> end = newSelection.end();
                 int distanceToStart = textDistance(start, pos);
                 int distanceToEnd = textDistance(pos, end);
                 if (distanceToStart <= distanceToEnd)
@@ -234,22 +234,22 @@
         // TODO(yosin) Should we use |Strategy::rootUserSelectAllForNode()|?
         Node* rootUserSelectAllForMousePressNode = EditingStrategy::rootUserSelectAllForNode(mousePressNode);
         if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == EditingStrategy::rootUserSelectAllForNode(target)) {
-            newSelection.setBase(mostBackwardCaretPosition(PositionAlgorithm<Strategy>::beforeNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
-            newSelection.setExtent(mostForwardCaretPosition(PositionAlgorithm<Strategy>::afterNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
+            newSelection.setBase(mostBackwardCaretPosition(PositionTemplate<Strategy>::beforeNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
+            newSelection.setExtent(mostForwardCaretPosition(PositionTemplate<Strategy>::afterNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
         } else {
             // Reset base for user select all when base is inside user-select-all area and extent < base.
             if (rootUserSelectAllForMousePressNode) {
-                PositionAlgorithm<Strategy> eventPosition = fromPositionInDOMTree<Strategy>(target->layoutObject()->positionForPoint(hitTestResult.localPoint()).position());
-                PositionAlgorithm<Strategy> dragStartPosition = fromPositionInDOMTree<Strategy>(mousePressNode->layoutObject()->positionForPoint(dragStartPos).position());
+                PositionTemplate<Strategy> eventPosition = fromPositionInDOMTree<Strategy>(target->layoutObject()->positionForPoint(hitTestResult.localPoint()).position());
+                PositionTemplate<Strategy> dragStartPosition = fromPositionInDOMTree<Strategy>(mousePressNode->layoutObject()->positionForPoint(dragStartPos).position());
                 if (eventPosition.compareTo(dragStartPosition) < 0)
-                    newSelection.setBase(mostForwardCaretPosition(PositionAlgorithm<Strategy>::afterNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
+                    newSelection.setBase(mostForwardCaretPosition(PositionTemplate<Strategy>::afterNode(rootUserSelectAllForMousePressNode), CanCrossEditingBoundary));
             }
 
             Node* rootUserSelectAllForTarget = EditingStrategy::rootUserSelectAllForNode(target);
             if (rootUserSelectAllForTarget && mousePressNode->layoutObject() && fromPositionInDOMTree<Strategy>(target->layoutObject()->positionForPoint(hitTestResult.localPoint()).position()).compareTo(fromPositionInDOMTree<Strategy>(mousePressNode->layoutObject()->positionForPoint(dragStartPos).position())) < 0)
-                newSelection.setExtent(mostBackwardCaretPosition(PositionAlgorithm<Strategy>::beforeNode(rootUserSelectAllForTarget), CanCrossEditingBoundary));
+                newSelection.setExtent(mostBackwardCaretPosition(PositionTemplate<Strategy>::beforeNode(rootUserSelectAllForTarget), CanCrossEditingBoundary));
             else if (rootUserSelectAllForTarget && mousePressNode->layoutObject())
-                newSelection.setExtent(mostForwardCaretPosition(PositionAlgorithm<Strategy>::afterNode(rootUserSelectAllForTarget), CanCrossEditingBoundary));
+                newSelection.setExtent(mostForwardCaretPosition(PositionTemplate<Strategy>::afterNode(rootUserSelectAllForTarget), CanCrossEditingBoundary));
             else
                 newSelection.setExtent(targetPosition);
         }
@@ -331,12 +331,12 @@
 
     VisiblePositionTemplate<Strategy> pos = createVisiblePosition(fromPositionInDOMTree<Strategy>(innerNode->layoutObject()->positionForPoint(result.localPoint())));
     if (pos.isNotNull()) {
-        const PositionAlgorithm<Strategy> markerPosition = pos.deepEquivalent().parentAnchoredEquivalent();
+        const PositionTemplate<Strategy> markerPosition = pos.deepEquivalent().parentAnchoredEquivalent();
         DocumentMarkerVector markers = innerNode->document().markers().markersInRange(EphemeralRange(toPositionInDOMTree(markerPosition)), DocumentMarker::MisspellingMarkers());
         if (markers.size() == 1) {
             Node* containerNode = markerPosition.computeContainerNode();
-            const PositionAlgorithm<Strategy> start(containerNode, markers[0]->startOffset());
-            const PositionAlgorithm<Strategy> end(containerNode, markers[0]->endOffset());
+            const PositionTemplate<Strategy> start(containerNode, markers[0]->startOffset());
+            const PositionTemplate<Strategy> end(containerNode, markers[0]->endOffset());
             newSelection = VisibleSelectionTemplate<Strategy>(start, end);
         }
     }
diff --git a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
index 3de66608..4687c606 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
+++ b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
@@ -63,7 +63,7 @@
 template<typename Strategy>
 VisiblePositionTemplate<Strategy> VisiblePositionTemplate<Strategy>::create(const PositionWithAffinityTemplate<Strategy>& positionWithAffinity)
 {
-    const PositionAlgorithm<Strategy> deepPosition = canonicalPositionOf(positionWithAffinity.position());
+    const PositionTemplate<Strategy> deepPosition = canonicalPositionOf(positionWithAffinity.position());
     if (deepPosition.isNull())
         return VisiblePositionTemplate<Strategy>();
     const PositionWithAffinityTemplate<Strategy> downstreamPosition(deepPosition);
diff --git a/third_party/WebKit/Source/core/editing/VisiblePosition.h b/third_party/WebKit/Source/core/editing/VisiblePosition.h
index 74550f8..c84fb8db 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePosition.h
+++ b/third_party/WebKit/Source/core/editing/VisiblePosition.h
@@ -88,8 +88,8 @@
     bool isNotNull() const { return m_positionWithAffinity.isNotNull(); }
     bool isOrphan() const { return deepEquivalent().isOrphan(); }
 
-    PositionAlgorithm<Strategy> deepEquivalent() const { return m_positionWithAffinity.position(); }
-    PositionAlgorithm<Strategy> toParentAnchoredPosition() const { return deepEquivalent().parentAnchoredEquivalent(); }
+    PositionTemplate<Strategy> deepEquivalent() const { return m_positionWithAffinity.position(); }
+    PositionTemplate<Strategy> toParentAnchoredPosition() const { return deepEquivalent().parentAnchoredEquivalent(); }
     PositionWithAffinityTemplate<Strategy> toPositionWithAffinity() const { return m_positionWithAffinity; }
     TextAffinity affinity() const { return m_positionWithAffinity.affinity(); }
 
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 85ee1d61..44601a6 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -296,7 +296,7 @@
 }
 
 template <typename Strategy>
-static EphemeralRangeTemplate<Strategy> makeSearchRange(const PositionAlgorithm<Strategy>& pos)
+static EphemeralRangeTemplate<Strategy> makeSearchRange(const PositionTemplate<Strategy>& pos)
 {
     Node* node = pos.anchorNode();
     if (!node)
@@ -308,7 +308,7 @@
     if (!boundary)
         return EphemeralRangeTemplate<Strategy>();
 
-    return EphemeralRangeTemplate<Strategy>(pos, PositionAlgorithm<Strategy>::lastPositionInNode(boundary));
+    return EphemeralRangeTemplate<Strategy>(pos, PositionTemplate<Strategy>::lastPositionInNode(boundary));
 }
 
 void VisibleSelection::appendTrailingWhitespace()
@@ -1141,7 +1141,7 @@
 // ----
 
 template <typename Strategy>
-VisibleSelectionTemplate<Strategy>::VisibleSelectionTemplate(const PositionAlgorithm<Strategy>& base, const PositionAlgorithm<Strategy>& extent, TextAffinity affinity)
+VisibleSelectionTemplate<Strategy>::VisibleSelectionTemplate(const PositionTemplate<Strategy>& base, const PositionTemplate<Strategy>& extent, TextAffinity affinity)
     : VisibleSelectionTemplate(VisibleSelection(base, extent, affinity))
 {
 }
@@ -1188,7 +1188,7 @@
 }
 
 template <typename Strategy>
-void VisibleSelectionTemplate<Strategy>::setWithoutValidation(const PositionAlgorithm<Strategy>& base, const PositionAlgorithm<Strategy>& extent)
+void VisibleSelectionTemplate<Strategy>::setWithoutValidation(const PositionTemplate<Strategy>& base, const PositionTemplate<Strategy>& extent)
 {
     m_visibleSelection.setWithoutValidation(base, extent);
 }
@@ -1266,6 +1266,23 @@
 }
 
 template <> CORE_TEMPLATE_EXPORT
+VisibleSelectionTemplate<EditingInComposedTreeStrategy>::VisibleSelectionTemplate(const VisibleSelection& visibleSelection)
+    : m_visibleSelection(visibleSelection)
+{
+}
+
+template <> CORE_TEMPLATE_EXPORT
+VisibleSelectionTemplate<EditingInComposedTreeStrategy>::VisibleSelectionTemplate(const VisiblePositionTemplate<EditingInComposedTreeStrategy>& visiblePosition)
+    : VisibleSelectionTemplate(VisibleSelection(visiblePosition.deepEquivalent(), visiblePosition.deepEquivalent(), visiblePosition.affinity()))
+{
+}
+
+template <> CORE_TEMPLATE_EXPORT
+VisibleSelectionTemplate<EditingInComposedTreeStrategy>::VisibleSelectionTemplate()
+{
+}
+
+template <> CORE_TEMPLATE_EXPORT
 bool VisibleSelectionTemplate<EditingInComposedTreeStrategy>::operator==(const VisibleSelectionTemplate<EditingInComposedTreeStrategy>& other) const
 {
     return equalSelectionsInComposedTree(m_visibleSelection, other.m_visibleSelection);
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.h b/third_party/WebKit/Source/core/editing/VisibleSelection.h
index da88470..bcd64ee 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.h
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.h
@@ -268,7 +268,7 @@
 class CORE_TEMPLATE_CLASS_EXPORT VisibleSelectionTemplate final {
     STACK_ALLOCATED();
 public:
-    VisibleSelectionTemplate(const PositionAlgorithm<Strategy>& base, const PositionAlgorithm<Strategy>& extent, TextAffinity = TextAffinity::Downstream);
+    VisibleSelectionTemplate(const PositionTemplate<Strategy>& base, const PositionTemplate<Strategy>& extent, TextAffinity = TextAffinity::Downstream);
     VisibleSelectionTemplate(const VisiblePositionTemplate<Strategy>& base, const VisiblePositionTemplate<Strategy>& extent);
     explicit VisibleSelectionTemplate(const VisibleSelection&);
     explicit VisibleSelectionTemplate(const VisiblePositionTemplate<Strategy>&);
@@ -277,10 +277,10 @@
     operator const VisibleSelection&() const { return m_visibleSelection; }
 
     TextAffinity affinity() const { return m_visibleSelection.affinity(); }
-    PositionAlgorithm<Strategy> base() const;
-    PositionAlgorithm<Strategy> extent() const;
-    PositionAlgorithm<Strategy> start() const;
-    PositionAlgorithm<Strategy> end() const;
+    PositionTemplate<Strategy> base() const;
+    PositionTemplate<Strategy> extent() const;
+    PositionTemplate<Strategy> start() const;
+    PositionTemplate<Strategy> end() const;
     SelectionType selectionType() const { return m_visibleSelection.selectionType(); }
     VisiblePositionTemplate<Strategy> visibleStart() const;
     VisiblePositionTemplate<Strategy> visibleEnd() const;
@@ -294,12 +294,12 @@
 
     EphemeralRangeTemplate<Strategy> toNormalizedEphemeralRange() const;
 
-    void setBase(const PositionAlgorithm<Strategy>&);
+    void setBase(const PositionTemplate<Strategy>&);
     void setBase(const VisiblePositionTemplate<Strategy>&);
-    void setExtent(const PositionAlgorithm<Strategy>&);
+    void setExtent(const PositionTemplate<Strategy>&);
     void setExtent(const VisiblePositionTemplate<Strategy>&);
     void setIsDirectional(bool isDirectional) { m_visibleSelection.setIsDirectional(isDirectional); }
-    void setWithoutValidation(const PositionAlgorithm<Strategy>& base, const PositionAlgorithm<Strategy>& extent);
+    void setWithoutValidation(const PositionTemplate<Strategy>& base, const PositionTemplate<Strategy>& extent);
 
     void appendTrailingWhitespace();
     bool expandUsingGranularity(TextGranularity);
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
index 1c2bac6..aa3c63a 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelectionTest.cpp
@@ -45,8 +45,8 @@
     void setSelection(VisibleSelectionTemplate<Strategy>& selection, int base, int extend)
     {
         Node* node = document().body()->firstChild();
-        selection.setBase(PositionAlgorithm<Strategy>(node, base));
-        selection.setExtent(PositionAlgorithm<Strategy>(node, extend));
+        selection.setBase(PositionTemplate<Strategy>(node, base));
+        selection.setExtent(PositionTemplate<Strategy>(node, extend));
     }
 };
 
@@ -61,6 +61,109 @@
     EXPECT_EQ(selection.extent(), toPositionInDOMTree(selectionInComposedTree.extent()));
 }
 
+TEST_F(VisibleSelectionTest, expandUsingGranularity)
+{
+    const char* bodyContent = "<span id=host><a id=one>1</a><a id=two>22</a></span>";
+    const char* shadowContent = "<p><b id=three>333</b><content select=#two></content><b id=four>4444</b><span id=space>  </span><content select=#one></content><b id=five>55555</b></p>";
+    setBodyContent(bodyContent);
+    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
+    updateLayoutAndStyleForPainting();
+
+    Node* one = document().getElementById("one")->firstChild();
+    Node* two = document().getElementById("two")->firstChild();
+    Node* three = shadowRoot->getElementById("three")->firstChild();
+    Node* four = shadowRoot->getElementById("four")->firstChild();
+    Node* five = shadowRoot->getElementById("five")->firstChild();
+    Node* space = shadowRoot->getElementById("space")->firstChild();
+
+    VisibleSelection selection;
+    VisibleSelectionInComposedTree selectionInComposedTree;
+
+    // From a position at distributed node
+    selection = VisibleSelection(createVisiblePosition(Position(one, 1)));
+    selection.expandUsingGranularity(WordGranularity);
+    selectionInComposedTree = VisibleSelectionInComposedTree(createVisiblePosition(PositionInComposedTree(one, 1)));
+    selectionInComposedTree.expandUsingGranularity(WordGranularity);
+
+    EXPECT_EQ(Position(one, 1), selection.base());
+    EXPECT_EQ(Position(one, 1), selection.extent());
+    EXPECT_EQ(Position(one, 0), selection.start());
+    EXPECT_EQ(Position(two, 2), selection.end());
+
+    EXPECT_EQ(PositionInComposedTree(one, 1), selectionInComposedTree.base());
+    EXPECT_EQ(PositionInComposedTree(one, 1), selectionInComposedTree.extent());
+    // TODO(yosin) Once we have full version of VisibleSelectionInComposedTree
+    // we should change them (one, 0) - (five, 5).
+    EXPECT_EQ(PositionInComposedTree(four, 0), selectionInComposedTree.start());
+    EXPECT_EQ(PositionInComposedTree(space, 1), selectionInComposedTree.end());
+
+    // From a position at distributed node
+    selection = VisibleSelection(createVisiblePosition(Position(two, 1)));
+    selection.expandUsingGranularity(WordGranularity);
+    selectionInComposedTree = VisibleSelectionInComposedTree(createVisiblePosition(PositionInComposedTree(two, 1)));
+    selectionInComposedTree.expandUsingGranularity(WordGranularity);
+
+    EXPECT_EQ(Position(two, 1), selection.base());
+    EXPECT_EQ(Position(two, 1), selection.extent());
+    EXPECT_EQ(Position(one, 0), selection.start());
+    EXPECT_EQ(Position(two, 2), selection.end());
+
+    EXPECT_EQ(PositionInComposedTree(two, 1), selectionInComposedTree.base());
+    EXPECT_EQ(PositionInComposedTree(two, 1), selectionInComposedTree.extent());
+    // TODO(yosin) Once we have full version of VisibleSelectionInComposedTree
+    // we should change them (three, 0) - (four, 4).
+    EXPECT_EQ(PositionInComposedTree(four, 0), selectionInComposedTree.start());
+    EXPECT_EQ(PositionInComposedTree(space, 1), selectionInComposedTree.end());
+
+    // From a position at node in shadow tree
+    selection = VisibleSelection(createVisiblePosition(Position(three, 1)));
+    selection.expandUsingGranularity(WordGranularity);
+    selectionInComposedTree = VisibleSelectionInComposedTree(createVisiblePosition(PositionInComposedTree(three, 1)));
+    selectionInComposedTree.expandUsingGranularity(WordGranularity);
+
+    EXPECT_EQ(Position(three, 1), selection.base());
+    EXPECT_EQ(Position(three, 1), selection.extent());
+    EXPECT_EQ(Position(three, 0), selection.start());
+    EXPECT_EQ(Position(four, 4), selection.end());
+
+    EXPECT_EQ(PositionInComposedTree(three, 1), selectionInComposedTree.base());
+    EXPECT_EQ(PositionInComposedTree(three, 1), selectionInComposedTree.extent());
+    EXPECT_EQ(PositionInComposedTree(three, 0), selectionInComposedTree.start());
+    EXPECT_EQ(PositionInComposedTree(four, 4), selectionInComposedTree.end());
+
+    // From a position at node in shadow tree
+    selection = VisibleSelection(createVisiblePosition(Position(four, 1)));
+    selection.expandUsingGranularity(WordGranularity);
+    selectionInComposedTree = VisibleSelectionInComposedTree(createVisiblePosition(PositionInComposedTree(four, 1)));
+    selectionInComposedTree.expandUsingGranularity(WordGranularity);
+
+    EXPECT_EQ(Position(four, 1), selection.base());
+    EXPECT_EQ(Position(four, 1), selection.extent());
+    EXPECT_EQ(Position(three, 0), selection.start());
+    EXPECT_EQ(Position(four, 4), selection.end());
+
+    EXPECT_EQ(PositionInComposedTree(four, 1), selectionInComposedTree.base());
+    EXPECT_EQ(PositionInComposedTree(four, 1), selectionInComposedTree.extent());
+    EXPECT_EQ(PositionInComposedTree(three, 0), selectionInComposedTree.start());
+    EXPECT_EQ(PositionInComposedTree(four, 4), selectionInComposedTree.end());
+
+    // From a position at node in shadow tree
+    selection = VisibleSelection(createVisiblePosition(Position(five, 1)));
+    selection.expandUsingGranularity(WordGranularity);
+    selectionInComposedTree = VisibleSelectionInComposedTree(createVisiblePosition(PositionInComposedTree(five, 1)));
+    selectionInComposedTree.expandUsingGranularity(WordGranularity);
+
+    EXPECT_EQ(Position(five, 1), selection.base());
+    EXPECT_EQ(Position(five, 1), selection.extent());
+    EXPECT_EQ(Position(five, 0), selection.start());
+    EXPECT_EQ(Position(five, 5), selection.end());
+
+    EXPECT_EQ(PositionInComposedTree(five, 1), selectionInComposedTree.base());
+    EXPECT_EQ(PositionInComposedTree(five, 1), selectionInComposedTree.extent());
+    EXPECT_EQ(PositionInComposedTree(one, 0), selectionInComposedTree.start());
+    EXPECT_EQ(PositionInComposedTree(five, 5), selectionInComposedTree.end());
+}
+
 TEST_F(VisibleSelectionTest, Initialisation)
 {
     setBodyContent(LOREM_IPSUM);
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index e0265d75..75c8f02 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -163,7 +163,7 @@
 }
 
 template <typename Strategy>
-static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBefore(const PositionWithAffinityTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
+static PositionWithAffinityTemplate<Strategy> honorEditingBoundaryAtOrBefore(const PositionWithAffinityTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
 {
     if (pos.isNull())
         return pos;
@@ -195,13 +195,13 @@
 }
 
 template <typename Strategy>
-static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const VisiblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
+static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrBefore(const VisiblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
 {
     return createVisiblePosition(honorEditingBoundaryAtOrBefore(pos.toPositionWithAffinity(), anchor));
 }
 
 template <typename Strategy>
-static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const VisiblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
+static VisiblePositionTemplate<Strategy> honorEditingBoundaryAtOrAfter(const VisiblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
 {
     if (pos.isNull())
         return pos;
@@ -631,7 +631,7 @@
 }
 
 template <typename Strategy>
-static Node* parentEditingBoundary(const PositionAlgorithm<Strategy>& position)
+static Node* parentEditingBoundary(const PositionTemplate<Strategy>& position)
 {
     Node* const anchorNode = position.anchorNode();
     if (!anchorNode)
@@ -655,19 +655,19 @@
 template <typename Strategy>
 static VisiblePositionTemplate<Strategy> previousBoundary(const VisiblePositionTemplate<Strategy>& c, BoundarySearchFunction searchFunction)
 {
-    const PositionAlgorithm<Strategy> pos = c.deepEquivalent();
+    const PositionTemplate<Strategy> pos = c.deepEquivalent();
     Node* boundary = parentEditingBoundary(pos);
     if (!boundary)
         return VisiblePositionTemplate<Strategy>();
 
-    const PositionAlgorithm<Strategy> start = PositionAlgorithm<Strategy>::editingPositionOf(boundary, 0).parentAnchoredEquivalent();
-    const PositionAlgorithm<Strategy> end = pos.parentAnchoredEquivalent();
+    const PositionTemplate<Strategy> start = PositionTemplate<Strategy>::editingPositionOf(boundary, 0).parentAnchoredEquivalent();
+    const PositionTemplate<Strategy> end = pos.parentAnchoredEquivalent();
 
     Vector<UChar, 1024> string;
     unsigned suffixLength = 0;
 
     if (requiresContextForWordBoundary(characterBefore(c))) {
-        TextIteratorAlgorithm<Strategy> forwardsIterator(end, PositionAlgorithm<Strategy>::afterNode(boundary));
+        TextIteratorAlgorithm<Strategy> forwardsIterator(end, PositionTemplate<Strategy>::afterNode(boundary));
         while (!forwardsIterator.atEnd()) {
             Vector<UChar, 1024> characters;
             forwardsIterator.text().appendTextTo(characters);
@@ -715,7 +715,7 @@
     Node* node = it.startContainer();
     if (node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) {
         // The next variable contains a usable index into a text node
-        return createVisiblePosition(PositionAlgorithm<Strategy>(node, next));
+        return createVisiblePosition(PositionTemplate<Strategy>(node, next));
     }
 
     // Use the character iterator to translate the next value into a DOM
@@ -729,19 +729,19 @@
 template <typename Strategy>
 static VisiblePositionTemplate<Strategy> nextBoundary(const VisiblePositionTemplate<Strategy>& c, BoundarySearchFunction searchFunction)
 {
-    PositionAlgorithm<Strategy> pos = c.deepEquivalent();
+    PositionTemplate<Strategy> pos = c.deepEquivalent();
     Node* boundary = parentEditingBoundary(pos);
     if (!boundary)
         return VisiblePositionTemplate<Strategy>();
 
     Document& d = boundary->document();
-    const PositionAlgorithm<Strategy> start(pos.parentAnchoredEquivalent());
+    const PositionTemplate<Strategy> start(pos.parentAnchoredEquivalent());
 
     Vector<UChar, 1024> string;
     unsigned prefixLength = 0;
 
     if (requiresContextForWordBoundary(characterAfter(c))) {
-        SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(PositionAlgorithm<Strategy>::firstPositionInNode(&d), start);
+        SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(PositionTemplate<Strategy>::firstPositionInNode(&d), start);
         while (!backwardsIterator.atEnd()) {
             Vector<UChar, 1024> characters;
             backwardsIterator.prependTextTo(characters);
@@ -755,8 +755,8 @@
         }
     }
 
-    const PositionAlgorithm<Strategy> searchStart = PositionAlgorithm<Strategy>::editingPositionOf(start.anchorNode(), start.offsetInContainerNode());
-    const PositionAlgorithm<Strategy> searchEnd = PositionAlgorithm<Strategy>::lastPositionInNode(boundary);
+    const PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::editingPositionOf(start.anchorNode(), start.offsetInContainerNode());
+    const PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::lastPositionInNode(boundary);
     TextIteratorAlgorithm<Strategy> it(searchStart, searchEnd, TextIteratorEmitsCharactersBetweenAllVisiblePositions);
     const unsigned invalidOffset = static_cast<unsigned>(-1);
     unsigned next = invalidOffset;
@@ -941,7 +941,7 @@
     if (!rootBox) {
         // There are VisiblePositions at offset 0 in blocks without
         // RootInlineBoxes, like empty editable blocks and bordered blocks.
-        PositionAlgorithm<Strategy> p = c.position();
+        PositionTemplate<Strategy> p = c.position();
         if (p.anchorNode()->layoutObject() && p.anchorNode()->layoutObject()->isLayoutBlock() && !p.computeEditingOffset())
             return c;
 
@@ -970,7 +970,7 @@
         }
     }
 
-    return PositionWithAffinityTemplate<Strategy>(startNode->isTextNode() ? PositionAlgorithm<Strategy>(toText(startNode), toInlineTextBox(startBox)->start()) : PositionAlgorithm<Strategy>::beforeNode(startNode));
+    return PositionWithAffinityTemplate<Strategy>(startNode->isTextNode() ? PositionTemplate<Strategy>(toText(startNode), toInlineTextBox(startBox)->start()) : PositionTemplate<Strategy>::beforeNode(startNode));
 }
 
 template <typename Strategy>
@@ -1012,7 +1012,7 @@
 
     if (ContainerNode* editableRoot = highestEditableRoot(c.position())) {
         if (!editableRoot->contains(visPos.position().computeContainerNode()))
-            return PositionWithAffinityTemplate<Strategy>(PositionAlgorithm<Strategy>::firstPositionInNode(editableRoot));
+            return PositionWithAffinityTemplate<Strategy>(PositionTemplate<Strategy>::firstPositionInNode(editableRoot));
     }
 
     return honorEditingBoundaryAtOrBefore(visPos, c.position());
@@ -1038,7 +1038,7 @@
     if (!rootBox) {
         // There are VisiblePositions at offset 0 in blocks without
         // RootInlineBoxes, like empty editable blocks and bordered blocks.
-        const PositionAlgorithm<Strategy> p = c.deepEquivalent();
+        const PositionTemplate<Strategy> p = c.deepEquivalent();
         if (p.anchorNode()->layoutObject() && p.anchorNode()->layoutObject()->isLayoutBlock() && !p.computeEditingOffset())
             return c;
         return VisiblePositionTemplate<Strategy>();
@@ -1067,17 +1067,17 @@
         }
     }
 
-    PositionAlgorithm<Strategy> pos;
+    PositionTemplate<Strategy> pos;
     if (isHTMLBRElement(*endNode)) {
-        pos = PositionAlgorithm<Strategy>::beforeNode(endNode);
+        pos = PositionTemplate<Strategy>::beforeNode(endNode);
     } else if (endBox->isInlineTextBox() && endNode->isTextNode()) {
         InlineTextBox* endTextBox = toInlineTextBox(endBox);
         int endOffset = endTextBox->start();
         if (!endTextBox->isLineBreak())
             endOffset += endTextBox->len();
-        pos = PositionAlgorithm<Strategy>(toText(endNode), endOffset);
+        pos = PositionTemplate<Strategy>(toText(endNode), endOffset);
     } else {
-        pos = PositionAlgorithm<Strategy>::afterNode(endNode);
+        pos = PositionTemplate<Strategy>::afterNode(endNode);
     }
 
     return createVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE);
@@ -1146,7 +1146,7 @@
 
     if (ContainerNode* editableRoot = highestEditableRoot(currentPosition.deepEquivalent())) {
         if (!editableRoot->contains(visPos.deepEquivalent().computeContainerNode()))
-            return createVisiblePosition(PositionAlgorithm<Strategy>::lastPositionInNode(editableRoot));
+            return createVisiblePosition(PositionTemplate<Strategy>::lastPositionInNode(editableRoot));
     }
 
     return honorEditingBoundaryAtOrAfter(visPos, currentPosition.deepEquivalent());
@@ -1171,7 +1171,7 @@
     PositionWithAffinityTemplate<Strategy> startOfLine2 = startOfLine(position2);
     if (startOfLine1 == startOfLine2)
         return true;
-    PositionAlgorithm<Strategy> canonicalized1 = canonicalPositionOf(startOfLine1.position());
+    PositionTemplate<Strategy> canonicalized1 = canonicalPositionOf(startOfLine1.position());
     if (canonicalized1 == startOfLine2.position())
         return true;
     return canonicalized1 == canonicalPositionOf(startOfLine2.position());
@@ -1448,16 +1448,16 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy> startOfParagraphAlgorithm(const VisiblePositionTemplate<Strategy>& c, EditingBoundaryCrossingRule boundaryCrossingRule)
 {
-    const PositionAlgorithm<Strategy> p = c.deepEquivalent();
+    const PositionTemplate<Strategy> p = c.deepEquivalent();
     Node* startNode = p.anchorNode();
 
     if (!startNode)
         return VisiblePositionTemplate<Strategy>();
 
     if (isRenderedAsNonInlineTableImageOrHR(startNode))
-        return createVisiblePosition(PositionAlgorithm<Strategy>::beforeNode(startNode));
+        return createVisiblePosition(PositionTemplate<Strategy>::beforeNode(startNode));
 
-    Element* startBlock = enclosingBlock(PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
+    Element* startBlock = enclosingBlock(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
 
     Node* node = startNode;
     ContainerNode* highestRoot = highestEditableRoot(p);
@@ -1500,7 +1500,7 @@
                     i = max(0, o);
                 while (--i >= 0) {
                     if ((*text)[i] == '\n')
-                        return createVisiblePosition(PositionAlgorithm<Strategy>(toText(n), i + 1));
+                        return createVisiblePosition(PositionTemplate<Strategy>(toText(n), i + 1));
                 }
             }
             node = n;
@@ -1516,9 +1516,9 @@
     }
 
     if (type == PositionAnchorType::OffsetInAnchor)
-        return createVisiblePosition(PositionAlgorithm<Strategy>(node, offset));
+        return createVisiblePosition(PositionTemplate<Strategy>(node, offset));
 
-    return createVisiblePosition(PositionAlgorithm<Strategy>(node, type));
+    return createVisiblePosition(PositionTemplate<Strategy>(node, type));
 }
 
 VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
@@ -1537,13 +1537,13 @@
     if (c.isNull())
         return VisiblePositionTemplate<Strategy>();
 
-    const PositionAlgorithm<Strategy> p = c.deepEquivalent();
+    const PositionTemplate<Strategy> p = c.deepEquivalent();
     Node* startNode = p.anchorNode();
 
     if (isRenderedAsNonInlineTableImageOrHR(startNode))
-        return createVisiblePosition(PositionAlgorithm<Strategy>::afterNode(startNode));
+        return createVisiblePosition(PositionTemplate<Strategy>::afterNode(startNode));
 
-    Element* startBlock = enclosingBlock(PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
+    Element* startBlock = enclosingBlock(PositionTemplate<Strategy>::firstPositionInOrBeforeNode(startNode), CannotCrossEditingBoundary);
     Element* stayInsideBlock = startBlock;
 
     Node* node = startNode;
@@ -1587,7 +1587,7 @@
                 int o = n == startNode ? offset : 0;
                 for (int i = o; i < length; ++i) {
                     if ((*text)[i] == '\n')
-                        return createVisiblePosition(PositionAlgorithm<Strategy>(toText(n), i));
+                        return createVisiblePosition(PositionTemplate<Strategy>(toText(n), i));
                 }
             }
             node = n;
@@ -1603,9 +1603,9 @@
     }
 
     if (type == PositionAnchorType::OffsetInAnchor)
-        return createVisiblePosition(PositionAlgorithm<Strategy>(node, offset));
+        return createVisiblePosition(PositionTemplate<Strategy>(node, offset));
 
-    return createVisiblePosition(PositionAlgorithm<Strategy>(node, type));
+    return createVisiblePosition(PositionTemplate<Strategy>(node, type));
 }
 
 VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
@@ -1731,7 +1731,7 @@
     if (!node || !node->document().documentElement())
         return VisiblePositionTemplate<Strategy>();
 
-    return createVisiblePosition(PositionAlgorithm<Strategy>::firstPositionInNode(node->document().documentElement()));
+    return createVisiblePosition(PositionTemplate<Strategy>::firstPositionInNode(node->document().documentElement()));
 }
 
 VisiblePosition startOfDocument(const VisiblePosition& c)
@@ -1752,7 +1752,7 @@
         return VisiblePositionTemplate<Strategy>();
 
     Element* doc = node->document().documentElement();
-    return createVisiblePosition(PositionAlgorithm<Strategy>::lastPositionInNode(doc));
+    return createVisiblePosition(PositionTemplate<Strategy>::lastPositionInNode(doc));
 }
 
 VisiblePosition endOfDocument(const VisiblePosition& c)
@@ -1864,9 +1864,9 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
+PositionTemplate<Strategy> downstreamIgnoringEditingBoundaries(PositionTemplate<Strategy> position)
 {
-    PositionAlgorithm<Strategy> lastPosition;
+    PositionTemplate<Strategy> lastPosition;
     while (position != lastPosition) {
         lastPosition = position;
         position = mostForwardCaretPosition(position, CanCrossEditingBoundary);
@@ -1875,9 +1875,9 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
+PositionTemplate<Strategy> upstreamIgnoringEditingBoundaries(PositionTemplate<Strategy> position)
 {
-    PositionAlgorithm<Strategy> lastPosition;
+    PositionTemplate<Strategy> lastPosition;
     while (position != lastPosition) {
         lastPosition = position;
         position = mostBackwardCaretPosition(position, CanCrossEditingBoundary);
@@ -1886,7 +1886,7 @@
 }
 
 template <typename Strategy>
-static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
+static InlineBoxPosition computeInlineBoxPositionTemplate(const PositionTemplate<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
 {
     InlineBox* inlineBox = nullptr;
     int caretOffset = position.computeEditingOffset();
@@ -1901,7 +1901,7 @@
             // but surrounded by non-editable positions. It acts to negate the
             // logic at the beginning of
             // |LayoutObject::createPositionWithAffinity()|.
-            PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBoundaries(position);
+            PositionTemplate<Strategy> equivalent = downstreamIgnoringEditingBoundaries(position);
             if (equivalent == position) {
                 equivalent = upstreamIgnoringEditingBoundaries(position);
                 if (equivalent == position || downstreamIgnoringEditingBoundaries(equivalent) == position)
@@ -2053,19 +2053,19 @@
 }
 
 template <typename Strategy>
-static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity)
+static InlineBoxPosition computeInlineBoxPositionTemplate(const PositionTemplate<Strategy>& position, TextAffinity affinity)
 {
-    return computeInlineBoxPositionAlgorithm<Strategy>(position, affinity, primaryDirectionOf(*position.anchorNode()));
+    return computeInlineBoxPositionTemplate<Strategy>(position, affinity, primaryDirectionOf(*position.anchorNode()));
 }
 
 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity)
 {
-    return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity);
+    return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity);
 }
 
 InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity)
 {
-    return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity);
+    return computeInlineBoxPositionTemplate<EditingInComposedTreeStrategy>(position, affinity);
 }
 
 InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position)
@@ -2080,16 +2080,16 @@
 
 InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity, TextDirection primaryDirection)
 {
-    return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity, primaryDirection);
+    return computeInlineBoxPositionTemplate<EditingStrategy>(position, affinity, primaryDirection);
 }
 
 InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity, TextDirection primaryDirection)
 {
-    return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity, primaryDirection);
+    return computeInlineBoxPositionTemplate<EditingInComposedTreeStrategy>(position, affinity, primaryDirection);
 }
 
 template <typename Strategy>
-LayoutRect localCaretRectOfPositionAlgorithm(const PositionWithAffinityTemplate<Strategy>& position, LayoutObject*& layoutObject)
+LayoutRect localCaretRectOfPositionTemplate(const PositionWithAffinityTemplate<Strategy>& position, LayoutObject*& layoutObject)
 {
     if (position.position().isNull()) {
         layoutObject = nullptr;
@@ -2111,12 +2111,12 @@
 
 LayoutRect localCaretRectOfPosition(const PositionWithAffinity& position, LayoutObject*& layoutObject)
 {
-    return localCaretRectOfPositionAlgorithm<EditingStrategy>(position, layoutObject);
+    return localCaretRectOfPositionTemplate<EditingStrategy>(position, layoutObject);
 }
 
 LayoutRect localCaretRectOfPosition(const PositionInComposedTreeWithAffinity& position, LayoutObject*& layoutObject)
 {
-    return localCaretRectOfPositionAlgorithm<EditingInComposedTreeStrategy>(position, layoutObject);
+    return localCaretRectOfPositionTemplate<EditingInComposedTreeStrategy>(position, layoutObject);
 }
 
 static int boundingBoxLogicalHeight(LayoutObject *o, const IntRect &rect)
@@ -2150,7 +2150,7 @@
 }
 
 template <typename Strategy>
-static bool inRenderedText(const PositionAlgorithm<Strategy>& position)
+static bool inRenderedText(const PositionTemplate<Strategy>& position)
 {
     Node* const anchorNode = position.anchorNode();
     if (!anchorNode || !anchorNode->isTextNode())
@@ -2369,18 +2369,18 @@
 }
 
 template <typename Strategy>
-static PositionAlgorithm<Strategy> mostBackwardCaretPosition(const PositionAlgorithm<Strategy>& position, EditingBoundaryCrossingRule rule)
+static PositionTemplate<Strategy> mostBackwardCaretPosition(const PositionTemplate<Strategy>& position, EditingBoundaryCrossingRule rule)
 {
     TRACE_EVENT0("blink", "Position::upstream");
 
     Node* startNode = position.anchorNode();
     if (!startNode)
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     // iterate backward from there, looking for a qualified position
     Node* boundary = enclosingVisualBoundary<Strategy>(startNode);
     // FIXME: PositionIterator should respect Before and After positions.
-    PositionIteratorAlgorithm<Strategy> lastVisible(position.isAfterAnchor() ? PositionAlgorithm<Strategy>::editingPositionOf(position.anchorNode(), Strategy::caretMaxOffset(*position.anchorNode())) : position);
+    PositionIteratorAlgorithm<Strategy> lastVisible(position.isAfterAnchor() ? PositionTemplate<Strategy>::editingPositionOf(position.anchorNode(), Strategy::caretMaxOffset(*position.anchorNode())) : position);
     PositionIteratorAlgorithm<Strategy> currentPos = lastVisible;
     bool startEditable = startNode->hasEditableStyle();
     Node* lastNode = startNode;
@@ -2427,7 +2427,7 @@
         // Return position after tables and nodes which have content that can be ignored.
         if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
             if (currentPos.atEndOfNode())
-                return PositionAlgorithm<Strategy>::afterNode(currentNode);
+                return PositionTemplate<Strategy>::afterNode(currentNode);
             continue;
         }
 
@@ -2439,7 +2439,7 @@
                 // layout tree which can have a different length due to case transformation.
                 // Until we resolve that, disable this so we can run the layout tests!
                 // ASSERT(currentOffset >= layoutObject->caretMaxOffset());
-                return PositionAlgorithm<Strategy>(currentNode, layoutObject->caretMaxOffset());
+                return PositionTemplate<Strategy>(currentNode, layoutObject->caretMaxOffset());
             }
 
             unsigned textOffset = currentPos.offsetInLeafNode();
@@ -2496,18 +2496,18 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> mostForwardCaretPosition(const PositionAlgorithm<Strategy>& position, EditingBoundaryCrossingRule rule)
+PositionTemplate<Strategy> mostForwardCaretPosition(const PositionTemplate<Strategy>& position, EditingBoundaryCrossingRule rule)
 {
     TRACE_EVENT0("blink", "Position::downstream");
 
     Node* startNode = position.anchorNode();
     if (!startNode)
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
     // iterate forward from there, looking for a qualified position
     Node* boundary = enclosingVisualBoundary<Strategy>(startNode);
     // FIXME: PositionIterator should respect Before and After positions.
-    PositionIteratorAlgorithm<Strategy> lastVisible(position.isAfterAnchor() ? PositionAlgorithm<Strategy>::editingPositionOf(position.anchorNode(), Strategy::caretMaxOffset(*position.anchorNode())) : position);
+    PositionIteratorAlgorithm<Strategy> lastVisible(position.isAfterAnchor() ? PositionTemplate<Strategy>::editingPositionOf(position.anchorNode(), Strategy::caretMaxOffset(*position.anchorNode())) : position);
     PositionIteratorAlgorithm<Strategy> currentPos = lastVisible;
     bool startEditable = startNode->hasEditableStyle();
     Node* lastNode = startNode;
@@ -2559,7 +2559,7 @@
         // Return position before tables and nodes which have content that can be ignored.
         if (Strategy::editingIgnoresContent(currentNode) || isRenderedHTMLTableElement(currentNode)) {
             if (currentPos.offsetInLeafNode() <= layoutObject->caretMinOffset())
-                return PositionAlgorithm<Strategy>::editingPositionOf(currentNode, layoutObject->caretMinOffset());
+                return PositionTemplate<Strategy>::editingPositionOf(currentNode, layoutObject->caretMinOffset());
             continue;
         }
 
@@ -2567,7 +2567,7 @@
         if (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox()) {
             if (currentNode != startNode) {
                 ASSERT(currentPos.atStartOfNode());
-                return PositionAlgorithm<Strategy>(currentNode, layoutObject->caretMinOffset());
+                return PositionTemplate<Strategy>(currentNode, layoutObject->caretMinOffset());
             }
 
             unsigned textOffset = currentPos.offsetInLeafNode();
@@ -2634,13 +2634,13 @@
 // 3. It is an editable position and both the next and previous visually
 //    equivalent positions are both non editable.
 template <typename Strategy>
-static bool atEditingBoundary(const PositionAlgorithm<Strategy> positions)
+static bool atEditingBoundary(const PositionTemplate<Strategy> positions)
 {
-    PositionAlgorithm<Strategy> nextPosition = mostForwardCaretPosition(positions, CanCrossEditingBoundary);
+    PositionTemplate<Strategy> nextPosition = mostForwardCaretPosition(positions, CanCrossEditingBoundary);
     if (positions.atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosition.anchorNode()->hasEditableStyle())
         return true;
 
-    PositionAlgorithm<Strategy> prevPosition = mostBackwardCaretPosition(positions, CanCrossEditingBoundary);
+    PositionTemplate<Strategy> prevPosition = mostBackwardCaretPosition(positions, CanCrossEditingBoundary);
     if (positions.atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosition.anchorNode()->hasEditableStyle())
         return true;
 
@@ -2649,7 +2649,7 @@
 }
 
 template <typename Strategy>
-static bool isVisuallyEquivalentCandidateAlgorithm(const PositionAlgorithm<Strategy>& position)
+static bool isVisuallyEquivalentCandidateAlgorithm(const PositionTemplate<Strategy>& position)
 {
     Node* const anchorNode = position.anchorNode();
     if (!anchorNode)
@@ -2734,7 +2734,7 @@
 }
 
 template <typename Strategy>
-static VisiblePositionTemplate<Strategy> skipToEndOfEditingBoundary(const VisiblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
+static VisiblePositionTemplate<Strategy> skipToEndOfEditingBoundary(const VisiblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
 {
     if (pos.isNull())
         return pos;
@@ -2749,7 +2749,7 @@
 
     // If this is not editable but |pos| has an editable root, skip to the end
     if (!highestRoot && highestRootOfPos)
-        return createVisiblePosition(PositionAlgorithm<Strategy>(highestRootOfPos, PositionAnchorType::AfterAnchor).parentAnchoredEquivalent());
+        return createVisiblePosition(PositionTemplate<Strategy>(highestRootOfPos, PositionAnchorType::AfterAnchor).parentAnchoredEquivalent());
 
     // That must mean that |pos| is not editable. Return the next position after
     // |pos| that is in the same editable region as this position
@@ -2762,7 +2762,7 @@
     // We canonicalize to the first of two equivalent candidates, but the second
     // of the two candidates is the one that will be inside the text node
     // containing the character after this visible position.
-    const PositionAlgorithm<Strategy> pos = mostForwardCaretPosition(visiblePosition.deepEquivalent());
+    const PositionTemplate<Strategy> pos = mostForwardCaretPosition(visiblePosition.deepEquivalent());
     if (!pos.isOffsetInAnchor())
         return 0;
     Node* containerNode = pos.computeContainerNode();
@@ -2804,15 +2804,15 @@
 }
 
 template <typename Strategy>
-static PositionAlgorithm<Strategy> leftVisuallyDistinctCandidate(const VisiblePositionTemplate<Strategy>& visiblePosition)
+static PositionTemplate<Strategy> leftVisuallyDistinctCandidate(const VisiblePositionTemplate<Strategy>& visiblePosition)
 {
-    const PositionAlgorithm<Strategy> deepPosition = visiblePosition.deepEquivalent();
-    PositionAlgorithm<Strategy> p = deepPosition;
+    const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivalent();
+    PositionTemplate<Strategy> p = deepPosition;
 
     if (p.isNull())
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
-    const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(p);
+    const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition(p);
     TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
     const TextAffinity affinity = visiblePosition.affinity();
 
@@ -2850,13 +2850,13 @@
                 // Overshot to the left.
                 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
                 if (!prevBox) {
-                    PositionAlgorithm<Strategy> positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent()) : nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
+                    PositionTemplate<Strategy> positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent()) : nextVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
                     if (positionOnLeft.isNull())
-                        return PositionAlgorithm<Strategy>();
+                        return PositionTemplate<Strategy>();
 
                     InlineBox* boxOnLeft = computeInlineBoxPosition(positionOnLeft, affinity, primaryDirection).inlineBox;
                     if (boxOnLeft && boxOnLeft->root() == box->root())
-                        return PositionAlgorithm<Strategy>();
+                        return PositionTemplate<Strategy>();
                     return positionOnLeft;
                 }
 
@@ -2946,7 +2946,7 @@
             break;
         }
 
-        p = PositionAlgorithm<Strategy>::editingPositionOf(layoutObject->node(), offset);
+        p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), offset);
 
         if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
             return p;
@@ -2958,7 +2958,7 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy> leftPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
 {
-    const PositionAlgorithm<Strategy> pos = leftVisuallyDistinctCandidate(visiblePosition);
+    const PositionTemplate<Strategy> pos = leftVisuallyDistinctCandidate(visiblePosition);
     // TODO(yosin) Why can't we move left from the last position in a tree?
     if (pos.atStartOfTree() || pos.atEndOfTree())
         return VisiblePositionTemplate<Strategy>();
@@ -2980,14 +2980,14 @@
 }
 
 template <typename Strategy>
-static PositionAlgorithm<Strategy> rightVisuallyDistinctCandidate(const VisiblePositionTemplate<Strategy>& visiblePosition)
+static PositionTemplate<Strategy> rightVisuallyDistinctCandidate(const VisiblePositionTemplate<Strategy>& visiblePosition)
 {
-    const PositionAlgorithm<Strategy> deepPosition = visiblePosition.deepEquivalent();
-    PositionAlgorithm<Strategy> p = deepPosition;
+    const PositionTemplate<Strategy> deepPosition = visiblePosition.deepEquivalent();
+    PositionTemplate<Strategy> p = deepPosition;
     if (p.isNull())
-        return PositionAlgorithm<Strategy>();
+        return PositionTemplate<Strategy>();
 
-    const PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(p);
+    const PositionTemplate<Strategy> downstreamStart = mostForwardCaretPosition(p);
     TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode());
     const TextAffinity affinity = visiblePosition.affinity();
 
@@ -3025,13 +3025,13 @@
                 // Overshot to the right.
                 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
                 if (!nextBox) {
-                    PositionAlgorithm<Strategy> positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
+                    PositionTemplate<Strategy> positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(deepPosition) : previousVisuallyDistinctCandidate(deepPosition);
                     if (positionOnRight.isNull())
-                        return PositionAlgorithm<Strategy>();
+                        return PositionTemplate<Strategy>();
 
                     InlineBox* boxOnRight = computeInlineBoxPosition(positionOnRight, affinity, primaryDirection).inlineBox;
                     if (boxOnRight && boxOnRight->root() == box->root())
-                        return PositionAlgorithm<Strategy>();
+                        return PositionTemplate<Strategy>();
                     return positionOnRight;
                 }
 
@@ -3124,7 +3124,7 @@
             break;
         }
 
-        p = PositionAlgorithm<Strategy>::editingPositionOf(layoutObject->node(), offset);
+        p = PositionTemplate<Strategy>::editingPositionOf(layoutObject->node(), offset);
 
         if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
             return p;
@@ -3136,7 +3136,7 @@
 template <typename Strategy>
 static VisiblePositionTemplate<Strategy> rightPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition)
 {
-    const PositionAlgorithm<Strategy> pos = rightVisuallyDistinctCandidate(visiblePosition);
+    const PositionTemplate<Strategy> pos = rightVisuallyDistinctCandidate(visiblePosition);
     // FIXME: Why can't we move left from the last position in a tree?
     if (pos.atStartOfTree() || pos.atEndOfTree())
         return VisiblePositionTemplate<Strategy>();
@@ -3185,7 +3185,7 @@
 }
 
 template <typename Strategy>
-static VisiblePositionTemplate<Strategy> skipToStartOfEditingBoundary(const VisiblePositionTemplate<Strategy>& pos, const PositionAlgorithm<Strategy>& anchor)
+static VisiblePositionTemplate<Strategy> skipToStartOfEditingBoundary(const VisiblePositionTemplate<Strategy>& pos, const PositionTemplate<Strategy>& anchor)
 {
     if (pos.isNull())
         return pos;
@@ -3200,7 +3200,7 @@
 
     // If this is not editable but |pos| has an editable root, skip to the start
     if (!highestRoot && highestRootOfPos)
-        return createVisiblePosition(previousVisuallyDistinctCandidate(PositionAlgorithm<Strategy>(highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent()));
+        return createVisiblePosition(previousVisuallyDistinctCandidate(PositionTemplate<Strategy>(highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent()));
 
     // That must mean that |pos| is not editable. Return the last position
     // before |pos| that is in the same editable region as this position
@@ -3210,7 +3210,7 @@
 template <typename Strategy>
 static VisiblePositionTemplate<Strategy> previousPositionOfAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule rule)
 {
-    const PositionAlgorithm<Strategy> pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
+    const PositionTemplate<Strategy> pos = previousVisuallyDistinctCandidate(visiblePosition.deepEquivalent());
 
     // return null visible position if there is no previous visible position
     if (pos.atStartOfTree())
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
index 9247e7c4..d0b9019 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
@@ -967,7 +967,7 @@
     Node* space = shadowRoot->getElementById("space")->firstChild();
 
     EXPECT_EQ(Position(one, 0), startOfWord(createVisiblePositionInDOMTree(*one, 0)).deepEquivalent());
-    EXPECT_EQ(PositionInComposedTree(four, 0), startOfWord(createVisiblePositionInComposedTree(*one, 0)).deepEquivalent());
+    EXPECT_EQ(PositionInComposedTree(space, 1), startOfWord(createVisiblePositionInComposedTree(*one, 0)).deepEquivalent());
 
     EXPECT_EQ(Position(one, 0), startOfWord(createVisiblePositionInDOMTree(*one, 1)).deepEquivalent());
     EXPECT_EQ(PositionInComposedTree(space, 1), startOfWord(createVisiblePositionInComposedTree(*one, 1)).deepEquivalent());
@@ -979,7 +979,7 @@
     EXPECT_EQ(PositionInComposedTree(four, 0), startOfWord(createVisiblePositionInComposedTree(*two, 1)).deepEquivalent());
 
     EXPECT_EQ(Position(one, 0), startOfWord(createVisiblePositionInDOMTree(*three, 1)).deepEquivalent());
-    EXPECT_EQ(PositionInComposedTree(four, 0), startOfWord(createVisiblePositionInComposedTree(*three, 1)).deepEquivalent());
+    EXPECT_EQ(PositionInComposedTree(space, 1), startOfWord(createVisiblePositionInComposedTree(*three, 1)).deepEquivalent());
 
     EXPECT_EQ(Position(four, 0), startOfWord(createVisiblePositionInDOMTree(*four, 1)).deepEquivalent());
     EXPECT_EQ(PositionInComposedTree(four, 0), startOfWord(createVisiblePositionInComposedTree(*four, 1)).deepEquivalent());
diff --git a/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.cpp
index 0a2e98de..bf7b5ae 100644
--- a/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.cpp
@@ -30,7 +30,7 @@
 namespace blink {
 
 template <typename Strategy>
-BackwardsCharacterIteratorAlgorithm<Strategy>::BackwardsCharacterIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags behavior)
+BackwardsCharacterIteratorAlgorithm<Strategy>::BackwardsCharacterIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags behavior)
     : m_offset(0)
     , m_runOffset(0)
     , m_atBreak(true)
@@ -41,12 +41,12 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> BackwardsCharacterIteratorAlgorithm<Strategy>::endPosition() const
+PositionTemplate<Strategy> BackwardsCharacterIteratorAlgorithm<Strategy>::endPosition() const
 {
     if (!m_textIterator.atEnd()) {
         if (m_textIterator.length() > 1) {
             Node* n = m_textIterator.startContainer();
-            return PositionAlgorithm<Strategy>::editingPositionOf(n, m_textIterator.endOffset() - m_runOffset);
+            return PositionTemplate<Strategy>::editingPositionOf(n, m_textIterator.endOffset() - m_runOffset);
         }
         ASSERT(!m_runOffset);
     }
diff --git a/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.h b/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.h
index 48f8a2a..69b495a 100644
--- a/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/BackwardsCharacterIterator.h
@@ -35,13 +35,13 @@
 class BackwardsCharacterIteratorAlgorithm {
     STACK_ALLOCATED();
 public:
-    BackwardsCharacterIteratorAlgorithm(const PositionAlgorithm<Strategy>&, const PositionAlgorithm<Strategy>&, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
+    BackwardsCharacterIteratorAlgorithm(const PositionTemplate<Strategy>&, const PositionTemplate<Strategy>&, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
 
     void advance(int);
 
     bool atEnd() const { return m_textIterator.atEnd(); }
 
-    PositionAlgorithm<Strategy> endPosition() const;
+    PositionTemplate<Strategy> endPosition() const;
 
 private:
     int m_offset;
diff --git a/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.cpp
index ec877a1e..255ac9a6 100644
--- a/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.cpp
@@ -30,7 +30,7 @@
 namespace blink {
 
 template <typename Strategy>
-CharacterIteratorAlgorithm<Strategy>::CharacterIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags behavior)
+CharacterIteratorAlgorithm<Strategy>::CharacterIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags behavior)
     : m_offset(0)
     , m_runOffset(0)
     , m_atBreak(true)
@@ -58,12 +58,12 @@
     EphemeralRangeTemplate<Strategy> range(m_textIterator.range());
     if (m_textIterator.atEnd() || m_textIterator.length() <= 1)
         return range;
-    PositionAlgorithm<Strategy> startPosition = range.startPosition().parentAnchoredEquivalent();
-    PositionAlgorithm<Strategy> endPosition = range.endPosition().parentAnchoredEquivalent();
+    PositionTemplate<Strategy> startPosition = range.startPosition().parentAnchoredEquivalent();
+    PositionTemplate<Strategy> endPosition = range.endPosition().parentAnchoredEquivalent();
     Node* node = startPosition.computeContainerNode();
     ASSERT_UNUSED(endPosition, node == endPosition.computeContainerNode());
     int offset = startPosition.offsetInContainerNode() + m_runOffset;
-    return EphemeralRangeTemplate<Strategy>(PositionAlgorithm<Strategy>(node, offset), PositionAlgorithm<Strategy>(node, offset + 1));
+    return EphemeralRangeTemplate<Strategy>(PositionTemplate<Strategy>(node, offset), PositionTemplate<Strategy>(node, offset + 1));
 }
 
 template <typename Strategy>
@@ -101,13 +101,13 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> CharacterIteratorAlgorithm<Strategy>::startPosition() const
+PositionTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::startPosition() const
 {
     if (!m_textIterator.atEnd()) {
         if (m_textIterator.length() > 1) {
             Node* n = m_textIterator.currentContainer();
             int offset = m_textIterator.startOffsetInCurrentContainer() + m_runOffset;
-            return PositionAlgorithm<Strategy>::editingPositionOf(n, offset);
+            return PositionTemplate<Strategy>::editingPositionOf(n, offset);
         }
         ASSERT(!m_runOffset);
     }
@@ -115,13 +115,13 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> CharacterIteratorAlgorithm<Strategy>::endPosition() const
+PositionTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::endPosition() const
 {
     if (!m_textIterator.atEnd()) {
         if (m_textIterator.length() > 1) {
             Node* n = m_textIterator.currentContainer();
             int offset = m_textIterator.startOffsetInCurrentContainer() + m_runOffset;
-            return PositionAlgorithm<Strategy>::editingPositionOf(n, offset + 1);
+            return PositionTemplate<Strategy>::editingPositionOf(n, offset + 1);
         }
         ASSERT(!m_runOffset);
     }
@@ -178,7 +178,7 @@
 EphemeralRangeTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::calculateCharacterSubrange(int offset, int length)
 {
     advance(offset);
-    const PositionAlgorithm<Strategy> startPos = startPosition();
+    const PositionTemplate<Strategy> startPos = startPosition();
 
     if (length > 1)
         advance(length - 1);
diff --git a/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.h b/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.h
index 5b25b7a..0f95ff4b 100644
--- a/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/CharacterIterator.h
@@ -41,7 +41,7 @@
 class CORE_EXPORT CharacterIteratorAlgorithm {
     STACK_ALLOCATED();
 public:
-    CharacterIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
+    CharacterIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
     explicit CharacterIteratorAlgorithm(const EphemeralRangeTemplate<Strategy>&, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
 
     void advance(int numCharacters);
@@ -62,8 +62,8 @@
     Node* currentContainer() const;
     int startOffset() const;
     int endOffset() const;
-    PositionAlgorithm<Strategy> startPosition() const;
-    PositionAlgorithm<Strategy> endPosition() const;
+    PositionTemplate<Strategy> startPosition() const;
+    PositionTemplate<Strategy> endPosition() const;
 
     EphemeralRangeTemplate<Strategy> calculateCharacterSubrange(int offset, int length);
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.cpp b/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.cpp
index 9ddbade..cd9c286 100644
--- a/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.cpp
@@ -88,7 +88,7 @@
     ASSERT(size() == 1 + depthCrossingShadowBoundaries<Strategy>(*node));
 }
 
-template class FullyClippedStateStackAlgorithm<EditingStrategy>;
-template class FullyClippedStateStackAlgorithm<EditingInComposedTreeStrategy>;
+template class CORE_TEMPLATE_EXPORT FullyClippedStateStackAlgorithm<EditingStrategy>;
+template class CORE_TEMPLATE_EXPORT FullyClippedStateStackAlgorithm<EditingInComposedTreeStrategy>;
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.h b/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.h
index 74d5b607..e157c9c 100644
--- a/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.h
+++ b/third_party/WebKit/Source/core/editing/iterators/FullyClippedStateStack.h
@@ -12,7 +12,7 @@
 namespace blink {
 
 template<typename Strategy>
-class FullyClippedStateStackAlgorithm final : public BitStack {
+class CORE_TEMPLATE_CLASS_EXPORT FullyClippedStateStackAlgorithm final : public BitStack {
     STACK_ALLOCATED();
 public:
     FullyClippedStateStackAlgorithm();
@@ -22,8 +22,8 @@
     void setUpFullyClippedStack(Node*);
 };
 
-extern template class FullyClippedStateStackAlgorithm<EditingStrategy>;
-extern template class FullyClippedStateStackAlgorithm<EditingInComposedTreeStrategy>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT FullyClippedStateStackAlgorithm<EditingStrategy>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT FullyClippedStateStackAlgorithm<EditingInComposedTreeStrategy>;
 
 using FullyClippedStateStack = FullyClippedStateStackAlgorithm<EditingStrategy>;
 
diff --git a/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp b/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
index d3a7f7a..a17d949 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/SearchBuffer.cpp
@@ -380,7 +380,7 @@
     SearchBuffer buffer(target, options);
 
     if (buffer.needsMoreContext()) {
-        for (SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(PositionAlgorithm<Strategy>::firstPositionInNode(it.ownerDocument()), PositionAlgorithm<Strategy>(it.currentContainer(), it.startOffset())); !backwardsIterator.atEnd(); backwardsIterator.advance()) {
+        for (SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwardsIterator(PositionTemplate<Strategy>::firstPositionInNode(it.ownerDocument()), PositionTemplate<Strategy>(it.currentContainer(), it.startOffset())); !backwardsIterator.atEnd(); backwardsIterator.advance()) {
             Vector<UChar, 1024> characters;
             backwardsIterator.prependTextTo(characters);
             buffer.prependContext(characters.data(), characters.size());
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
index 8760723..d10bede 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.cpp
@@ -59,7 +59,7 @@
 }
 
 template <typename Strategy>
-SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::SimplifiedBackwardsTextIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags behavior)
+SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::SimplifiedBackwardsTextIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags behavior)
     : m_node(nullptr)
     , m_offset(0)
     , m_handledNode(false)
@@ -96,17 +96,19 @@
 void SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::init(Node* startNode, Node* endNode, int startOffset, int endOffset)
 {
     if (!startNode->offsetInCharacters() && startOffset >= 0) {
-        // NodeTraversal::childAt() will return 0 if the offset is out of range. We rely on this behavior
-        // instead of calling countChildren() to avoid traversing the children twice.
-        if (Node* childAtOffset = NodeTraversal::childAt(*startNode, startOffset)) {
+        // |Strategy::childAt()| will return 0 if the offset is out of range. We
+        // rely on this behavior instead of calling |countChildren()| to avoid
+        // traversing the children twice.
+        if (Node* childAtOffset = Strategy::childAt(*startNode, startOffset)) {
             startNode = childAtOffset;
             startOffset = 0;
         }
     }
     if (!endNode->offsetInCharacters() && endOffset > 0) {
-        // NodeTraversal::childAt() will return 0 if the offset is out of range. We rely on this behavior
-        // instead of calling countChildren() to avoid traversing the children twice.
-        if (Node* childAtOffset = NodeTraversal::childAt(*endNode, endOffset - 1)) {
+        // |Strategy::childAt()| will return 0 if the offset is out of range. We
+        // rely on this behavior instead of calling |countChildren()| to avoid
+        // traversing the children twice.
+        if (Node* childAtOffset = Strategy::childAt(*endNode, endOffset - 1)) {
             endNode = childAtOffset;
             endOffset = lastOffsetInNode(endNode);
         }
@@ -167,16 +169,16 @@
                 return;
         }
 
-        if (!m_handledChildren && m_node->hasChildren()) {
-            m_node = m_node->lastChild();
+        if (!m_handledChildren && Strategy::hasChildren(*m_node)) {
+            m_node = Strategy::lastChild(*m_node);
             m_fullyClippedStack.pushFullyClippedState(m_node);
         } else {
             // Exit empty containers as we pass over them or containers
             // where [container, 0] is where we started iterating.
             if (!m_handledNode
                 && canHaveChildrenForEditing(m_node)
-                && m_node->parentNode()
-                && (!m_node->lastChild() || (m_node == m_endNode && !m_endOffset))) {
+                && Strategy::parent(*m_node)
+                && (!Strategy::lastChild(*m_node) || (m_node == m_endNode && !m_endOffset))) {
                 exitNode();
                 if (m_positionNode) {
                     m_handledNode = true;
@@ -186,8 +188,8 @@
             }
 
             // Exit all other containers.
-            while (!m_node->previousSibling()) {
-                if (!advanceRespectingRange(m_node->parentOrShadowHostNode()))
+            while (!Strategy::previousSibling(*m_node)) {
+                if (!advanceRespectingRange(parentCrossingShadowBoundaries<Strategy>(*m_node)))
                     break;
                 m_fullyClippedStack.pop();
                 exitNode();
@@ -199,7 +201,7 @@
             }
 
             m_fullyClippedStack.pop();
-            if (advanceRespectingRange(m_node->previousSibling()))
+            if (advanceRespectingRange(Strategy::previousSibling(*m_node)))
                 m_fullyClippedStack.pushFullyClippedState(m_node);
             else
                 m_node = nullptr;
@@ -292,12 +294,12 @@
 template <typename Strategy>
 bool SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::handleReplacedElement()
 {
-    unsigned index = m_node->nodeIndex();
+    unsigned index = Strategy::index(*m_node);
     // We want replaced elements to behave like punctuation for boundary
     // finding, and to simply take up space for the selection preservation
     // code in moveParagraphs, so we use a comma. Unconditionally emit
     // here because this iterator is only used for boundary finding.
-    emitCharacter(',', m_node->parentNode(), index, index + 1);
+    emitCharacter(',', Strategy::parent(*m_node), index, index + 1);
     return true;
 }
 
@@ -307,10 +309,10 @@
     // We can use a linefeed in place of a tab because this simple iterator is only used to
     // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs.
     if (TextIterator::shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || TextIterator::shouldEmitNewlineAfterNode(*m_node) || TextIterator::shouldEmitTabBeforeNode(m_node)) {
-        unsigned index = m_node->nodeIndex();
+        unsigned index = Strategy::index(*m_node);
         // The start of this emitted range is wrong. Ensuring correctness would require
         // VisiblePositions and so would be slow. previousBoundary expects this.
-        emitCharacter('\n', m_node->parentNode(), index + 1, index + 1);
+        emitCharacter('\n', Strategy::parent(*m_node), index + 1, index + 1);
     }
     return true;
 }
@@ -365,19 +367,19 @@
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy> SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::startPosition() const
+PositionTemplate<Strategy> SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::startPosition() const
 {
     if (m_positionNode)
-        return PositionAlgorithm<Strategy>::editingPositionOf(m_positionNode, m_positionStartOffset);
-    return PositionAlgorithm<Strategy>::editingPositionOf(m_startNode, m_startOffset);
+        return PositionTemplate<Strategy>::editingPositionOf(m_positionNode, m_positionStartOffset);
+    return PositionTemplate<Strategy>::editingPositionOf(m_startNode, m_startOffset);
 }
 
 template <typename Strategy>
-PositionAlgorithm<Strategy>SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::endPosition() const
+PositionTemplate<Strategy>SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::endPosition() const
 {
     if (m_positionNode)
-        return PositionAlgorithm<Strategy>::editingPositionOf(m_positionNode, m_positionEndOffset);
-    return PositionAlgorithm<Strategy>::editingPositionOf(m_startNode, m_startOffset);
+        return PositionTemplate<Strategy>::editingPositionOf(m_positionNode, m_positionEndOffset);
+    return PositionTemplate<Strategy>::editingPositionOf(m_startNode, m_startOffset);
 }
 
 template class CORE_TEMPLATE_EXPORT SimplifiedBackwardsTextIteratorAlgorithm<EditingStrategy>;
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
index 8d810dc..9c38c03 100644
--- a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIterator.h
@@ -40,10 +40,10 @@
 // at points where replaced elements break up the text flow. The text comes back in
 // chunks so as to optimize for performance of the iteration.
 template <typename Strategy>
-class SimplifiedBackwardsTextIteratorAlgorithm {
+class CORE_TEMPLATE_CLASS_EXPORT SimplifiedBackwardsTextIteratorAlgorithm {
     STACK_ALLOCATED();
 public:
-    SimplifiedBackwardsTextIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
+    SimplifiedBackwardsTextIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
 
     bool atEnd() const { return !m_positionNode || m_shouldStop; }
     void advance();
@@ -65,8 +65,8 @@
 
     Node* startContainer() const;
     int endOffset() const;
-    PositionAlgorithm<Strategy> startPosition() const;
-    PositionAlgorithm<Strategy> endPosition() const;
+    PositionTemplate<Strategy> startPosition() const;
+    PositionTemplate<Strategy> endPosition() const;
 
 private:
     void init(Node* startNode, Node* endNode, int startOffset, int endOffset);
@@ -84,7 +84,7 @@
     int m_offset;
     bool m_handledNode;
     bool m_handledChildren;
-    FullyClippedStateStack m_fullyClippedStack;
+    FullyClippedStateStackAlgorithm<Strategy> m_fullyClippedStack;
 
     // End of the range.
     RawPtrWillBeMember<Node> m_startNode;
diff --git a/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIteratorTest.cpp b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIteratorTest.cpp
new file mode 100644
index 0000000..2934dfc
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/iterators/SimplifiedBackwardsTextIteratorTest.cpp
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/editing/iterators/SimplifiedBackwardsTextIterator.h"
+
+#include "core/editing/EditingTestBase.h"
+#include "core/editing/EphemeralRange.h"
+#include "wtf/Vector.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+class SimplifiedBackwardsTextIteratorTest : public EditingTestBase {
+};
+
+template <typename Strategy>
+static String extractString(const Element& element)
+{
+    const EphemeralRangeTemplate<Strategy> range = EphemeralRangeTemplate<Strategy>::rangeOfContents(element);
+    Vector<UChar> buffer;
+    for (SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) {
+        it.prependTextTo(buffer);
+    }
+    return String(buffer);
+}
+
+TEST_F(SimplifiedBackwardsTextIteratorTest, SubrangeWithReplacedElements)
+{
+    static const char* bodyContent = "<a id=host><b id=one>one</b> not appeared <b id=two>two</b></a>";
+    const char* shadowContent = "three <content select=#two></content> <content select=#one></content> zero";
+    setBodyContent(bodyContent);
+    setShadowContent(shadowContent, "host");
+    updateLayoutAndStyleForPainting();
+
+    Element* host = document().getElementById("host");
+
+    // We should not apply DOM tree version to containing shadow tree in
+    // general. To record current behavior, we have this test. even if it
+    // isn't intuitive.
+    EXPECT_EQ("onetwo", extractString<EditingStrategy>(*host));
+    EXPECT_EQ("three two one zero", extractString<EditingInComposedTreeStrategy>(*host));
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
index c0bd614b..e578686 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
@@ -123,7 +123,7 @@
 } // namespace
 
 template<typename Strategy>
-TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags behavior)
+TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags behavior)
     : m_offset(0)
     , m_startContainer(nullptr)
     , m_startOffset(0)
@@ -995,12 +995,12 @@
     // use the current run information, if we have it
     if (m_textState.positionNode()) {
         m_textState.flushPositionOffsets();
-        return EphemeralRangeTemplate<Strategy>(PositionAlgorithm<Strategy>(m_textState.positionNode(), m_textState.positionStartOffset()), PositionAlgorithm<Strategy>(m_textState.positionNode(), m_textState.positionEndOffset()));
+        return EphemeralRangeTemplate<Strategy>(PositionTemplate<Strategy>(m_textState.positionNode(), m_textState.positionStartOffset()), PositionTemplate<Strategy>(m_textState.positionNode(), m_textState.positionEndOffset()));
     }
 
     // otherwise, return the end of the overall range we were given
     if (m_endContainer)
-        return EphemeralRangeTemplate<Strategy>(PositionAlgorithm<Strategy>(m_endContainer, m_endOffset));
+        return EphemeralRangeTemplate<Strategy>(PositionTemplate<Strategy>(m_endContainer, m_endOffset));
 
     return EphemeralRangeTemplate<Strategy>();
 }
@@ -1060,19 +1060,19 @@
 }
 
 template<typename Strategy>
-PositionAlgorithm<Strategy> TextIteratorAlgorithm<Strategy>::startPositionInCurrentContainer() const
+PositionTemplate<Strategy> TextIteratorAlgorithm<Strategy>::startPositionInCurrentContainer() const
 {
-    return PositionAlgorithm<Strategy>::editingPositionOf(currentContainer(), startOffsetInCurrentContainer());
+    return PositionTemplate<Strategy>::editingPositionOf(currentContainer(), startOffsetInCurrentContainer());
 }
 
 template<typename Strategy>
-PositionAlgorithm<Strategy> TextIteratorAlgorithm<Strategy>::endPositionInCurrentContainer() const
+PositionTemplate<Strategy> TextIteratorAlgorithm<Strategy>::endPositionInCurrentContainer() const
 {
-    return PositionAlgorithm<Strategy>::editingPositionOf(currentContainer(), endOffsetInCurrentContainer());
+    return PositionTemplate<Strategy>::editingPositionOf(currentContainer(), endOffsetInCurrentContainer());
 }
 
 template<typename Strategy>
-int TextIteratorAlgorithm<Strategy>::rangeLength(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, bool forSelectionPreservation)
+int TextIteratorAlgorithm<Strategy>::rangeLength(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, bool forSelectionPreservation)
 {
     int length = 0;
     TextIteratorBehaviorFlags behaviorFlags = TextIteratorEmitsObjectReplacementCharacter;
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
index f300c1c..532f7c4 100644
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.h
@@ -55,7 +55,7 @@
     STACK_ALLOCATED();
 public:
     // [start, end] indicates the document range that the iteration should take place within (both ends inclusive).
-    TextIteratorAlgorithm(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
+    TextIteratorAlgorithm(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, TextIteratorBehaviorFlags = TextIteratorDefaultBehavior);
     ~TextIteratorAlgorithm();
 
     bool atEnd() const { return !m_textState.positionNode() || m_shouldStop; }
@@ -69,8 +69,8 @@
     Node* currentContainer() const;
     int startOffsetInCurrentContainer() const;
     int endOffsetInCurrentContainer() const;
-    PositionAlgorithm<Strategy> startPositionInCurrentContainer() const;
-    PositionAlgorithm<Strategy> endPositionInCurrentContainer() const;
+    PositionTemplate<Strategy> startPositionInCurrentContainer() const;
+    PositionTemplate<Strategy> endPositionInCurrentContainer() const;
 
     const TextIteratorTextState& text() const { return m_textState; }
     int length() const { return m_textState.length(); }
@@ -82,7 +82,7 @@
     // replaced elements. When |forSelectionPreservation| is set to true, it
     // also emits spaces for other non-text nodes using the
     // |TextIteratorEmitsCharactersBetweenAllVisiblePosition| mode.
-    static int rangeLength(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, bool forSelectionPreservation = false);
+    static int rangeLength(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, bool forSelectionPreservation = false);
 
     static bool shouldEmitTabBeforeNode(Node*);
     static bool shouldEmitNewlineBeforeNode(Node&);
diff --git a/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp b/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
index 14cd8488..68ff853 100644
--- a/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/Serialization.cpp
@@ -181,7 +181,7 @@
 }
 
 template<typename Strategy>
-static HTMLElement* highestAncestorToWrapMarkup(const PositionAlgorithm<Strategy>& startPosition, const PositionAlgorithm<Strategy>& endPosition, EAnnotateForInterchange shouldAnnotate, Node* constrainingAncestor)
+static HTMLElement* highestAncestorToWrapMarkup(const PositionTemplate<Strategy>& startPosition, const PositionTemplate<Strategy>& endPosition, EAnnotateForInterchange shouldAnnotate, Node* constrainingAncestor)
 {
     Node* firstNode = startPosition.nodeAsRangeFirstNode();
     // For compatibility reason, we use container node of start and end
@@ -234,13 +234,13 @@
 template <typename Strategy>
 class CreateMarkupAlgorithm {
 public:
-    static String createMarkup(const PositionAlgorithm<Strategy>& startPosition, const PositionAlgorithm<Strategy>& endPosition, EAnnotateForInterchange shouldAnnotate = DoNotAnnotateForInterchange, ConvertBlocksToInlines = ConvertBlocksToInlines::NotConvert, EAbsoluteURLs shouldResolveURLs = DoNotResolveURLs, Node* constrainingAncestor = nullptr);
+    static String createMarkup(const PositionTemplate<Strategy>& startPosition, const PositionTemplate<Strategy>& endPosition, EAnnotateForInterchange shouldAnnotate = DoNotAnnotateForInterchange, ConvertBlocksToInlines = ConvertBlocksToInlines::NotConvert, EAbsoluteURLs shouldResolveURLs = DoNotResolveURLs, Node* constrainingAncestor = nullptr);
 };
 
 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForInterchange?
 // FIXME: At least, annotation and style info should probably not be included in range.markupString()
 template <typename Strategy>
-String CreateMarkupAlgorithm<Strategy>::createMarkup(const PositionAlgorithm<Strategy>& startPosition, const PositionAlgorithm<Strategy>& endPosition,
+String CreateMarkupAlgorithm<Strategy>::createMarkup(const PositionTemplate<Strategy>& startPosition, const PositionTemplate<Strategy>& endPosition,
     EAnnotateForInterchange shouldAnnotate, ConvertBlocksToInlines convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs, Node* constrainingAncestor)
 {
     ASSERT(startPosition.isNotNull());
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
index b47c91d1..eb48adc 100644
--- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
@@ -49,7 +49,7 @@
 namespace {
 
 template<typename Strategy>
-TextOffset toTextOffset(const PositionAlgorithm<Strategy>& position)
+TextOffset toTextOffset(const PositionTemplate<Strategy>& position)
 {
     if (position.isNull())
         return TextOffset();
@@ -123,7 +123,7 @@
 }
 
 template<typename Strategy>
-StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines convertBlocksToInlines)
+StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines convertBlocksToInlines)
     : m_start(start)
     , m_end(end)
     , m_shouldResolveURLs(shouldResolveURLs)
@@ -151,7 +151,7 @@
 }
 
 template<typename Strategy>
-static bool areSameRanges(Node* node, const PositionAlgorithm<Strategy>& startPosition, const PositionAlgorithm<Strategy>& endPosition)
+static bool areSameRanges(Node* node, const PositionTemplate<Strategy>& startPosition, const PositionTemplate<Strategy>& endPosition)
 {
     ASSERT(node);
     const EphemeralRange range = VisibleSelection::selectionFromContentsOfNode(node).toNormalizedEphemeralRange();
@@ -184,7 +184,7 @@
 
         firstNode = nextPositionOf(visibleStart).deepEquivalent().anchorNode();
 
-        if (pastEnd && PositionAlgorithm<Strategy>::beforeNode(firstNode).compareTo(PositionAlgorithm<Strategy>::beforeNode(pastEnd)) >= 0) {
+        if (pastEnd && PositionTemplate<Strategy>::beforeNode(firstNode).compareTo(PositionTemplate<Strategy>::beforeNode(pastEnd)) >= 0) {
             // This condition hits in editing/pasteboard/copy-display-none.html.
             return markupAccumulator.takeResults();
         }
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.h b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.h
index ce0f4155..92980b1 100644
--- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.h
+++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.h
@@ -42,15 +42,15 @@
 class StyledMarkupSerializer final {
     STACK_ALLOCATED();
 public:
-    StyledMarkupSerializer(EAbsoluteURLs, EAnnotateForInterchange, const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines);
+    StyledMarkupSerializer(EAbsoluteURLs, EAnnotateForInterchange, const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines);
 
     String createMarkup();
 
 private:
     bool shouldAnnotate() const { return m_shouldAnnotate == AnnotateForInterchange; }
 
-    const PositionAlgorithm<Strategy> m_start;
-    const PositionAlgorithm<Strategy> m_end;
+    const PositionTemplate<Strategy> m_start;
+    const PositionTemplate<Strategy> m_end;
     const EAbsoluteURLs m_shouldResolveURLs;
     const EAnnotateForInterchange m_shouldAnnotate;
     const RefPtrWillBeMember<Node> m_highestNodeToBeSerialized;
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializerTest.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializerTest.cpp
index 98421bf..838aa4d 100644
--- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializerTest.cpp
@@ -30,19 +30,19 @@
     std::string serialize(EAnnotateForInterchange = DoNotAnnotateForInterchange);
 
     template <typename Strategy>
-    std::string serializePart(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, EAnnotateForInterchange = DoNotAnnotateForInterchange);
+    std::string serializePart(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, EAnnotateForInterchange = DoNotAnnotateForInterchange);
 };
 
 template <typename Strategy>
 std::string StyledMarkupSerializerTest::serialize(EAnnotateForInterchange shouldAnnotate)
 {
-    PositionAlgorithm<Strategy> start = PositionAlgorithm<Strategy>(document().body(), PositionAnchorType::BeforeChildren);
-    PositionAlgorithm<Strategy> end = PositionAlgorithm<Strategy>(document().body(), PositionAnchorType::AfterChildren);
+    PositionTemplate<Strategy> start = PositionTemplate<Strategy>(document().body(), PositionAnchorType::BeforeChildren);
+    PositionTemplate<Strategy> end = PositionTemplate<Strategy>(document().body(), PositionAnchorType::AfterChildren);
     return createMarkup(start, end, shouldAnnotate).utf8().data();
 }
 
 template <typename Strategy>
-std::string StyledMarkupSerializerTest::serializePart(const PositionAlgorithm<Strategy>& start, const PositionAlgorithm<Strategy>& end, EAnnotateForInterchange shouldAnnotate)
+std::string StyledMarkupSerializerTest::serializePart(const PositionTemplate<Strategy>& start, const PositionTemplate<Strategy>& end, EAnnotateForInterchange shouldAnnotate)
 {
     return createMarkup(start, end, shouldAnnotate).utf8().data();
 }
diff --git a/third_party/WebKit/Source/core/events/CustomEvent.cpp b/third_party/WebKit/Source/core/events/CustomEvent.cpp
index a9c87cbb..3d36ece 100644
--- a/third_party/WebKit/Source/core/events/CustomEvent.cpp
+++ b/third_party/WebKit/Source/core/events/CustomEvent.cpp
@@ -27,6 +27,7 @@
 #include "core/events/CustomEvent.h"
 
 #include "bindings/core/v8/SerializedScriptValue.h"
+#include "bindings/core/v8/SerializedScriptValueFactory.h"
 
 namespace blink {
 
@@ -37,8 +38,6 @@
 CustomEvent::CustomEvent(const AtomicString& type, const CustomEventInit& initializer)
     : Event(type, initializer)
 {
-    if (initializer.hasDetail())
-        m_detail = initializer.detail();
 }
 
 CustomEvent::~CustomEvent()
@@ -48,7 +47,7 @@
 void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, const ScriptValue& detail)
 {
     initEvent(type, canBubble, cancelable);
-    m_detail = detail;
+    m_serializedDetail = SerializedScriptValueFactory::instance().createAndSwallowExceptions(detail.isolate(), detail.v8Value());
 }
 
 void CustomEvent::initCustomEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> serializedDetail)
diff --git a/third_party/WebKit/Source/core/events/CustomEvent.h b/third_party/WebKit/Source/core/events/CustomEvent.h
index 82d5f35..9ae76f8 100644
--- a/third_party/WebKit/Source/core/events/CustomEvent.h
+++ b/third_party/WebKit/Source/core/events/CustomEvent.h
@@ -55,8 +55,7 @@
     const AtomicString& interfaceName() const override;
 
     SerializedScriptValue* serializedDetail() { return m_serializedDetail.get(); }
-
-    ScriptValue detail() const { return m_detail; }
+    void setSerializedDetail(PassRefPtr<SerializedScriptValue> serializedDetail) { m_serializedDetail = serializedDetail; }
 
     DECLARE_VIRTUAL_TRACE();
 
@@ -64,7 +63,6 @@
     CustomEvent();
     CustomEvent(const AtomicString& type, const CustomEventInit& initializer);
 
-    ScriptValue m_detail;
     RefPtr<SerializedScriptValue> m_serializedDetail;
 };
 
diff --git a/third_party/WebKit/Source/core/events/CustomEvent.idl b/third_party/WebKit/Source/core/events/CustomEvent.idl
index 5e6d7abd..260e2e19 100644
--- a/third_party/WebKit/Source/core/events/CustomEvent.idl
+++ b/third_party/WebKit/Source/core/events/CustomEvent.idl
@@ -26,7 +26,9 @@
 // https://dom.spec.whatwg.org/#interface-customevent
 
 [
-    Constructor(DOMString type, optional CustomEventInit eventInitDict),
+    // TODO(bashi): Don't use CustomConstructor. Constructor should be:
+    // Constructor(DOMString type, optional CustomEventInit eventInitDict),
+    CustomConstructor,
     Exposed=(Window,Worker),
 ] interface CustomEvent : Event {
     [Custom=Getter] readonly attribute any detail;
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
index ce4e585e..fd5471d 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -156,7 +156,7 @@
     Resource::allClientsRemoved();
 }
 
-pair<blink::Image*, float> ImageResource::brokenImage(float deviceScaleFactor)
+std::pair<blink::Image*, float> ImageResource::brokenImage(float deviceScaleFactor)
 {
     if (deviceScaleFactor >= 2) {
         DEFINE_STATIC_REF(blink::Image, brokenImageHiRes, (blink::Image::loadPlatformResource("missingImage@2x")));
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
index b514d46..7faf9ae 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.cpp
@@ -8,6 +8,7 @@
 #include "bindings/core/v8/ScriptCallStackFactory.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/dom/ExecutionContext.h"
 #include "core/dom/SecurityContext.h"
 #include "core/events/MessageEvent.h"
 #include "core/frame/Frame.h"
@@ -120,7 +121,9 @@
 
 bool DOMWindow::isCurrentlyDisplayedInFrame() const
 {
-    return frame() && frame()->domWindow() == this && frame()->host();
+    if (frame())
+        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(frame()->domWindow() == this);
+    return frame() && frame()->host();
 }
 
 bool DOMWindow::isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString)
@@ -155,6 +158,15 @@
     }
 }
 
+bool DOMWindow::isSecureContext() const
+{
+    if (!frame())
+        return false;
+
+    String unusedErrorMessage;
+    return document()->isSecureContext(unusedErrorMessage, ExecutionContext::StandardSecureContextCheck);
+}
+
 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState)
 {
     if (!isCurrentlyDisplayedInFrame())
diff --git a/third_party/WebKit/Source/core/frame/DOMWindow.h b/third_party/WebKit/Source/core/frame/DOMWindow.h
index ae786035..f811f8b 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindow.h
@@ -197,6 +197,8 @@
 
     void resetLocation();
 
+    bool isSecureContext() const;
+
     DEFINE_ATTRIBUTE_EVENT_LISTENER(animationend);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(animationiteration);
     DEFINE_ATTRIBUTE_EVENT_LISTENER(animationstart);
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index d27feb2..0ac9a2b 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -96,6 +96,7 @@
 #include "platform/graphics/paint/DisplayItemList.h"
 #include "platform/scroll/ScrollAnimator.h"
 #include "platform/text/TextStream.h"
+#include "public/platform/WebDisplayItemList.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/TemporaryChange.h"
@@ -2437,9 +2438,10 @@
 
             updateCompositedSelectionIfNeeded();
 
-            if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
-                paintForSlimmingPaintV2(interestRect);
-                compositeForSlimmingPaintV2();
+            if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
+                synchronizedPaint(interestRect);
+                if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+                    compositeForSlimmingPaintV2();
             }
 
             if (RuntimeEnabledFeatures::frameTimingSupportEnabled())
@@ -2447,30 +2449,47 @@
 
             ASSERT(!view->hasPendingSelection());
             ASSERT(lifecycle().state() == DocumentLifecycle::PaintInvalidationClean
-                || (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && lifecycle().state() == DocumentLifecycle::CompositingForSlimmingPaintV2Clean));
+                || (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && lifecycle().state() == DocumentLifecycle::CompositingForSlimmingPaintV2Clean)
+                || (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled() && lifecycle().state() == DocumentLifecycle::PaintClean));
         }
     }
 }
 
-void FrameView::paintForSlimmingPaintV2(const LayoutRect& interestRect)
+void FrameView::synchronizedPaint(const LayoutRect& interestRect)
 {
-    ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
+    ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled());
     ASSERT(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame()));
 
     LayoutView* view = layoutView();
     ASSERT(view);
+    // TODO(chrishtr): figure out if there can be any GraphicsLayer above this one that draws content.
     GraphicsLayer* rootGraphicsLayer = view->layer()->graphicsLayerBacking();
+    lifecycle().advanceTo(DocumentLifecycle::InPaint);
 
-    // Detached frames can have no root graphics layer.
-    if (!rootGraphicsLayer)
-        return;
+    // A null graphics layer can occur for painting of SVG images that are not parented into the main frame tree.
+    if (rootGraphicsLayer) {
+        synchronizedPaintRecursively(rootGraphicsLayer, interestRect);
+    }
+    lifecycle().advanceTo(DocumentLifecycle::PaintClean);
+}
 
-    lifecycle().advanceTo(DocumentLifecycle::InPaintForSlimmingPaintV2);
+void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer, const LayoutRect& interestRect)
+{
+    if (graphicsLayer->needsDisplay()) {
+        // TODO(chrishtr): implement interest rects.
+        GraphicsContext context(graphicsLayer->displayItemList());
+        graphicsLayer->paint(context, roundedIntRect(interestRect));
 
-    GraphicsContext context(rootGraphicsLayer->displayItemList());
-    rootGraphicsLayer->paint(context, roundedIntRect(interestRect));
+        if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+            DisplayListDiff diff;
+            graphicsLayer->commitIfNeeded(diff);
+        }
+    }
 
-    lifecycle().advanceTo(DocumentLifecycle::PaintForSlimmingPaintV2Clean);
+    for (auto& child : graphicsLayer->children()) {
+        if (child)
+            synchronizedPaintRecursively(child, interestRect);
+    }
 }
 
 void FrameView::compositeForSlimmingPaintV2()
@@ -2487,7 +2506,7 @@
     lifecycle().advanceTo(DocumentLifecycle::InCompositingForSlimmingPaintV2);
 
     DisplayListDiff displayListDiff;
-    rootGraphicsLayer->displayItemList()->commitNewDisplayItems(&displayListDiff);
+    rootGraphicsLayer->commitIfNeeded(displayListDiff);
 
     DisplayListCompositingBuilder compositingBuilder(*rootGraphicsLayer->displayItemList(), displayListDiff);
     OwnPtr<CompositedDisplayList> compositedDisplayList = adoptPtr(new CompositedDisplayList());
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index b5ac796..a612cbf 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -359,7 +359,7 @@
     bool isScrollCornerVisible() const override;
     bool userInputScrollable(ScrollbarOrientation) const override;
     bool shouldPlaceVerticalScrollbarOnLeft() const override;
-    virtual LayoutRect scrollIntoView(
+    LayoutRect scrollIntoView(
         const LayoutRect& rectInContent,
         const ScrollAlignment& alignX,
         const ScrollAlignment& alignY) override;
@@ -615,7 +615,8 @@
     void invalidateTreeIfNeededRecursive();
     void scrollContentsIfNeededRecursive();
     void updateStyleAndLayoutIfNeededRecursive();
-    void paintForSlimmingPaintV2(const LayoutRect& interestRect);
+    void synchronizedPaint(const LayoutRect& interestRect);
+    void synchronizedPaintRecursively(GraphicsLayer*, const LayoutRect& interestRect);
     void compositeForSlimmingPaintV2();
 
     void reset();
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 1da4958..8532109 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -523,7 +523,7 @@
 
 void LocalDOMWindow::reset()
 {
-    frameDestroyed();
+    m_frameObserver->contextDestroyed();
 
     m_screen = nullptr;
     m_history = nullptr;
@@ -541,8 +541,6 @@
     m_hasBeenReset = true;
 #endif
 
-    resetLocation();
-
     LocalDOMWindow::notifyContextDestroyed();
 }
 
@@ -662,17 +660,8 @@
 
 Navigator* LocalDOMWindow::navigator() const
 {
-    if (!isCurrentlyDisplayedInFrame() && (!m_navigator || m_navigator->frame())) {
-        // We return a navigator with null frame instead of returning null
-        // pointer as other functions do, in order to allow users to access
-        // functions such as navigator.product.
-        m_navigator = Navigator::create(nullptr);
-    }
     if (!m_navigator)
         m_navigator = Navigator::create(frame());
-    // As described above, when not dispayed in the frame, the returning
-    // navigator should not be associated with the frame.
-    ASSERT(isCurrentlyDisplayedInFrame() || !m_navigator->frame());
     return m_navigator.get();
 }
 
@@ -1387,8 +1376,9 @@
         timing.markLoadEventStart();
         dispatchEvent(loadEvent, document());
         timing.markLoadEventEnd();
-    } else
+    } else {
         dispatchEvent(loadEvent, document());
+    }
 
     // For load events, send a separate load event to the enclosing frame only.
     // This is a DOM extension and is independent of bubbling/capturing rules of
@@ -1474,9 +1464,9 @@
     // Get the target frame for the special cases of _top and _parent.
     // In those cases, we schedule a location change right now and return early.
     Frame* targetFrame = nullptr;
-    if (frameName == "_top")
+    if (frameName == "_top") {
         targetFrame = frame()->tree().top();
-    else if (frameName == "_parent") {
+    } else if (frameName == "_parent") {
         if (Frame* parent = frame()->tree().parent())
             targetFrame = parent;
         else
@@ -1530,6 +1520,11 @@
 
 LocalFrame* LocalDOMWindow::frame() const
 {
+    // If the LocalDOMWindow still has a frame reference, that frame must point
+    // back to this LocalDOMWindow: otherwise, it's easy to get into a situation
+    // where script execution leaks between different LocalDOMWindows.
+    if (m_frameObserver->frame())
+        ASSERT_WITH_SECURITY_IMPLICATION(m_frameObserver->frame()->domWindow() == this);
     return m_frameObserver->frame();
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
index 379590ec..279ee89 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -223,13 +223,13 @@
 
         DECLARE_VIRTUAL_TRACE();
 
-    private:
-        WindowFrameObserver(LocalDOMWindow*, LocalFrame&);
-
         // LocalFrameLifecycleObserver overrides:
         void willDetachFrameHost() override;
         void contextDestroyed() override;
 
+    private:
+        WindowFrameObserver(LocalDOMWindow*, LocalFrame&);
+
         RawPtrWillBeMember<LocalDOMWindow> m_window;
     };
     friend WTF::OwnedPtrDeleter<WindowFrameObserver>;
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h
index f9b9f9c6..4e0e7d83 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.h
+++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -142,7 +142,6 @@
         DocumentCreateAttribute = 111,
         DocumentCreateAttributeNS = 112,
         DocumentCreateCDATASection = 113, // Removed from DOM4.
-        DocumentInputEncoding = 114,
         DocumentXMLEncoding = 115, // Removed from DOM4.
         DocumentXMLStandalone = 116, // Removed from DOM4.
         DocumentXMLVersion = 117, // Removed from DOM4.
@@ -151,7 +150,6 @@
         NavigatorVendor = 124,
         NavigatorVendorSub = 125,
         FileError = 126,
-        DocumentCharset = 127, // Documented as IE extensions = 0, from KHTML days.
         PrefixedAnimationEndEvent = 128,
         UnprefixedAnimationEndEvent = 129,
         PrefixedAndUnprefixedAnimationEndEvent = 130,
@@ -656,10 +654,6 @@
         V8Element_Animate_Method = 773,
         // The above items are available in M44 branch.
 
-        V8SVGSVGElement_PixelUnitToMillimeterX_AttributeGetter = 774,
-        V8SVGSVGElement_PixelUnitToMillimeterY_AttributeGetter = 775,
-        V8SVGSVGElement_ScreenPixelToMillimeterX_AttributeGetter = 776,
-        V8SVGSVGElement_ScreenPixelToMillimeterY_AttributeGetter = 777,
         V8SVGSVGElement_GetElementById_Method = 778,
         ElementCreateShadowRootMultiple = 779,
         V8MessageChannel_Constructor = 780,
@@ -839,6 +833,11 @@
         BackspaceNavigatedBack = 957,
         BackspaceNavigatedBackAfterFormInteraction = 958,
         CSPSourceWildcardWouldMatchExactHost = 959,
+        CredentialManagerGet = 959,
+        CredentialManagerGetWithUI = 960,
+        CredentialManagerGetWithoutUI = 961,
+        CredentialManagerStore = 962,
+        CredentialManagerRequireUserMediation = 963,
 
         // Add new features immediately above this line. Don't change assigned
         // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl
index 08a3c6f..156c1f3 100644
--- a/third_party/WebKit/Source/core/frame/Window.idl
+++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -185,6 +185,9 @@
     attribute EventHandler onwebkittransitionend;
     attribute EventHandler onwheel;
 
+    // https://w3c.github.io/webappsec/specs/powerfulfeatures/#monkey-patching-global-object
+    readonly attribute boolean isSecureContext;
+
     // window.toString() requires special handling in V8
     [DoNotCheckSignature, DoNotCheckSecurity, Custom, NotEnumerable] stringifier;
 };
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
index be49ffb..36e4f45a 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -363,7 +363,7 @@
         LayoutImageResource* layoutImageResource = layoutImage->imageResource();
         if (m_isFallbackImage) {
             float deviceScaleFactor = blink::deviceScaleFactor(layoutImage->frame());
-            pair<Image*, float> brokenImageAndImageScaleFactor = ImageResource::brokenImage(deviceScaleFactor);
+            std::pair<Image*, float> brokenImageAndImageScaleFactor = ImageResource::brokenImage(deviceScaleFactor);
             ImageResource* newImageResource = new ImageResource(brokenImageAndImageScaleFactor.first);
             layoutImage->imageResource()->setImageResource(newImageResource);
         }
@@ -691,7 +691,10 @@
     }
     imageLoader().updateFromElement(behavior, m_referrerPolicy);
 
-    if (imageLoader().image() || (imageLoader().hasPendingActivity() && !imageSourceURL().isEmpty()))
+    // Images such as data: uri's can return immediately and may already have errored out.
+    bool imageHasLoaded = imageLoader().image() && !imageLoader().image()->errorOccurred();
+    bool imageStillLoading = !imageHasLoaded && imageLoader().hasPendingActivity() && !imageLoader().hasPendingError() && !imageSourceURL().isEmpty();
+    if (imageHasLoaded || imageStillLoading)
         ensurePrimaryContent();
     else
         ensureFallbackContent();
diff --git a/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp b/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
index f4e9ca6..eabff06e 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageLoader.cpp
@@ -38,7 +38,6 @@
 
 HTMLImageLoader::HTMLImageLoader(Element* element)
     : ImageLoader(element)
-    , m_loadFallbackContentTimer(this, &HTMLImageLoader::timerFired)
 {
 }
 
@@ -102,14 +101,7 @@
 
 void HTMLImageLoader::ensureFallbackContent()
 {
-    if (image()->url().protocolIsData())
-        m_loadFallbackContentTimer.startOneShot(0, FROM_HERE);
-    else
-        loadFallbackContentForElement(element());
-}
-
-void HTMLImageLoader::timerFired(Timer<HTMLImageLoader>*)
-{
     loadFallbackContentForElement(element());
 }
+
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLImageLoader.h b/third_party/WebKit/Source/core/html/HTMLImageLoader.h
index 84d4588..5852c73 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageLoader.h
+++ b/third_party/WebKit/Source/core/html/HTMLImageLoader.h
@@ -41,8 +41,6 @@
     void notifyFinished(Resource*) override;
 
 private:
-    Timer<HTMLImageLoader> m_loadFallbackContentTimer;
-    void timerFired(Timer<HTMLImageLoader>*);
     explicit HTMLImageLoader(Element*);
     void noImageResourceToLoad() override;
     void ensureFallbackContent();
diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
index f06fd168..da256fa 100644
--- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp
@@ -1181,6 +1181,8 @@
     OwnPtrWillBeRawPtr<ClickHandlingState> state = adoptPtrWillBeNoop(static_cast<ClickHandlingState*>(dataFromPreDispatch));
     if (!state)
         return;
+    // m_inputTypeView could be freed if the type attribute is modified through a change event handler.
+    RefPtrWillBeRawPtr<InputTypeView> protect(m_inputTypeView.get());
     m_inputTypeView->didDispatchClick(event, *state);
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 0da37222..02debc6 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -80,7 +80,7 @@
     : HTMLFormControlElementWithState(selectTag, document, form)
     , m_typeAhead(this)
     , m_size(0)
-    , m_lastOnChangeIndex(-1)
+    , m_lastOnChangeOption(nullptr)
     , m_activeSelectionAnchorIndex(-1)
     , m_activeSelectionEndIndex(-1)
     , m_isProcessingUserDrivenChange(false)
@@ -249,11 +249,8 @@
 
 String HTMLSelectElement::value() const
 {
-    const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems();
-    for (unsigned i = 0; i < items.size(); i++) {
-        if (isHTMLOptionElement(items[i]) && toHTMLOptionElement(items[i])->selected())
-            return toHTMLOptionElement(items[i])->value();
-    }
+    if (HTMLOptionElement* option = selectedOption())
+        return option->value();
     return "";
 }
 
@@ -630,7 +627,7 @@
 void HTMLSelectElement::saveLastSelection()
 {
     if (usesMenuList()) {
-        m_lastOnChangeIndex = selectedIndex();
+        m_lastOnChangeOption = selectedOption();
         return;
     }
 
@@ -724,9 +721,9 @@
 {
     ASSERT(usesMenuList());
 
-    int selected = selectedIndex();
-    if (m_lastOnChangeIndex != selected && (!requiresUserGesture || m_isProcessingUserDrivenChange)) {
-        m_lastOnChangeIndex = selected;
+    HTMLOptionElement* selectedOption = this->selectedOption();
+    if (m_lastOnChangeOption.get() != selectedOption && (!requiresUserGesture || m_isProcessingUserDrivenChange)) {
+        m_lastOnChangeOption = selectedOption;
         m_isProcessingUserDrivenChange = false;
         RefPtrWillBeRawPtr<HTMLSelectElement> protector(this);
         dispatchInputEvent();
@@ -861,6 +858,15 @@
         firstOption->setSelectedState(true);
 }
 
+HTMLOptionElement* HTMLSelectElement::selectedOption() const
+{
+    for (const auto& element : listItems()) {
+        if (isHTMLOptionElement(*element) && toHTMLOptionElement(*element).selected())
+            return toHTMLOptionElement(element);
+    }
+    return nullptr;
+}
+
 int HTMLSelectElement::selectedIndex() const
 {
     unsigned index = 0;
@@ -938,6 +944,8 @@
 
 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option)
 {
+    if (m_lastOnChangeOption == &option)
+        m_lastOnChangeOption.clear();
     if (m_activeSelectionAnchorIndex < 0 && m_activeSelectionEndIndex < 0)
         return;
     int listIndex = optionToListIndex(option.index());
@@ -1768,6 +1776,7 @@
 #if ENABLE(OILPAN)
     visitor->trace(m_listItems);
 #endif
+    visitor->trace(m_lastOnChangeOption);
     visitor->trace(m_popup);
     HTMLFormControlElementWithState::trace(visitor);
 }
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
index 1fa16b1..0f8fdb7 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -197,6 +197,8 @@
 
     void typeAheadFind(KeyboardEvent*);
     void saveLastSelection();
+    // Returns the first selected OPTION, or nullptr.
+    HTMLOptionElement* selectedOption() const;
 
     InsertionNotificationRequest insertedInto(ContainerNode*) override;
 
@@ -254,7 +256,7 @@
     Vector<bool> m_cachedStateForActiveSelection;
     TypeAhead m_typeAhead;
     unsigned m_size;
-    int m_lastOnChangeIndex;
+    RefPtrWillBeMember<HTMLOptionElement> m_lastOnChangeOption;
     int m_activeSelectionAnchorIndex;
     int m_activeSelectionEndIndex;
     bool m_isProcessingUserDrivenChange;
diff --git a/third_party/WebKit/Source/core/html/HTMLTagNames.in b/third_party/WebKit/Source/core/html/HTMLTagNames.in
index 6571285..923233c 100644
--- a/third_party/WebKit/Source/core/html/HTMLTagNames.in
+++ b/third_party/WebKit/Source/core/html/HTMLTagNames.in
@@ -8,6 +8,7 @@
 abbr interfaceName=HTMLElement
 acronym interfaceName=HTMLElement
 address interfaceName=HTMLElement
+applet interfaceName=HTMLUnknownElement
 area
 article interfaceName=HTMLElement
 aside interfaceName=HTMLElement
diff --git a/third_party/WebKit/Source/core/html/LinkResource.cpp b/third_party/WebKit/Source/core/html/LinkResource.cpp
index 20a884f..ee7a3345 100644
--- a/third_party/WebKit/Source/core/html/LinkResource.cpp
+++ b/third_party/WebKit/Source/core/html/LinkResource.cpp
@@ -73,7 +73,7 @@
 {
     m_charset = m_owner->getAttribute(charsetAttr);
     if (m_charset.isEmpty() && m_owner->document().frame())
-        m_charset = m_owner->document().charset();
+        m_charset = m_owner->document().characterSet();
 }
 
 FetchRequest LinkRequestBuilder::build(bool blocking) const
diff --git a/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp b/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp
index b41cd74..f3f4e39 100644
--- a/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp
+++ b/third_party/WebKit/Source/core/html/MediaFragmentURIParser.cpp
@@ -153,7 +153,7 @@
     m_timeFormat = Invalid;
 
     for (unsigned i = 0; i < m_fragments.size(); ++i) {
-        pair<String, String>& fragment = m_fragments[i];
+        std::pair<String, String>& fragment = m_fragments[i];
 
         ASSERT(fragment.first.is8Bit());
         ASSERT(fragment.second.is8Bit());
diff --git a/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp b/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp
index 5e5ce03997..2be0d960 100644
--- a/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/CheckboxInputType.cpp
@@ -88,11 +88,6 @@
 
 void CheckboxInputType::didDispatchClick(Event* event, const ClickHandlingState& state)
 {
-    // Prevent change event handlers from indirectly freeing the
-    // CheckboxInputType via a modification of the "type" attribute on the
-    // HTMLInputElement.
-    RefPtrWillBeRawPtr<CheckboxInputType> protect(this);
-
     if (event->defaultPrevented() || event->defaultHandled()) {
         element().setIndeterminate(state.indeterminate);
         element().setChecked(state.checked);
diff --git a/third_party/WebKit/Source/core/html/forms/FileInputType.cpp b/third_party/WebKit/Source/core/html/forms/FileInputType.cpp
index db3d2ffc..c672cb2 100644
--- a/third_party/WebKit/Source/core/html/forms/FileInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/FileInputType.cpp
@@ -242,12 +242,12 @@
 
 void FileInputType::countUsage()
 {
-    // It is required by isPrivilegedContext() but isn't
+    // It is required by isSecureContext() but isn't
     // actually used. This could be used later if a warning is shown in the
     // developer console.
     String insecureOriginMsg;
     Document* document = &element().document();
-    if (document->isPrivilegedContext(insecureOriginMsg))
+    if (document->isSecureContext(insecureOriginMsg))
         UseCounter::count(*document, UseCounter::InputTypeFileInsecureOrigin);
     else
         UseCounter::count(*document, UseCounter::InputTypeFileSecureOrigin);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
index 2edee02d8..2df710a 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLElementStack.cpp
@@ -48,7 +48,8 @@
 
 inline bool isScopeMarker(HTMLStackItem* item)
 {
-    return item->hasTagName(captionTag)
+    return item->hasTagName(appletTag)
+        || item->hasTagName(captionTag)
         || item->hasTagName(marqueeTag)
         || item->hasTagName(objectTag)
         || item->hasTagName(tableTag)
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp
index bcab21ac..eb108dc 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.cpp
@@ -121,6 +121,8 @@
     UChar firstCharacter = string[0];
     if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter))
         return fallbackValue;
+    if (string.endsWith('.'))
+        return fallbackValue;
 
     bool valid = false;
     double value = string.toDouble(&valid);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h b/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h
index 11dc5b72..a4291cc 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserIdioms.h
@@ -60,7 +60,7 @@
 // http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-non-negative-integers
 bool parseHTMLNonNegativeInteger(const String&, unsigned&);
 
-typedef Vector<pair<String, String>> HTMLAttributeList;
+typedef Vector<std::pair<String, String>> HTMLAttributeList;
 // The returned encoding might not be valid.
 WTF::TextEncoding encodingFromMetaAttributes(const HTMLAttributeList&);
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp b/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp
index 683f980..bff78e5 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLResourcePreloader.cpp
@@ -81,7 +81,7 @@
     if (request.url().protocolIsData())
         return;
     if (preload->resourceType() == Resource::Script || preload->resourceType() == Resource::CSSStyleSheet || preload->resourceType() == Resource::ImportResource)
-        request.setCharset(preload->charset().isEmpty() ? m_document->charset().string() : preload->charset());
+        request.setCharset(preload->charset().isEmpty() ? m_document->characterSet().string() : preload->charset());
     request.setForPreload(true);
     Platform::current()->histogramCustomCounts("WebCore.PreloadDelayMs", static_cast<int>(1000 * (monotonicallyIncreasingTime() - preload->discoveryTime())), 0, 2000, 20);
     m_document->loader()->startPreload(preload->resourceType(), request);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h b/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h
index e978ff1..b3ebe8ee 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLStackItem.h
@@ -135,6 +135,7 @@
         const AtomicString& tagName = localName();
         return tagName == HTMLNames::addressTag
             || tagName == HTMLNames::areaTag
+            || tagName == HTMLNames::appletTag
             || tagName == HTMLNames::articleTag
             || tagName == HTMLNames::asideTag
             || tagName == HTMLNames::baseTag
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
index 21d666b6..7a1d819 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
@@ -752,12 +752,14 @@
         m_tree.insertFormattingElement(token);
         return;
     }
-    if (token->name() == embedTag
+    if (token->name() == appletTag
+        || token->name() == embedTag
         || token->name() == objectTag) {
         if (!pluginContentIsAllowed(m_tree.parserContentPolicy()))
             return;
     }
-    if (token->name() == marqueeTag
+    if (token->name() == appletTag
+        || token->name() == marqueeTag
         || token->name() == objectTag) {
         m_tree.reconstructTheActiveFormattingElements();
         m_tree.insertHTMLElement(token);
@@ -1858,7 +1860,8 @@
         callTheAdoptionAgency(token);
         return;
     }
-    if (token->name() == marqueeTag
+    if (token->name() == appletTag
+        || token->name() == marqueeTag
         || token->name() == objectTag) {
         if (!m_tree.openElements()->inScope(token->name())) {
             parseError(token);
diff --git a/third_party/WebKit/Source/core/inspector/AsyncCallChain.cpp b/third_party/WebKit/Source/core/inspector/AsyncCallChain.cpp
index 10dbc99..0a67c78 100644
--- a/third_party/WebKit/Source/core/inspector/AsyncCallChain.cpp
+++ b/third_party/WebKit/Source/core/inspector/AsyncCallChain.cpp
@@ -9,11 +9,6 @@
 
 namespace blink {
 
-DEFINE_TRACE(AsyncCallChain)
-{
-    visitor->trace(m_callStacks);
-}
-
 AsyncCallStack::AsyncCallStack(const String& description, v8::Local<v8::Object> callFrames)
     : m_description(description)
     , m_callFrames(callFrames->GetIsolate(), callFrames)
@@ -24,12 +19,12 @@
 {
 }
 
-PassRefPtrWillBeRawPtr<AsyncCallChain> AsyncCallChain::create(PassRefPtrWillBeRawPtr<AsyncCallStack> stack, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength)
+PassRefPtr<AsyncCallChain> AsyncCallChain::create(PassRefPtr<AsyncCallStack> stack, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength)
 {
-    return adoptRefWillBeNoop(new AsyncCallChain(stack, prevChain, asyncCallChainMaxLength));
+    return adoptRef(new AsyncCallChain(stack, prevChain, asyncCallChainMaxLength));
 }
 
-AsyncCallChain::AsyncCallChain(PassRefPtrWillBeRawPtr<AsyncCallStack> stack, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength)
+AsyncCallChain::AsyncCallChain(PassRefPtr<AsyncCallStack> stack, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength)
 {
     if (stack)
         m_callStacks.append(stack);
diff --git a/third_party/WebKit/Source/core/inspector/AsyncCallChain.h b/third_party/WebKit/Source/core/inspector/AsyncCallChain.h
index ef3dd35..17d91ff 100644
--- a/third_party/WebKit/Source/core/inspector/AsyncCallChain.h
+++ b/third_party/WebKit/Source/core/inspector/AsyncCallChain.h
@@ -5,19 +5,19 @@
 #ifndef AsyncCallChain_h
 #define AsyncCallChain_h
 
-#include "platform/heap/Handle.h"
 #include "wtf/Deque.h"
 #include "wtf/Forward.h"
 #include "wtf/RefCounted.h"
+#include "wtf/text/WTFString.h"
 #include <v8.h>
 
 namespace blink {
 
-class AsyncCallStack final : public RefCountedWillBeGarbageCollectedFinalized<AsyncCallStack> {
+class AsyncCallStack final : public RefCounted<AsyncCallStack> {
 public:
     AsyncCallStack(const String&, v8::Local<v8::Object>);
     ~AsyncCallStack();
-    DEFINE_INLINE_TRACE() { }
+
     String description() const { return m_description; }
     v8::Local<v8::Object> callFrames(v8::Isolate* isolate) const { return v8::Local<v8::Object>::New(isolate, m_callFrames); }
 private:
@@ -25,17 +25,16 @@
     v8::Global<v8::Object> m_callFrames;
 };
 
-using AsyncCallStackVector = WillBeHeapDeque<RefPtrWillBeMember<AsyncCallStack>, 4>;
+using AsyncCallStackVector = Deque<RefPtr<AsyncCallStack>, 4>;
 
-class AsyncCallChain final : public RefCountedWillBeGarbageCollectedFinalized<AsyncCallChain> {
+class AsyncCallChain final : public RefCounted<AsyncCallChain> {
 public:
-    static PassRefPtrWillBeRawPtr<AsyncCallChain> create(PassRefPtrWillBeRawPtr<AsyncCallStack>, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength);
+    static PassRefPtr<AsyncCallChain> create(PassRefPtr<AsyncCallStack>, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength);
     ~AsyncCallChain();
     const AsyncCallStackVector& callStacks() const { return m_callStacks; }
-    DECLARE_TRACE();
 
 private:
-    AsyncCallChain(PassRefPtrWillBeRawPtr<AsyncCallStack>, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength);
+    AsyncCallChain(PassRefPtr<AsyncCallStack>, AsyncCallChain* prevChain, unsigned asyncCallChainMaxLength);
 
     AsyncCallStackVector m_callStacks;
 };
diff --git a/third_party/WebKit/Source/core/inspector/AsyncCallTracker.cpp b/third_party/WebKit/Source/core/inspector/AsyncCallTracker.cpp
index 5f2d474..e017c0c 100644
--- a/third_party/WebKit/Source/core/inspector/AsyncCallTracker.cpp
+++ b/third_party/WebKit/Source/core/inspector/AsyncCallTracker.cpp
@@ -37,7 +37,6 @@
 #include "core/events/Event.h"
 #include "core/events/EventTarget.h"
 #include "core/inspector/AsyncOperationMap.h"
-#include "core/inspector/V8DebuggerAgent.h"
 #include "core/xmlhttprequest/XMLHttpRequest.h"
 #include "core/xmlhttprequest/XMLHttpRequestUpload.h"
 #include "platform/ScriptForbiddenScope.h"
@@ -140,14 +139,10 @@
     : m_debuggerAgent(debuggerAgent)
     , m_instrumentingAgents(instrumentingAgents)
 {
-    m_debuggerAgent->addAsyncCallTrackingListener(this);
 }
 
 AsyncCallTracker::~AsyncCallTracker()
 {
-#if !ENABLE(OILPAN)
-    m_debuggerAgent->removeAsyncCallTrackingListener(this);
-#endif
 }
 
 void AsyncCallTracker::asyncCallTrackingStateChanged(bool tracking)
@@ -431,10 +426,8 @@
 {
 #if ENABLE(OILPAN)
     visitor->trace(m_executionContextDataMap);
-    visitor->trace(m_debuggerAgent);
     visitor->trace(m_instrumentingAgents);
 #endif
-    V8DebuggerAgent::AsyncCallTrackingListener::trace(visitor);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/AsyncCallTracker.h b/third_party/WebKit/Source/core/inspector/AsyncCallTracker.h
index 05ba546..5ff6fd74 100644
--- a/third_party/WebKit/Source/core/inspector/AsyncCallTracker.h
+++ b/third_party/WebKit/Source/core/inspector/AsyncCallTracker.h
@@ -32,7 +32,8 @@
 #define AsyncCallTracker_h
 
 #include "core/CoreExport.h"
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/InstrumentingAgents.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 #include "platform/heap/Handle.h"
 #include "wtf/Forward.h"
 #include "wtf/HashMap.h"
@@ -52,17 +53,15 @@
 class ThreadableLoaderClient;
 class XMLHttpRequest;
 
-class CORE_EXPORT AsyncCallTracker final : public NoBaseWillBeGarbageCollectedFinalized<AsyncCallTracker>, public V8DebuggerAgent::AsyncCallTrackingListener {
+class CORE_EXPORT AsyncCallTracker final : public NoBaseWillBeGarbageCollectedFinalized<AsyncCallTracker> {
     WTF_MAKE_NONCOPYABLE(AsyncCallTracker);
-    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(AsyncCallTracker);
     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(AsyncCallTracker);
 public:
     AsyncCallTracker(V8DebuggerAgent*, InstrumentingAgents*);
-    ~AsyncCallTracker() override;
+    ~AsyncCallTracker();
 
-    // V8DebuggerAgent::AsyncCallTrackingListener implementation:
-    void asyncCallTrackingStateChanged(bool tracking) override;
-    void resetAsyncOperations() override;
+    void asyncCallTrackingStateChanged(bool tracking);
+    void resetAsyncOperations();
 
     void didInstallTimer(ExecutionContext*, int timerId, int timeout, bool singleShot);
     void didRemoveTimer(ExecutionContext*, int timerId);
@@ -113,7 +112,7 @@
 
     using ExecutionContextDataMap = WillBeHeapHashMap<RawPtrWillBeMember<ExecutionContext>, OwnPtrWillBeMember<ExecutionContextData>>;
     ExecutionContextDataMap m_executionContextDataMap;
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgent* m_debuggerAgent;
     RawPtrWillBeMember<InstrumentingAgents> m_instrumentingAgents;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/AsyncOperationMap.h b/third_party/WebKit/Source/core/inspector/AsyncOperationMap.h
index 3ff30ae..64c18aa 100644
--- a/third_party/WebKit/Source/core/inspector/AsyncOperationMap.h
+++ b/third_party/WebKit/Source/core/inspector/AsyncOperationMap.h
@@ -5,7 +5,7 @@
 #ifndef AsyncOperationMap_h
 #define AsyncOperationMap_h
 
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 #include "platform/heap/Handle.h"
 #include "wtf/HashMap.h"
 #include "wtf/PassRefPtr.h"
@@ -75,12 +75,11 @@
 
     DEFINE_INLINE_TRACE()
     {
-        visitor->trace(m_debuggerAgent);
         visitor->trace(m_asyncOperations);
     }
 
 private:
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgent* m_debuggerAgent;
     MapType m_asyncOperations;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/ContentSearchUtils.cpp b/third_party/WebKit/Source/core/inspector/ContentSearchUtils.cpp
index ffd6fbd0..24d0fe1 100644
--- a/third_party/WebKit/Source/core/inspector/ContentSearchUtils.cpp
+++ b/third_party/WebKit/Source/core/inspector/ContentSearchUtils.cpp
@@ -56,9 +56,9 @@
     return result.toString();
 }
 
-static Vector<pair<int, String> > getScriptRegexpMatchesByLines(const ScriptRegexp* regex, const String& text)
+static Vector<std::pair<int, String>> getScriptRegexpMatchesByLines(const ScriptRegexp* regex, const String& text)
 {
-    Vector<pair<int, String> > result;
+    Vector<std::pair<int, String>> result;
     if (text.isEmpty())
         return result;
 
@@ -73,7 +73,7 @@
 
         int matchLength;
         if (regex->match(line, 0, &matchLength) != -1)
-            result.append(pair<int, String>(lineNumber, line));
+            result.append(std::pair<int, String>(lineNumber, line));
 
         start = lineEnd + 1;
     }
@@ -99,7 +99,7 @@
     RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::SearchMatch>> result = TypeBuilder::Array<TypeBuilder::Debugger::SearchMatch>::create();
 
     OwnPtr<ScriptRegexp> regex = ContentSearchUtils::createSearchRegex(query, caseSensitive, isRegex);
-    Vector<pair<int, String> > matches = getScriptRegexpMatchesByLines(regex.get(), text);
+    Vector<std::pair<int, String>> matches = getScriptRegexpMatchesByLines(regex.get(), text);
 
     for (const auto& match : matches)
         result->addItem(buildObjectForSearchMatch(match.first, match.second));
diff --git a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
index c0c31e2e..9f63c278 100644
--- a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
+++ b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.cpp
@@ -201,7 +201,7 @@
     return result;
 }
 
-pair<DOMPatchSupport::ResultMap, DOMPatchSupport::ResultMap>
+std::pair<DOMPatchSupport::ResultMap, DOMPatchSupport::ResultMap>
 DOMPatchSupport::diff(const WillBeHeapVector<OwnPtrWillBeMember<Digest>>& oldList, const WillBeHeapVector<OwnPtrWillBeMember<Digest>>& newList)
 {
     ResultMap newMap(newList.size());
@@ -289,7 +289,7 @@
 
 bool DOMPatchSupport::innerPatchChildren(ContainerNode* parentNode, const WillBeHeapVector<OwnPtrWillBeMember<Digest>>& oldList, const WillBeHeapVector<OwnPtrWillBeMember<Digest>>& newList, ExceptionState& exceptionState)
 {
-    pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList);
+    std::pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList);
     ResultMap& oldMap = resultMaps.first;
     ResultMap& newMap = resultMaps.second;
 
diff --git a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.h b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.h
index c58ecde..899743b 100644
--- a/third_party/WebKit/Source/core/inspector/DOMPatchSupport.h
+++ b/third_party/WebKit/Source/core/inspector/DOMPatchSupport.h
@@ -69,7 +69,7 @@
         WillBeHeapVector<OwnPtrWillBeMember<Digest>> m_children;
     };
 
-    typedef WillBeHeapVector<pair<RawPtrWillBeMember<Digest>, size_t>> ResultMap;
+    typedef WillBeHeapVector<std::pair<RawPtrWillBeMember<Digest>, size_t>> ResultMap;
     typedef WillBeHeapHashMap<String, RawPtrWillBeMember<Digest>> UnusedNodesMap;
 
     bool innerPatchNode(Digest* oldNode, Digest* newNode, ExceptionState&);
diff --git a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.cpp b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.cpp
index 662900d8..f5a5534 100644
--- a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.cpp
+++ b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.cpp
@@ -31,10 +31,11 @@
 #include "config.h"
 #include "core/inspector/InjectedScriptHost.h"
 
+#include "bindings/core/v8/ScriptValue.h"
 #include "core/inspector/EventListenerInfo.h"
 #include "core/inspector/InspectorConsoleAgent.h"
-#include "core/inspector/V8DebuggerAgent.h"
 #include "core/inspector/v8/V8Debugger.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 #include "platform/JSONValues.h"
 
 #include "wtf/RefPtr.h"
@@ -63,7 +64,6 @@
 DEFINE_TRACE(InjectedScriptHost)
 {
     visitor->trace(m_consoleAgent);
-    visitor->trace(m_debuggerAgent);
     visitor->trace(m_inspectedObjects);
     visitor->trace(m_defaultInspectableObject);
 }
diff --git a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
index 66a5ec6..79b4a007 100644
--- a/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
+++ b/third_party/WebKit/Source/core/inspector/InjectedScriptHost.h
@@ -109,7 +109,7 @@
     InjectedScriptHost();
 
     RawPtrWillBeMember<InspectorConsoleAgent> m_consoleAgent;
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgent* m_debuggerAgent;
     OwnPtr<InspectCallback> m_inspectCallback;
     V8Debugger* m_debugger;
     WillBeHeapVector<OwnPtrWillBeMember<InspectableObject>> m_inspectedObjects;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index a8e86860..ae0346a 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -78,6 +78,14 @@
 
 namespace {
 
+int s_frontendOperationCounter = 0;
+
+class FrontendOperationScope {
+public:
+    FrontendOperationScope() { ++s_frontendOperationCounter; }
+    ~FrontendOperationScope() { --s_frontendOperationCounter; }
+};
+
 using namespace blink;
 
 String createShorthandValue(Document* document, const String& shorthand, const String& oldText, const String& longhand, const String& newValue)
@@ -864,6 +872,7 @@
 
 void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
 {
+    FrontendOperationScope scope;
     InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
     if (!inspectorStyleSheet) {
         *errorString = "Style sheet with id " + styleSheetId + " not found";
@@ -918,6 +927,7 @@
 
 void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& selector, RefPtr<TypeBuilder::CSS::SelectorList>& result)
 {
+    FrontendOperationScope scope;
     InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
     if (!inspectorStyleSheet) {
         *errorString = "Stylesheet not found";
@@ -944,6 +954,7 @@
 
 void InspectorCSSAgent::setStyleText(ErrorString* errorString, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
 {
+    FrontendOperationScope scope;
     InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
     if (!inspectorStyleSheet) {
         *errorString = "Stylesheet not found";
@@ -981,6 +992,7 @@
 
 void InspectorCSSAgent::setMediaText(ErrorString* errorString, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<TypeBuilder::CSS::CSSMedia>& result)
 {
+    FrontendOperationScope scope;
     InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
     if (!inspectorStyleSheet) {
         *errorString = "Stylesheet not found";
@@ -1030,6 +1042,7 @@
 
 void InspectorCSSAgent::addRule(ErrorString* errorString, const String& styleSheetId, const String& ruleText, const RefPtr<JSONObject>& location, RefPtr<TypeBuilder::CSS::CSSRule>& result)
 {
+    FrontendOperationScope scope;
     InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
     if (!inspectorStyleSheet)
         return;
@@ -1522,6 +1535,8 @@
 
 void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheetBase* styleSheet)
 {
+    if (s_frontendOperationCounter)
+        return;
     flushPendingProtocolNotifications();
     frontend()->styleSheetChanged(styleSheet->id());
 }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.cpp
index ca11695..f0aa028 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.cpp
@@ -35,8 +35,8 @@
 #include "core/inspector/InstrumentingAgents.h"
 #include "core/inspector/ScriptArguments.h"
 #include "core/inspector/ScriptAsyncCallStack.h"
-#include "core/inspector/V8DebuggerAgent.h"
 #include "core/inspector/v8/V8Debugger.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 #include "wtf/text/WTFString.h"
 
 namespace blink {
@@ -63,7 +63,6 @@
 DEFINE_TRACE(InspectorConsoleAgent)
 {
     visitor->trace(m_injectedScriptManager);
-    visitor->trace(m_debuggerAgent);
     InspectorBaseAgent::trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.h b/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.h
index 9756e56..3f2a42b 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorConsoleAgent.h
@@ -66,7 +66,7 @@
     virtual void disableStackCapturingIfNeeded() = 0;
 
     RawPtrWillBeMember<InjectedScriptManager> m_injectedScriptManager;
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgent* m_debuggerAgent;
     bool m_enabled;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 6863c2a9..38f8be7 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -2071,6 +2071,8 @@
     if (!node)
         return;
     m_injectedScriptManager->injectedScriptHost()->addInspectedObject(adoptPtrWillBeNoop(new InspectableNode(node)));
+    if (m_client)
+        m_client->setInspectedNode(node);
 }
 
 void InspectorDOMAgent::getRelayoutBoundary(ErrorString* errorString, int nodeId, int* relayoutBoundaryNodeId)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
index 354eeefa..a5c2db37 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -95,6 +95,7 @@
         virtual void highlightNode(Node*, const InspectorHighlightConfig&, bool omitTooltip) { }
         virtual void highlightQuad(PassOwnPtr<FloatQuad>, const InspectorHighlightConfig&) { }
         virtual void setInspectMode(SearchMode searchMode, PassOwnPtr<InspectorHighlightConfig>) { }
+        virtual void setInspectedNode(Node*) { }
     };
 
     static PassOwnPtrWillBeRawPtr<InspectorDOMAgent> create(InspectorPageAgent* pageAgent, InjectedScriptManager* injectedScriptManager, Client* client)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
index 4dab7ea..6cce902 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -46,7 +46,7 @@
 #include "core/inspector/InspectorState.h"
 #include "core/inspector/InstrumentingAgents.h"
 #include "core/inspector/RemoteObjectId.h"
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 #include "platform/JSONValues.h"
 
 namespace {
@@ -113,7 +113,6 @@
 {
     visitor->trace(m_injectedScriptManager);
     visitor->trace(m_domAgent);
-    visitor->trace(m_debuggerAgent);
 #if ENABLE(OILPAN)
     visitor->trace(m_domBreakpoints);
 #endif
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
index 656ad74..7f5ab8da 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
@@ -123,7 +123,7 @@
 
     RawPtrWillBeMember<InjectedScriptManager> m_injectedScriptManager;
     RawPtrWillBeMember<InspectorDOMAgent> m_domAgent;
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgent* m_debuggerAgent;
     WillBeHeapHashMap<RawPtrWillBeMember<Node>, uint32_t> m_domBreakpoints;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp
index 840b647..81eb1df 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.cpp
@@ -31,6 +31,7 @@
 #include "core/inspector/InspectorDebuggerAgent.h"
 
 #include "bindings/core/v8/V8Binding.h"
+#include "core/inspector/AsyncCallTracker.h"
 #include "core/inspector/ScriptAsyncCallStack.h"
 #include "core/inspector/v8/V8Debugger.h"
 #include "platform/ScriptForbiddenScope.h"
@@ -39,7 +40,7 @@
 
 InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, int contextGroupId)
     : InspectorBaseAgent<InspectorDebuggerAgent, InspectorFrontend::Debugger>("Debugger")
-    , m_v8DebuggerAgent(adoptPtrWillBeNoop(new V8DebuggerAgent(injectedScriptManager, debugger, this, contextGroupId)))
+    , m_v8DebuggerAgent(V8DebuggerAgent::create(injectedScriptManager, debugger, this, contextGroupId))
 {
 }
 
@@ -52,7 +53,7 @@
 
 DEFINE_TRACE(InspectorDebuggerAgent)
 {
-    visitor->trace(m_v8DebuggerAgent);
+    visitor->trace(m_asyncCallTracker);
     InspectorBaseAgent<InspectorDebuggerAgent, InspectorFrontend::Debugger>::trace(visitor);
 }
 
@@ -253,6 +254,16 @@
     m_instrumentingAgents->setInspectorDebuggerAgent(nullptr);
 }
 
+void InspectorDebuggerAgent::asyncCallTrackingStateChanged(bool tracking)
+{
+    m_asyncCallTracker->asyncCallTrackingStateChanged(tracking);
+}
+
+void InspectorDebuggerAgent::resetAsyncOperations()
+{
+    m_asyncCallTracker->resetAsyncOperations();
+}
+
 bool InspectorDebuggerAgent::isPaused()
 {
     return m_v8DebuggerAgent->isPaused();
@@ -287,6 +298,7 @@
 void InspectorDebuggerAgent::init()
 {
     m_v8DebuggerAgent->setInspectorState(m_state);
+    m_asyncCallTracker = adoptPtrWillBeNoop(new AsyncCallTracker(m_v8DebuggerAgent.get(), m_instrumentingAgents.get()));
 }
 
 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h
index a85db23..f15b4f1f 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDebuggerAgent.h
@@ -32,7 +32,7 @@
 
 #include "core/CoreExport.h"
 #include "core/inspector/InspectorBaseAgent.h"
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
 
 namespace blink {
 
@@ -86,6 +86,8 @@
     // V8DebuggerAgent::Client implementation.
     void debuggerAgentEnabled() override;
     void debuggerAgentDisabled() override;
+    void asyncCallTrackingStateChanged(bool tracking) override;
+    void resetAsyncOperations() override;
 
     // Called by InspectorInstrumentation.
     bool isPaused();
@@ -105,7 +107,8 @@
 protected:
     InspectorDebuggerAgent(InjectedScriptManager*, V8Debugger*, int contextGroupId);
 
-    OwnPtrWillBeMember<V8DebuggerAgent> m_v8DebuggerAgent;
+    OwnPtr<V8DebuggerAgent> m_v8DebuggerAgent;
+    OwnPtrWillBeMember<AsyncCallTracker> m_asyncCallTracker;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.cpp
index a04dff7..6b0a59c 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.cpp
@@ -69,7 +69,7 @@
 void InspectorInspectorAgent::enable(ErrorString*)
 {
     m_state->setBoolean(InspectorAgentState::inspectorAgentEnabled, true);
-    for (Vector<pair<long, String>>::iterator it = m_pendingEvaluateTestCommands.begin(); frontend() && it != m_pendingEvaluateTestCommands.end(); ++it)
+    for (Vector<std::pair<long, String>>::iterator it = m_pendingEvaluateTestCommands.begin(); frontend() && it != m_pendingEvaluateTestCommands.end(); ++it)
         frontend()->evaluateForTestInFrontend(static_cast<int>((*it).first), (*it).second);
     m_pendingEvaluateTestCommands.clear();
 }
@@ -104,7 +104,7 @@
         frontend()->evaluateForTestInFrontend(static_cast<int>(callId), script);
         frontend()->flush();
     } else {
-        m_pendingEvaluateTestCommands.append(pair<long, String>(callId, script));
+        m_pendingEvaluateTestCommands.append(std::pair<long, String>(callId, script));
     }
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.h b/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.h
index eb094a0..7ada22d4 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorInspectorAgent.h
@@ -73,7 +73,7 @@
 
     RawPtrWillBeMember<InjectedScriptManager> m_injectedScriptManager;
 
-    Vector<pair<long, String> > m_pendingEvaluateTestCommands;
+    Vector<std::pair<long, String>> m_pendingEvaluateTestCommands;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorOverlayPage.html b/third_party/WebKit/Source/core/inspector/InspectorOverlayPage.html
index 513ed89d..6ac39bf8 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorOverlayPage.html
+++ b/third_party/WebKit/Source/core/inspector/InspectorOverlayPage.html
@@ -158,22 +158,20 @@
     display: none !important;
 }
 
-#element-tooltip,
-#element-tooltip-arrow {
+.tooltip-content,
+.material-tooltip-arrow {
     position: absolute;
     z-index: 10;
     -webkit-user-select: none;
 }
 
-#element-tooltip {
+.tooltip-content {
     background-color: #333740;
     font-size: 11px;
     line-height: 14px;
     padding: 5px 8px;
     border-radius: 3px;
     color: white;
-    display: flex;
-    align-content: stretch;
     box-sizing: border-box;
     max-width: calc(100% - 4px);
     border: 1px solid hsla(0, 0%, 100%, 0.3);
@@ -183,7 +181,12 @@
     text-rendering: optimizeLegibility;
 }
 
-#element-tooltip-arrow {
+.element-info {
+    display: flex;
+    align-content: stretch;
+}
+
+.material-tooltip-arrow {
     border: solid;
     border-color: #333740 transparent;
     border-width: 0 8px 8px 8px;
@@ -191,17 +194,17 @@
     margin-top: 1px;
 }
 
-#element-tooltip-arrow.tooltip-arrow-top {
+.material-tooltip-arrow.tooltip-arrow-top {
     border-width: 8px 8px 0 8px;
     margin-top: -1px;
 }
 
-#element-description {
+.element-description {
     flex: 1 1;
     word-wrap: break-word;
 }
 
-#dimensions {
+.dimensions {
     border-left: 1px solid hsl(0, 0%, 50%);
     padding-left: 7px;
     margin-left: 7px;
@@ -213,26 +216,33 @@
     color: hsl(0, 0%, 85%);
 }
 
-#material-node-width {
+.material-node-width {
     margin-right: 2px;
 }
 
-#material-node-height {
+.material-node-height {
     margin-left: 2px;
 }
 
-#material-tag-name {
+.material-tag-name {
     color: hsl(304, 77%, 70%);
 }
 
-#material-node-id {
+.material-node-id {
     color: hsl(27, 100%, 70%);
 }
 
-#material-class-name {
+.material-class-name {
     color: hsl(202,92%,77%);
 }
 
+.layout-editor-media-tooltip {
+    color: hsl(0, 0%, 85%);
+}
+
+.layout-editor-selector-tooltip {
+    color: hsl(202,92%,77%);
+}
 
 </style>
 <script>
@@ -434,7 +444,8 @@
     window._controlsVisible = false;
     document.querySelector(".controls-line").style.visibility = "hidden";
     document.getElementById("element-title").style.visibility = "hidden";
-    document.getElementById("tooltip-container").classList.add("hidden");
+    document.getElementById("tooltip-container").removeChildren();
+
     document.body.classList.remove("dimmed");
 
     window._gridPainted = false;
@@ -448,10 +459,7 @@
 {
     document.getElementById("tag-name").textContent = elementInfo.tagName;
     document.getElementById("node-id").textContent = elementInfo.idValue ? "#" + elementInfo.idValue : "";
-    var className = elementInfo.className;
-    if (className && className.length > 50)
-       className = className.substring(0, 50) + "\u2026";
-    document.getElementById("class-name").textContent = className || "";
+    document.getElementById("class-name").textContent = (elementInfo.className || "").trimEnd(50);
     document.getElementById("node-width").textContent = elementInfo.nodeWidth;
     document.getElementById("node-height").textContent = elementInfo.nodeHeight;
     var elementTitle = document.getElementById("element-title");
@@ -517,27 +525,41 @@
     elementTitle.style.left = (boxX + 3) + "px";
 }
 
+function _createElementDescription(elementInfo)
+{
+    var elementInfoElement = createElement("div", "element-info");
+    var descriptionElement = elementInfoElement.createChild("div", "element-description monospace");
+    var tagNameElement = descriptionElement.createChild("b").createChild("span", "material-tag-name");
+    tagNameElement.textContent = elementInfo.tagName;
+    var nodeIdElement = descriptionElement.createChild("span", "material-node-id");
+    nodeIdElement.textContent = elementInfo.idValue ? "#" + elementInfo.idValue : "";
+    nodeIdElement.classList.toggle("hidden", !elementInfo.idValue);
+
+    var classNameElement = descriptionElement.createChild("span", "material-class-name");
+    classNameElement.textContent = (elementInfo.className || "").trim(50);
+    classNameElement.classList.toggle("hidden", !elementInfo.className);
+    var dimensionsElement = elementInfoElement.createChild("div", "dimensions");
+    dimensionsElement.createChild("span", "material-node-width").textContent = Math.round(elementInfo.nodeWidth * 100) / 100;
+    dimensionsElement.createTextChild("\u00d7");
+    dimensionsElement.createChild("span", "material-node-height").textContent = Math.round(elementInfo.nodeHeight * 100) / 100;
+    return elementInfoElement;
+}
+
 function _drawMaterialElementTitle(elementInfo, bounds)
 {
-    // Reset position before measuring to ensure line-wraps are consistent.
-    var elementTitle = document.getElementById("element-tooltip");
-    elementTitle.style.top = "0";
-    elementTitle.style.left = "0";
-    document.getElementById("tooltip-container").classList.remove("hidden");
+    var tooltipContainer = document.getElementById("tooltip-container");
+    tooltipContainer.removeChildren();
+    _createMaterialTooltip(tooltipContainer, bounds, _createElementDescription(elementInfo), true);
+}
 
-    document.getElementById("material-tag-name").textContent = elementInfo.tagName;
-    document.getElementById("material-node-id").textContent = elementInfo.idValue ? "#" + elementInfo.idValue : "";
-    document.getElementById("material-node-id").classList.toggle("hidden", !elementInfo.idValue);
-    var className = elementInfo.className;
-    if (className && className.length > 50)
-       className = className.substring(0, 50) + "\u2026";
-    document.getElementById("material-class-name").textContent = className || "";
-    document.getElementById("material-class-name").classList.toggle("hidden", !className);
-    document.getElementById("material-node-width").textContent = Math.round(elementInfo.nodeWidth* 100) / 100;
-    document.getElementById("material-node-height").textContent = Math.round(elementInfo.nodeHeight * 100) / 100;
+function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow)
+{
+    var tooltipContainer = parentElement.createChild("div");
+    var tooltipContent = tooltipContainer.createChild("div", "tooltip-content");
+    tooltipContent.appendChild(contentElement);
 
-    var titleWidth = elementTitle.offsetWidth;
-    var titleHeight = elementTitle.offsetHeight;
+    var titleWidth = tooltipContent.offsetWidth;
+    var titleHeight = tooltipContent.offsetHeight;
     var arrowRadius = 8;
     var pageMargin = 2;
 
@@ -553,10 +575,12 @@
         boxY = canvasHeight - arrowRadius - titleHeight;
     }
 
-    elementTitle.style.top = boxY + "px";
-    elementTitle.style.left = boxX + "px";
+    tooltipContent.style.top = boxY + "px";
+    tooltipContent.style.left = boxX + "px";
+    if (!withArrow)
+        return;
 
-    var tooltipArrow = document.getElementById("element-tooltip-arrow");
+    var tooltipArrow = tooltipContainer.createChild("div", "material-tooltip-arrow");
     // Center arrow if possible. Otherwise, try the bounds of the element.
     var arrowX = bounds.minX + (bounds.maxX - bounds.minX) / 2 - arrowRadius;
     var tooltipBorderRadius = 2;
@@ -681,11 +705,8 @@
     return path;
 }
 
-function drawHighlight(highlight, context)
+function emptyBounds()
 {
-    context = context || window.context;
-    context.save();
-
     var bounds = {
         minX: Number.MAX_VALUE,
         minY: Number.MAX_VALUE,
@@ -696,6 +717,15 @@
         topmostYForX: {},
         bottommostYForX: {}
     };
+    return bounds;
+}
+
+function drawHighlight(highlight, context)
+{
+    context = context || window.context;
+    context.save();
+
+    var bounds = emptyBounds();
 
     var areasDescription = new Map();
     for (var paths = highlight.paths.slice(); paths.length;) {
@@ -727,7 +757,7 @@
     }
     context.restore();
 
-    return areasDescription;
+    return { areasDescription: areasDescription, bounds: bounds };
 }
 
 function setPlatform(platform)
@@ -744,9 +774,7 @@
 
 function log(text)
 {
-    var logEntry = document.createElement("div");
-    logEntry.textContent = text;
-    document.getElementById("log").appendChild(logEntry);
+    document.getElementById("log").createChild("div").textContent = text;
 }
 
 function onResumeClick()
@@ -806,8 +834,8 @@
 
     this._anchorsByType = new Map();
     this._hoverableAreas = new Map();
+    this._elementsBounds = emptyBounds();
     this._editorElement = document.getElementById("editor");
-    this._tooltipElement = document.getElementById("selector-tooltip");
     this._matchedNodesCanvas = createCanvas("layout-editor-matched-nodes-canvas");
     mainCanvas.parentElement.insertBefore(this._matchedNodesCanvas, mainCanvas);
 
@@ -821,13 +849,18 @@
     {
         this._anchorsByType.clear();
         this._hoverableAreas.clear();
+        this._elementsBounds = emptyBounds();
 
         resetCanvas(this._matchedNodesCanvas);
         this._resetLabelCanvas();
 
         this._editorElement.style.visibility = "hidden";
         this._editorElement.textContent = "";
-        this._tooltipElement.style.visibility = "hidden";
+
+        if (this._selectorTooltipElement) {
+            this._selectorTooltipElement.remove();
+            delete this._selectorTooltipElement;
+        }
 
         document.removeEventListener("mousedown", this._boundConsumeEvent);
         document.removeEventListener("mousemove", this._boundMouseMove);
@@ -839,7 +872,9 @@
 
     setState: function(info)
     {
-        this._hoverableAreas = drawHighlight(info.nodeHighlight, this._mainContext);
+        var highlightDescription = drawHighlight(info.nodeHighlight, this._mainContext);
+        this._hoverableAreas = highlightDescription.areasDescription;
+        this._elementsBounds = highlightDescription.bounds;
 
         this._editorElement.style.visibility = "visible";
         var anchors = info.anchors;
@@ -868,13 +903,19 @@
 
     setSelector: function(selectorInfo)
     {
-        this._tooltipElement.style.visibility = "visible";
-        this._tooltipElement.style.left = "100px";
-        this._tooltipElement.style.top = "100px";
-        var medias = selectorInfo.medias ? selectorInfo.medias.map(function (media) {return "@media " + media + ""}) : "";
-        this._tooltipElement.textContent = (medias ? medias.join(", ") + " { " : "") + selectorInfo.selector + ( medias ? " } " : "");
-        this._tooltipElement.style.backgroundColor = "#eee";
+        if (this._selectorTooltipElement)
+            this._selectorTooltipElement.remove();
 
+        var containerElement = createElement("div");
+
+        for (var i = (selectorInfo.medias || []).length - 1; i >= 0; --i)
+            containerElement.createChild("div", "layout-editor-media-tooltip").textContent = ("@media " + selectorInfo.medias[i]).trim(50);
+
+        var selectorElement = containerElement.createChild("div", "layout-editor-selector-tooltip");
+        selectorElement.textContent = selectorInfo.selector.trimEnd(50);
+
+        this._selectorTooltipElement = document.body.insertBefore(createElement("div"), this._editorElement);
+        _createMaterialTooltip(this._selectorTooltipElement, this._elementsBounds, containerElement);
         resetCanvas(this._matchedNodesCanvas);
 
         if (!selectorInfo.nodes)
@@ -896,8 +937,7 @@
         this._mainContext.fill();
         this._mainContext.restore();
 
-        var anchorElement = document.createElement("div");
-        anchorElement.className = "editor-anchor";
+        var anchorElement = createElement("div", "editor-anchor");
         anchorElement.style.left = anchorInfo.x - handleWidth + "px";
         anchorElement.style.top = anchorInfo.y - handleWidth + "px";
         if (anchorInfo.propertyValue.mutable)
@@ -1171,9 +1211,8 @@
 
 function createCanvas(id)
 {
-    var canvas = document.createElement("canvas");
+    var canvas = createElement("canvas", "fill");
     canvas.id = id;
-    canvas.className = "fill";
     resetCanvas(canvas);
     return canvas;
 }
@@ -1183,6 +1222,41 @@
     return v1.x * v2.x + v1.y * v2.y;
 }
 
+Element.prototype.createChild = function(tagName, className)
+{
+    var element = createElement(tagName, className);
+    this.appendChild(element);
+    return element;
+}
+
+Element.prototype.createTextChild = function(text)
+{
+    var element = document.createTextNode(text);
+    this.appendChild(element);
+    return element;
+}
+
+Element.prototype.removeChildren = function()
+{
+    if (this.firstChild)
+        this.textContent = "";
+}
+
+function createElement(tagName, className)
+{
+    var element = document.createElement(tagName);
+    if (className)
+        element.className = className;
+    return element;
+}
+
+String.prototype.trimEnd = function(maxLength)
+{
+    if (this.length <= maxLength)
+        return String(this);
+    return this.substr(0, maxLength - 1) + "\u2026";
+}
+
 window.addEventListener("DOMContentLoaded", onLoaded);
 document.addEventListener("keydown", onDocumentKeyDown);
 </script>
@@ -1199,14 +1273,7 @@
   <span id="tag-name"></span><span id="node-id"></span><span id="class-name"></span>
   <span id="node-width"></span><span class="px">px</span><span class="px"> &#xD7; </span><span id="node-height"></span><span class="px">px</span>
 </div>
-<div id="tooltip-container" class="hidden">
-    <div id="element-tooltip">
-      <div id="element-description" class="monospace"><b><span id="material-tag-name"></span></b><span id="material-node-id"></span><span id="material-class-name"></span></div>
-      <div id="dimensions"><span id="material-node-width"></span>&#xD7;<span id="material-node-height"></span></div>
-    </div>
-    <div id="element-tooltip-arrow"></div>
-</div>
+<div id="tooltip-container"></div>
 <div id="editor" class="fill"></div>
-<div id="selector-tooltip"></div>
 <div id="log"></div>
 </html>
diff --git a/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp b/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
index 9608da9..9c4abd5 100644
--- a/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
+++ b/third_party/WebKit/Source/core/inspector/LayoutEditor.cpp
@@ -139,14 +139,6 @@
     return number.left(number.length() - removeCount);
 }
 
-float toValidValue(CSSPropertyID propertyId, float newValue)
-{
-    if (CSSPropertyPaddingBottom <= propertyId && propertyId <= CSSPropertyPaddingTop)
-        return newValue >= 0 ? newValue : 0;
-
-    return newValue;
-}
-
 InspectorHighlightConfig affectedNodesHighlightConfig()
 {
     // TODO: find a better color
@@ -336,7 +328,8 @@
 void LayoutEditor::overlayPropertyChanged(float cssDelta)
 {
     if (m_changingProperty && m_factor) {
-        float newValue = toValidValue(m_changingProperty, cssDelta / m_factor + m_propertyInitialValue);
+        float newValue = cssDelta / m_factor + m_propertyInitialValue;
+        newValue = newValue >= 0 ? newValue : 0;
         m_isDirty |= setCSSPropertyValueInCurrentRule(truncateZeroes(String::format("%.2f", newValue)) + CSSPrimitiveValue::unitTypeToString(m_valueUnitType));
     }
 }
@@ -396,23 +389,13 @@
     if (!ownerDocument->isActive() || currentStyleIsInline())
         return object.release();
 
-    bool hasSameSelectors = false;
-    for (unsigned i = 0; i < m_matchedRules->length(); i++) {
-        if (i != m_currentRuleIndex && toCSSStyleRule(m_matchedRules->item(i))->selectorText() == currentSelectorText) {
-            hasSameSelectors = true;
-            break;
-        }
-    }
+    Vector<String> medias;
+    buildMediaListChain(m_matchedRules->item(m_currentRuleIndex), medias);
+    RefPtr<JSONArray> mediasJSONArray = JSONArray::create();
+    for (size_t i = 0; i < medias.size(); ++i)
+        mediasJSONArray->pushString(medias[i]);
 
-    if (hasSameSelectors) {
-        Vector<String> medias;
-        buildMediaListChain(m_matchedRules->item(m_currentRuleIndex), medias);
-        RefPtr<JSONArray> mediasJSONArray = JSONArray::create();
-        for (size_t i = 0; i < medias.size(); ++i)
-            mediasJSONArray->pushString(medias[i]);
-
-        object->setArray("medias", mediasJSONArray.release());
-    }
+    object->setArray("medias", mediasJSONArray.release());
 
     TrackExceptionState exceptionState;
     RefPtrWillBeRawPtr<StaticElementList> elements = ownerDocument->querySelectorAll(AtomicString(currentSelectorText), exceptionState);
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
index ce80c77..528ad9155 100644
--- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
@@ -32,35 +32,16 @@
 #include "core/inspector/MainThreadDebugger.h"
 
 #include "bindings/core/v8/DOMWrapperWorld.h"
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "bindings/core/v8/V8ScriptRunner.h"
-#include "bindings/core/v8/WindowProxy.h"
-#include "core/frame/FrameConsole.h"
-#include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/UseCounter.h"
-#include "core/inspector/InspectorInstrumentation.h"
 #include "core/inspector/InspectorTaskRunner.h"
-#include "core/inspector/InspectorTraceEvents.h"
-#include "core/inspector/v8/V8DebuggerListener.h"
-#include "core/page/Page.h"
 #include "wtf/OwnPtr.h"
 #include "wtf/PassOwnPtr.h"
-#include "wtf/StdLibExtras.h"
-#include "wtf/TemporaryChange.h"
 #include "wtf/ThreadingPrimitives.h"
-#include "wtf/text/StringBuilder.h"
 
 namespace blink {
 
 namespace {
 
-LocalFrame* retrieveFrameWithGlobalObjectCheck(v8::Local<v8::Context> context)
-{
-    return toLocalFrame(toFrameIfNotDetached(context));
-}
-
 int frameId(LocalFrame* frame)
 {
     ASSERT(frame);
@@ -121,13 +102,13 @@
         s_instance->m_taskRunner->interruptAndRun(task);
 }
 
-void MainThreadDebugger::runMessageLoopOnPause(v8::Local<v8::Context> context)
+void MainThreadDebugger::runMessageLoopOnPause(int contextGroupId)
 {
-    LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(context);
+    LocalFrame* pausedFrame = WeakIdentifierMap<LocalFrame>::lookup(contextGroupId);
     // Do not pause in Context of detached frame.
-    if (!frame)
+    if (!pausedFrame)
         return;
-    LocalFrame* pausedFrame = frame->localFrameRoot();
+    ASSERT(pausedFrame == pausedFrame->localFrameRoot());
     // Wait for continue or step command.
     m_clientMessageLoop->run(pausedFrame);
 }
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
index 203ad6d..1cdbbcd2 100644
--- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
+++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
@@ -73,13 +73,11 @@
 private:
     MainThreadDebugger(PassOwnPtr<ClientMessageLoop>, v8::Isolate*);
 
-    void runMessageLoopOnPause(v8::Local<v8::Context>) override;
+    void runMessageLoopOnPause(int contextGroupId) override;
     void quitMessageLoopOnPause() override;
 
     static WTF::Mutex& creationMutex();
 
-    using ListenersMap = HashMap<int, V8DebuggerListener*>;
-    ListenersMap m_listenersMap;
     OwnPtr<ClientMessageLoop> m_clientMessageLoop;
     OwnPtr<InspectorTaskRunner> m_taskRunner;
 
diff --git a/third_party/WebKit/Source/core/inspector/PromiseTracker.cpp b/third_party/WebKit/Source/core/inspector/PromiseTracker.cpp
index eb7a4a0..6a5532f 100644
--- a/third_party/WebKit/Source/core/inspector/PromiseTracker.cpp
+++ b/third_party/WebKit/Source/core/inspector/PromiseTracker.cpp
@@ -23,11 +23,7 @@
     WTF_MAKE_NONCOPYABLE(PromiseWeakCallbackData);
 public:
     PromiseWeakCallbackData(PromiseTracker* tracker, int id)
-#if ENABLE(OILPAN)
-        : m_tracker(tracker)
-#else
         : m_tracker(tracker->m_weakPtrFactory.createWeakPtr())
-#endif
         , m_id(id)
     {
     }
@@ -40,7 +36,7 @@
         m_tracker->m_listener->didUpdatePromise(InspectorFrontend::Debugger::EventType::Gc, promiseDetails.release());
     }
 
-    WeakPtrWillBeWeakPersistent<PromiseTracker> m_tracker;
+    WeakPtr<PromiseTracker> m_tracker;
     int m_id;
 };
 
@@ -77,9 +73,7 @@
     , m_captureStacks(false)
     , m_listener(listener)
     , m_isolate(isolate)
-#if !ENABLE(OILPAN)
     , m_weakPtrFactory(this)
-#endif
     , m_idToPromise(isolate)
 {
     clear();
@@ -89,13 +83,6 @@
 {
 }
 
-DEFINE_TRACE(PromiseTracker)
-{
-#if ENABLE(OILPAN)
-    visitor->trace(m_listener);
-#endif
-}
-
 void PromiseTracker::setEnabled(bool enabled, bool captureStacks)
 {
     m_isEnabled = enabled;
diff --git a/third_party/WebKit/Source/core/inspector/PromiseTracker.h b/third_party/WebKit/Source/core/inspector/PromiseTracker.h
index 6b8d5c51..61681e3 100644
--- a/third_party/WebKit/Source/core/inspector/PromiseTracker.h
+++ b/third_party/WebKit/Source/core/inspector/PromiseTracker.h
@@ -9,11 +9,12 @@
 #include "core/CoreExport.h"
 #include "core/InspectorFrontend.h"
 #include "core/InspectorTypeBuilder.h"
-#include "platform/heap/Handle.h"
 #include "wtf/HashMap.h"
 #include "wtf/Noncopyable.h"
+#include "wtf/PassOwnPtr.h"
 #include "wtf/RefPtr.h"
 #include "wtf/Vector.h"
+#include "wtf/WeakPtr.h"
 #include <v8.h>
 
 namespace blink {
@@ -21,19 +22,19 @@
 class ScriptState;
 class ScriptValue;
 
-class PromiseTracker final : public NoBaseWillBeGarbageCollectedFinalized<PromiseTracker> {
+class PromiseTracker final {
     WTF_MAKE_NONCOPYABLE(PromiseTracker);
-    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(PromiseTracker);
+    WTF_MAKE_FAST_ALLOCATED(PromiseTracker);
 public:
-    class CORE_EXPORT Listener : public WillBeGarbageCollectedMixin {
+    class CORE_EXPORT Listener {
     public:
         virtual ~Listener() { }
         virtual void didUpdatePromise(InspectorFrontend::Debugger::EventType::Enum, PassRefPtr<TypeBuilder::Debugger::PromiseDetails>) = 0;
     };
 
-    static PassOwnPtrWillBeRawPtr<PromiseTracker> create(Listener* listener, v8::Isolate* isolate)
+    static PassOwnPtr<PromiseTracker> create(Listener* listener, v8::Isolate* isolate)
     {
-        return adoptPtrWillBeNoop(new PromiseTracker(listener, isolate));
+        return adoptPtr(new PromiseTracker(listener, isolate));
     }
 
     ~PromiseTracker();
@@ -44,8 +45,6 @@
     void didReceiveV8PromiseEvent(ScriptState*, v8::Local<v8::Object> promise, v8::Local<v8::Value> parentPromise, int status);
     ScriptValue promiseById(int promiseId);
 
-    DECLARE_TRACE();
-
 private:
     PromiseTracker(Listener*, v8::Isolate*);
 
@@ -55,14 +54,12 @@
     int m_circularSequentialId;
     bool m_isEnabled;
     bool m_captureStacks;
-    RawPtrWillBeMember<Listener> m_listener;
+    Listener* m_listener;
 
     v8::Isolate* m_isolate;
     v8::Persistent<v8::NativeWeakMap> m_promiseToId;
 
-#if !ENABLE(OILPAN)
     WeakPtrFactory<PromiseTracker> m_weakPtrFactory;
-#endif
 
     class PromiseWeakCallbackData;
     class IdToPromiseMapTraits : public V8GlobalValueMapTraits<int, v8::Object, v8::kWeakWithParameter> {
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
index 200bc48..f6c31aa 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -34,7 +34,6 @@
 
 #include "core/InspectorBackendDispatcher.h"
 #include "core/InspectorFrontend.h"
-#include "core/inspector/AsyncCallTracker.h"
 #include "core/inspector/InjectedScriptHost.h"
 #include "core/inspector/InjectedScriptManager.h"
 #include "core/inspector/InspectorConsoleAgent.h"
@@ -135,7 +134,6 @@
     OwnPtrWillBeRawPtr<WorkerDebuggerAgent> workerDebuggerAgent = WorkerDebuggerAgent::create(m_workerThreadDebugger.get(), workerGlobalScope, m_injectedScriptManager.get());
     m_workerDebuggerAgent = workerDebuggerAgent.get();
     m_agents.append(workerDebuggerAgent.release());
-    m_asyncCallTracker = adoptPtrWillBeNoop(new AsyncCallTracker(m_workerDebuggerAgent->v8DebuggerAgent(), m_instrumentingAgents.get()));
 
     v8::Isolate* isolate = workerGlobalScope->thread()->isolate();
     m_agents.append(InspectorProfilerAgent::create(isolate, m_injectedScriptManager.get(), 0));
@@ -216,7 +214,8 @@
 
 void WorkerInspectorController::resumeStartup()
 {
-    m_paused = false;
+    if (m_paused)
+        m_workerThreadDebugger->quitMessageLoopOnPause();
 }
 
 bool WorkerInspectorController::isRunRequired()
@@ -234,13 +233,8 @@
 void WorkerInspectorController::pauseOnStart()
 {
     m_paused = true;
-    WorkerThread::TaskQueueResult result;
-    m_workerGlobalScope->thread()->willRunDebuggerTasks();
-    do {
-        result = m_workerGlobalScope->thread()->runDebuggerTask();
-    // Keep waiting until execution is resumed.
-    } while (result == WorkerThread::TaskReceived && m_paused);
-    m_workerGlobalScope->thread()->didRunDebuggerTasks();
+    m_workerThreadDebugger->runMessageLoopOnPause(WorkerThreadDebugger::contextGroupId());
+    m_paused = false;
 }
 
 DEFINE_TRACE(WorkerInspectorController)
@@ -252,7 +246,6 @@
     visitor->trace(m_backendDispatcher);
     visitor->trace(m_agents);
     visitor->trace(m_workerDebuggerAgent);
-    visitor->trace(m_asyncCallTracker);
     visitor->trace(m_workerRuntimeAgent);
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
index d117d81..156d0c27 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
@@ -42,7 +42,6 @@
 
 namespace blink {
 
-class AsyncCallTracker;
 class InjectedScriptManager;
 class InspectorBackendDispatcher;
 class InspectorFrontend;
@@ -91,7 +90,6 @@
     OwnPtr<InspectorFrontend> m_frontend;
     RefPtrWillBeMember<InspectorBackendDispatcher> m_backendDispatcher;
     RawPtrWillBeMember<WorkerDebuggerAgent> m_workerDebuggerAgent;
-    OwnPtrWillBeMember<AsyncCallTracker> m_asyncCallTracker;
     RawPtrWillBeMember<WorkerRuntimeAgent> m_workerRuntimeAgent;
     OwnPtr<InspectorTaskRunner> m_inspectorTaskRunner;
     OwnPtr<InspectorTaskRunner::IgnoreInterruptsScope> m_beforeInitlizedScope;
diff --git a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp
index 781628f..3381fcf 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp
@@ -33,7 +33,6 @@
 
 #include "bindings/core/v8/V8ScriptRunner.h"
 #include "core/inspector/WorkerDebuggerAgent.h"
-#include "core/inspector/v8/V8DebuggerListener.h"
 #include "core/workers/WorkerThread.h"
 #include <v8.h>
 
@@ -43,8 +42,8 @@
 
 WorkerThreadDebugger::WorkerThreadDebugger(WorkerThread* workerThread)
     : ScriptDebuggerBase(v8::Isolate::GetCurrent())
-    , m_listener(nullptr)
     , m_workerThread(workerThread)
+    , m_paused(false)
 {
 }
 
@@ -62,20 +61,22 @@
     return workerContextGroupId;
 }
 
-void WorkerThreadDebugger::runMessageLoopOnPause(v8::Local<v8::Context>)
+void WorkerThreadDebugger::runMessageLoopOnPause(int contextGroupId)
 {
+    ASSERT(contextGroupId == workerContextGroupId);
+    m_paused = true;
     WorkerThread::TaskQueueResult result;
     m_workerThread->willRunDebuggerTasks();
     do {
         result = m_workerThread->runDebuggerTask();
     // Keep waiting until execution is resumed.
-    } while (result == WorkerThread::TaskReceived && debugger()->isPaused());
+    } while (result == WorkerThread::TaskReceived && m_paused);
     m_workerThread->didRunDebuggerTasks();
 }
 
 void WorkerThreadDebugger::quitMessageLoopOnPause()
 {
-    // Nothing to do here in case of workers since runMessageLoopOnPause will check for paused state after each debugger command.
+    m_paused = false;
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h
index e0be8e4..f567f44 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h
+++ b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h
@@ -49,13 +49,12 @@
     static void setContextDebugData(v8::Local<v8::Context>);
     static int contextGroupId();
 
-private:
-    V8DebuggerListener* getDebugListenerForContext(v8::Local<v8::Context>);
-    void runMessageLoopOnPause(v8::Local<v8::Context>);
-    void quitMessageLoopOnPause();
+    void runMessageLoopOnPause(int contextGroupId) override;
+    void quitMessageLoopOnPause() override;
 
-    V8DebuggerListener* m_listener;
+private:
     WorkerThread* m_workerThread;
+    bool m_paused;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.cpp b/third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.cpp
similarity index 88%
rename from third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.cpp
rename to third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.cpp
index 8e68a5da..b812eab 100644
--- a/third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.cpp
+++ b/third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "config.h"
-#include "core/inspector/V8AsyncCallTracker.h"
+#include "core/inspector/v8/V8AsyncCallTracker.h"
 
 #include "bindings/core/v8/V8PerContextData.h"
 #include "core/inspector/AsyncOperationMap.h"
@@ -26,7 +26,7 @@
 class V8AsyncCallTracker::V8ContextAsyncOperations final : public NoBaseWillBeGarbageCollectedFinalized<V8AsyncCallTracker::V8ContextAsyncOperations> {
     WTF_MAKE_NONCOPYABLE(V8ContextAsyncOperations);
 public:
-    explicit V8ContextAsyncOperations(V8DebuggerAgent* debuggerAgent)
+    explicit V8ContextAsyncOperations(V8DebuggerAgentImpl* debuggerAgent)
         : m_v8AsyncOperations(debuggerAgent)
     {
     }
@@ -61,26 +61,20 @@
     return builder.toString();
 }
 
-V8AsyncCallTracker::V8AsyncCallTracker(V8DebuggerAgent* debuggerAgent) : m_debuggerAgent(debuggerAgent)
+V8AsyncCallTracker::V8AsyncCallTracker(V8DebuggerAgentImpl* debuggerAgent) : m_debuggerAgent(debuggerAgent)
 {
-    m_debuggerAgent->addAsyncCallTrackingListener(this);
 }
 
 V8AsyncCallTracker::~V8AsyncCallTracker()
 {
     ASSERT(m_contextAsyncOperationMap.isEmpty());
-#if !ENABLE(OILPAN)
-    m_debuggerAgent->removeAsyncCallTrackingListener(this);
-#endif
 }
 
 DEFINE_TRACE(V8AsyncCallTracker)
 {
 #if ENABLE(OILPAN)
     visitor->trace(m_contextAsyncOperationMap);
-    visitor->trace(m_debuggerAgent);
 #endif
-    V8DebuggerAgent::AsyncCallTrackingListener::trace(visitor);
 }
 
 void V8AsyncCallTracker::asyncCallTrackingStateChanged(bool)
@@ -136,7 +130,7 @@
         m_debuggerAgent->traceAsyncCallbackStarting(contextCallChains->m_v8AsyncOperations.get(taskId));
         contextCallChains->m_v8AsyncOperations.remove(taskId);
     } else {
-        m_debuggerAgent->traceAsyncCallbackStarting(V8DebuggerAgent::unknownAsyncOperationId);
+        m_debuggerAgent->traceAsyncCallbackStarting(V8DebuggerAgentImpl::unknownAsyncOperationId);
     }
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.h b/third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.h
similarity index 72%
rename from third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.h
rename to third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.h
index 87832d9..00c32ee 100644
--- a/third_party/WebKit/Source/core/inspector/V8AsyncCallTracker.h
+++ b/third_party/WebKit/Source/core/inspector/v8/V8AsyncCallTracker.h
@@ -6,7 +6,7 @@
 #define V8AsyncCallTracker_h
 
 #include "bindings/core/v8/ScriptState.h"
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerAgentImpl.h"
 #include "platform/heap/Handle.h"
 #include "wtf/Forward.h"
 #include "wtf/HashMap.h"
@@ -16,12 +16,11 @@
 
 class ScriptState;
 
-class V8AsyncCallTracker final : public NoBaseWillBeGarbageCollectedFinalized<V8AsyncCallTracker>, public ScriptState::Observer, public V8DebuggerAgent::AsyncCallTrackingListener {
+class V8AsyncCallTracker final : public NoBaseWillBeGarbageCollectedFinalized<V8AsyncCallTracker>, public ScriptState::Observer {
     WTF_MAKE_NONCOPYABLE(V8AsyncCallTracker);
-    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(V8AsyncCallTracker);
     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(V8AsyncCallTracker);
 public:
-    static PassOwnPtrWillBeRawPtr<V8AsyncCallTracker> create(V8DebuggerAgent* debuggerAgent)
+    static PassOwnPtrWillBeRawPtr<V8AsyncCallTracker> create(V8DebuggerAgentImpl* debuggerAgent)
     {
         return adoptPtrWillBeNoop(new V8AsyncCallTracker(debuggerAgent));
     }
@@ -29,9 +28,8 @@
     ~V8AsyncCallTracker();
     DECLARE_TRACE();
 
-    // V8DebuggerAgent::AsyncCallTrackingListener implementation:
-    void asyncCallTrackingStateChanged(bool tracking) override;
-    void resetAsyncOperations() override;
+    void asyncCallTrackingStateChanged(bool tracking);
+    void resetAsyncOperations();
 
     void didReceiveV8AsyncTaskEvent(ScriptState*, const String& eventType, const String& eventName, int id);
 
@@ -39,14 +37,14 @@
     void willDisposeScriptState(ScriptState*) override;
 
 private:
-    explicit V8AsyncCallTracker(V8DebuggerAgent*);
+    explicit V8AsyncCallTracker(V8DebuggerAgentImpl*);
 
     void didEnqueueV8AsyncTask(ScriptState*, const String& eventName, int id);
     void willHandleV8AsyncTask(ScriptState*, const String& eventName, int id);
 
     class V8ContextAsyncOperations;
     WillBeHeapHashMap<RefPtr<ScriptState>, OwnPtrWillBeMember<V8ContextAsyncOperations>> m_contextAsyncOperationMap;
-    RawPtrWillBeMember<V8DebuggerAgent> m_debuggerAgent;
+    V8DebuggerAgentImpl* m_debuggerAgent;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8Debugger.h b/third_party/WebKit/Source/core/inspector/v8/V8Debugger.h
index 26ebb5a..a0d402f 100644
--- a/third_party/WebKit/Source/core/inspector/v8/V8Debugger.h
+++ b/third_party/WebKit/Source/core/inspector/v8/V8Debugger.h
@@ -7,7 +7,6 @@
 
 #include "core/CoreExport.h"
 #include "core/InspectorTypeBuilder.h"
-#include "core/inspector/v8/V8DebuggerListener.h"
 #include "wtf/FastAllocBase.h"
 #include "wtf/Forward.h"
 #include "wtf/PassOwnPtr.h"
@@ -30,15 +29,9 @@
     virtual bool enabled() const = 0;
 
     // Each v8::Context is a part of a group. The group id is used to find approapriate
-    // V8DebuggerListener to notify about events in the context.
+    // V8DebuggerAgent to notify about events in the context.
     // |contextGroupId| must be non-0.
     static void setContextDebugData(v8::Local<v8::Context>, const String& type, int contextGroupId);
-    virtual void addListener(int contextGroupId, V8DebuggerListener*) = 0;
-    virtual void removeListener(int contextGroupId) = 0;
-
-    virtual String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation) = 0;
-    virtual void removeBreakpoint(const String& breakpointId) = 0;
-    virtual void setBreakpointsActivated(bool) = 0;
 
     enum PauseOnExceptionsState {
         DontPauseOnExceptions,
@@ -48,30 +41,15 @@
     virtual PauseOnExceptionsState pauseOnExceptionsState() = 0;
     virtual void setPauseOnExceptionsState(PauseOnExceptionsState) = 0;
 
+    // TODO: remove these methods once runtime agent is part of the implementation.
     virtual void setPauseOnNextStatement(bool) = 0;
     virtual bool pausingOnNextStatement() = 0;
-    virtual bool canBreakProgram() = 0;
-    virtual void breakProgram() = 0;
-    virtual void continueProgram() = 0;
-    virtual void stepIntoStatement() = 0;
-    virtual void stepOverStatement() = 0;
-    virtual void stepOutOfFunction() = 0;
-    virtual void clearStepping() = 0;
 
-    virtual bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, v8::Global<v8::Object>* newCallFrames, TypeBuilder::OptOutput<bool>* stackChanged) = 0;
-    virtual v8::Local<v8::Object> currentCallFrames() = 0;
-    virtual v8::Local<v8::Object> currentCallFramesForAsyncStack() = 0;
-    virtual PassRefPtr<JavaScriptCallFrame> callFrameNoScopes(int index) = 0;
-    virtual int frameCount() = 0;
-
-    virtual bool isPaused() = 0;
-
+    // TODO: these methods will not be public once InjectedScriptHost is in the implementation.
     virtual v8::Local<v8::Value> functionScopes(v8::Local<v8::Function>) = 0;
     virtual v8::Local<v8::Value> generatorObjectDetails(v8::Local<v8::Object>&) = 0;
     virtual v8::Local<v8::Value> collectionEntries(v8::Local<v8::Object>&) = 0;
     virtual v8::MaybeLocal<v8::Value> setFunctionVariableValue(v8::Local<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Local<v8::Value> newValue) = 0;
-
-    virtual v8::Isolate* isolate() const = 0;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h
new file mode 100644
index 0000000..6d94d81
--- /dev/null
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgent.h
@@ -0,0 +1,130 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8DebuggerAgent_h
+#define V8DebuggerAgent_h
+
+#include "core/CoreExport.h"
+#include "core/InspectorFrontend.h"
+#include "wtf/Forward.h"
+#include "wtf/PassRefPtr.h"
+
+namespace blink {
+
+class InjectedScript;
+class InjectedScriptManager;
+class InspectorState;
+class JSONObject;
+class RemoteCallFrameId;
+class ScriptAsyncCallStack;
+class V8Debugger;
+
+typedef String ErrorString;
+
+class CORE_EXPORT V8DebuggerAgent {
+public:
+    class CORE_EXPORT Client {
+    public:
+        virtual ~Client() { }
+        virtual void debuggerAgentEnabled() = 0;
+        virtual void debuggerAgentDisabled() = 0;
+        virtual void muteConsole() = 0;
+        virtual void unmuteConsole() = 0;
+        virtual InjectedScript defaultInjectedScript() = 0;
+
+        virtual void asyncCallTrackingStateChanged(bool tracking) = 0;
+        virtual void resetAsyncOperations() = 0;
+    };
+
+    // FIXME: remove this enum from public interface once InjectedScriptHost is moved to the implementation.
+    enum BreakpointSource {
+        UserBreakpointSource,
+        DebugCommandBreakpointSource,
+        MonitorCommandBreakpointSource
+    };
+
+    static const char backtraceObjectGroup[];
+
+    // FIXME: injected script management should be an implementation details. This method should only accept client.
+    static PassOwnPtr<V8DebuggerAgent> create(InjectedScriptManager*, V8Debugger*, V8DebuggerAgent::Client*, int contextGroupId);
+    virtual ~V8DebuggerAgent() { }
+
+    // Protocol methods.
+    virtual void enable(ErrorString*) = 0;
+    virtual void disable(ErrorString*) = 0;
+    virtual void setBreakpointsActive(ErrorString*, bool in_active) = 0;
+    virtual void setSkipAllPauses(ErrorString*, bool in_skipped) = 0;
+    virtual void setBreakpointByUrl(ErrorString*, int in_lineNumber, const String* in_url, const String* in_urlRegex, const int* in_columnNumber, const String* in_condition, TypeBuilder::Debugger::BreakpointId* out_breakpointId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location>>& out_locations) = 0;
+    virtual void setBreakpoint(ErrorString*, const RefPtr<JSONObject>& in_location, const String* in_condition, TypeBuilder::Debugger::BreakpointId* out_breakpointId, RefPtr<TypeBuilder::Debugger::Location>& out_actualLocation) = 0;
+    virtual void removeBreakpoint(ErrorString*, const String& in_breakpointId) = 0;
+    virtual void continueToLocation(ErrorString*, const RefPtr<JSONObject>& in_location, const bool* in_interstatementLocation) = 0;
+    virtual void stepOver(ErrorString*) = 0;
+    virtual void stepInto(ErrorString*) = 0;
+    virtual void stepOut(ErrorString*) = 0;
+    virtual void pause(ErrorString*) = 0;
+    virtual void resume(ErrorString*) = 0;
+    virtual void stepIntoAsync(ErrorString*) = 0;
+    virtual void searchInContent(ErrorString*, const String& in_scriptId, const String& in_query, const bool* in_caseSensitive, const bool* in_isRegex, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::SearchMatch>>& out_result) = 0;
+    virtual void canSetScriptSource(ErrorString*, bool* out_result) = 0;
+    virtual void setScriptSource(ErrorString*, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& in_scriptId, const String& in_scriptSource, const bool* in_preview, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>>& opt_out_callFrames, TypeBuilder::OptOutput<bool>* opt_out_stackChanged, RefPtr<TypeBuilder::Debugger::StackTrace>& opt_out_asyncStackTrace) = 0;
+    virtual void restartFrame(ErrorString*, const String& in_callFrameId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>>& out_callFrames, RefPtr<TypeBuilder::Debugger::StackTrace>& opt_out_asyncStackTrace) = 0;
+    virtual void getScriptSource(ErrorString*, const String& in_scriptId, String* out_scriptSource) = 0;
+    virtual void getFunctionDetails(ErrorString*, const String& in_functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>& out_details) = 0;
+    virtual void getGeneratorObjectDetails(ErrorString*, const String& in_objectId, RefPtr<TypeBuilder::Debugger::GeneratorObjectDetails>& out_details) = 0;
+    virtual void getCollectionEntries(ErrorString*, const String& in_objectId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CollectionEntry>>& out_entries) = 0;
+    virtual void setPauseOnExceptions(ErrorString*, const String& in_state) = 0;
+    virtual void evaluateOnCallFrame(ErrorString*, const String& in_callFrameId, const String& in_expression, const String* in_objectGroup, const bool* in_includeCommandLineAPI, const bool* in_doNotPauseOnExceptionsAndMuteConsole, const bool* in_returnByValue, const bool* in_generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_result, TypeBuilder::OptOutput<bool>* opt_out_wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0;
+    virtual void compileScript(ErrorString*, const String& in_expression, const String& in_sourceURL, bool in_persistScript, const int* in_executionContextId, TypeBuilder::OptOutput<TypeBuilder::Debugger::ScriptId>* opt_out_scriptId, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0;
+    virtual void runScript(ErrorString*, const String& in_scriptId, const int* in_executionContextId, const String* in_objectGroup, const bool* in_doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& opt_out_exceptionDetails) = 0;
+    virtual void setVariableValue(ErrorString*, int in_scopeNumber, const String& in_variableName, const RefPtr<JSONObject>& in_newValue, const String* in_callFrameId, const String* in_functionObjectId) = 0;
+    virtual void getStepInPositions(ErrorString*, const String& in_callFrameId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location>>& opt_out_stepInPositions) = 0;
+    virtual void getBacktrace(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>>& out_callFrames, RefPtr<TypeBuilder::Debugger::StackTrace>& opt_out_asyncStackTrace) = 0;
+    virtual void skipStackFrames(ErrorString*, const String* in_script, const bool* in_skipContentScripts) = 0;
+    virtual void setAsyncCallStackDepth(ErrorString*, int in_maxDepth) = 0;
+    virtual void enablePromiseTracker(ErrorString*, const bool* in_captureStacks) = 0;
+    virtual void disablePromiseTracker(ErrorString*) = 0;
+    virtual void getPromiseById(ErrorString*, int in_promiseId, const String* in_objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& out_promise) = 0;
+    virtual void flushAsyncOperationEvents(ErrorString*) = 0;
+    virtual void setAsyncOperationBreakpoint(ErrorString*, int in_operationId) = 0;
+    virtual void removeAsyncOperationBreakpoint(ErrorString*, int in_operationId) = 0;
+
+    // State management methods.
+    virtual void setInspectorState(InspectorState*) = 0;
+    virtual void setFrontend(InspectorFrontend::Debugger*) = 0;
+    virtual void clearFrontend() = 0;
+    virtual void restore() = 0;
+
+    // API for the embedder to report native activities.
+    virtual void schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data) = 0;
+    virtual void cancelPauseOnNextStatement() = 0;
+    virtual bool canBreakProgram() = 0;
+    virtual void breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data) = 0;
+    virtual void willExecuteScript(int scriptId) = 0;
+    virtual void didExecuteScript() = 0;
+    virtual void reset() = 0;
+
+    virtual bool isPaused() = 0;
+    virtual bool enabled() = 0;
+    virtual V8Debugger& debugger() = 0;
+
+    virtual void setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource, const String& condition = String()) = 0;
+    virtual void removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource) = 0;
+
+    // Async call stacks implementation
+    virtual PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> currentAsyncStackTraceForConsole() = 0;
+    static const int unknownAsyncOperationId;
+    virtual int traceAsyncOperationStarting(const String& description) = 0;
+    virtual void traceAsyncCallbackStarting(int operationId) = 0;
+    virtual void traceAsyncCallbackCompleted() = 0;
+    virtual void traceAsyncOperationCompleted(int operationId) = 0;
+    virtual bool trackingAsyncCalls() const = 0;
+
+    virtual InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) = 0;
+    virtual InjectedScriptManager* injectedScriptManager() = 0;
+};
+
+} // namespace blink
+
+
+#endif // V8DebuggerAgent_h
diff --git a/third_party/WebKit/Source/core/inspector/V8DebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp
similarity index 82%
rename from third_party/WebKit/Source/core/inspector/V8DebuggerAgent.cpp
rename to third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp
index b52e4e1c5..6c29c9b 100644
--- a/third_party/WebKit/Source/core/inspector/V8DebuggerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.cpp
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "config.h"
-#include "core/inspector/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerAgentImpl.h"
 
 #include "bindings/core/v8/ScriptCallStackFactory.h"
 #include "bindings/core/v8/ScriptRegexp.h"
@@ -23,8 +23,8 @@
 #include "core/inspector/ScriptAsyncCallStack.h"
 #include "core/inspector/ScriptCallFrame.h"
 #include "core/inspector/ScriptCallStack.h"
-#include "core/inspector/V8AsyncCallTracker.h"
 #include "core/inspector/v8/JavaScriptCallFrame.h"
+#include "core/inspector/v8/V8AsyncCallTracker.h"
 #include "core/inspector/v8/V8Debugger.h"
 #include "core/inspector/v8/V8JavaScriptCallFrame.h"
 #include "platform/JSONValues.h"
@@ -73,20 +73,20 @@
 
 const int V8DebuggerAgent::unknownAsyncOperationId = 0;
 
-static String breakpointIdSuffix(V8DebuggerAgent::BreakpointSource source)
+static String breakpointIdSuffix(V8DebuggerAgentImpl::BreakpointSource source)
 {
     switch (source) {
-    case V8DebuggerAgent::UserBreakpointSource:
+    case V8DebuggerAgentImpl::UserBreakpointSource:
         break;
-    case V8DebuggerAgent::DebugCommandBreakpointSource:
+    case V8DebuggerAgentImpl::DebugCommandBreakpointSource:
         return ":debug";
-    case V8DebuggerAgent::MonitorCommandBreakpointSource:
+    case V8DebuggerAgentImpl::MonitorCommandBreakpointSource:
         return ":monitor";
     }
     return String();
 }
 
-static String generateBreakpointId(const String& scriptId, int lineNumber, int columnNumber, V8DebuggerAgent::BreakpointSource source)
+static String generateBreakpointId(const String& scriptId, int lineNumber, int columnNumber, V8DebuggerAgentImpl::BreakpointSource source)
 {
     return scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber) + breakpointIdSuffix(source);
 }
@@ -121,7 +121,12 @@
     return jsCallFrame ? toScriptCallStack(jsCallFrame.get()) : nullptr;
 }
 
-V8DebuggerAgent::V8DebuggerAgent(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, V8DebuggerAgent::Client* client, int contextGroupId)
+PassOwnPtr<V8DebuggerAgent> V8DebuggerAgent::create(InjectedScriptManager* injectedScriptManager, V8Debugger* debugger, V8DebuggerAgentImpl::Client* client, int contextGroupId)
+{
+    return adoptPtr(new V8DebuggerAgentImpl(injectedScriptManager, static_cast<V8DebuggerImpl*>(debugger), client, contextGroupId));
+}
+
+V8DebuggerAgentImpl::V8DebuggerAgentImpl(InjectedScriptManager* injectedScriptManager, V8DebuggerImpl* debugger, V8DebuggerAgentImpl::Client* client, int contextGroupId)
     : m_injectedScriptManager(injectedScriptManager)
     , m_debugger(debugger)
     , m_client(client)
@@ -158,23 +163,11 @@
     clearBreakDetails();
 }
 
-V8DebuggerAgent::~V8DebuggerAgent()
+V8DebuggerAgentImpl::~V8DebuggerAgentImpl()
 {
 }
 
-DEFINE_TRACE(V8DebuggerAgent)
-{
-#if ENABLE(OILPAN)
-    visitor->trace(m_injectedScriptManager);
-    visitor->trace(m_asyncCallTrackingListeners);
-    visitor->trace(m_v8AsyncCallTracker);
-    visitor->trace(m_promiseTracker);
-    visitor->trace(m_asyncOperations);
-    visitor->trace(m_currentAsyncCallChain);
-#endif
-}
-
-bool V8DebuggerAgent::checkEnabled(ErrorString* errorString)
+bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString)
 {
     if (enabled())
         return true;
@@ -182,7 +175,7 @@
     return false;
 }
 
-void V8DebuggerAgent::enable()
+void V8DebuggerAgentImpl::enable()
 {
     // debugger().addListener may result in reporting all parsed scripts to
     // the agent so it should already be in enabled state by then.
@@ -193,12 +186,12 @@
     m_client->debuggerAgentEnabled();
 }
 
-bool V8DebuggerAgent::enabled()
+bool V8DebuggerAgentImpl::enabled()
 {
     return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
 }
 
-void V8DebuggerAgent::enable(ErrorString*)
+void V8DebuggerAgentImpl::enable(ErrorString*)
 {
     if (enabled())
         return;
@@ -208,7 +201,7 @@
     ASSERT(m_frontend);
 }
 
-void V8DebuggerAgent::disable(ErrorString*)
+void V8DebuggerAgentImpl::disable(ErrorString*)
 {
     if (!enabled())
         return;
@@ -255,14 +248,14 @@
     return result.release();
 }
 
-void V8DebuggerAgent::increaseCachedSkipStackGeneration()
+void V8DebuggerAgentImpl::increaseCachedSkipStackGeneration()
 {
     ++m_cachedSkipStackGeneration;
     if (!m_cachedSkipStackGeneration)
         m_cachedSkipStackGeneration = 1;
 }
 
-void V8DebuggerAgent::internalSetAsyncCallStackDepth(int depth)
+void V8DebuggerAgentImpl::internalSetAsyncCallStackDepth(int depth)
 {
     if (depth <= 0) {
         m_maxAsyncCallStackDepth = 0;
@@ -270,11 +263,11 @@
     } else {
         m_maxAsyncCallStackDepth = depth;
     }
-    for (auto& listener: m_asyncCallTrackingListeners)
-        listener->asyncCallTrackingStateChanged(m_maxAsyncCallStackDepth);
+    m_client->asyncCallTrackingStateChanged(m_maxAsyncCallStackDepth);
+    m_v8AsyncCallTracker->asyncCallTrackingStateChanged(m_maxAsyncCallStackDepth);
 }
 
-void V8DebuggerAgent::clearFrontend()
+void V8DebuggerAgentImpl::clearFrontend()
 {
     ErrorString error;
     disable(&error);
@@ -282,7 +275,7 @@
     m_frontend = nullptr;
 }
 
-void V8DebuggerAgent::restore()
+void V8DebuggerAgentImpl::restore()
 {
     if (enabled()) {
         m_frontend->globalObjectCleared();
@@ -299,20 +292,20 @@
     }
 }
 
-void V8DebuggerAgent::setBreakpointsActive(ErrorString* errorString, bool active)
+void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool active)
 {
     if (!checkEnabled(errorString))
         return;
     debugger().setBreakpointsActivated(active);
 }
 
-void V8DebuggerAgent::setSkipAllPauses(ErrorString*, bool skipped)
+void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skipped)
 {
     m_skipAllPauses = skipped;
     m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
 }
 
-bool V8DebuggerAgent::isPaused()
+bool V8DebuggerAgentImpl::isPaused()
 {
     return debugger().isPaused();
 }
@@ -337,7 +330,7 @@
     return url == pattern;
 }
 
-void V8DebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<Array<TypeBuilder::Debugger::Location>>& locations)
+void V8DebuggerAgentImpl::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<Array<TypeBuilder::Debugger::Location>>& locations)
 {
     locations = Array<TypeBuilder::Debugger::Location>::create();
     if (!optionalURL == !optionalURLRegex) {
@@ -391,7 +384,7 @@
     return true;
 }
 
-void V8DebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<JSONObject>& location, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
+void V8DebuggerAgentImpl::setBreakpoint(ErrorString* errorString, const RefPtr<JSONObject>& location, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
 {
     String scriptId;
     int lineNumber;
@@ -415,7 +408,7 @@
         *errorString = "Could not resolve breakpoint";
 }
 
-void V8DebuggerAgent::removeBreakpoint(ErrorString* errorString, const String& breakpointId)
+void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, const String& breakpointId)
 {
     if (!checkEnabled(errorString))
         return;
@@ -425,7 +418,7 @@
     removeBreakpoint(breakpointId);
 }
 
-void V8DebuggerAgent::removeBreakpoint(const String& breakpointId)
+void V8DebuggerAgentImpl::removeBreakpoint(const String& breakpointId)
 {
     ASSERT(enabled());
     BreakpointIdToDebuggerBreakpointIdsMap::iterator debuggerBreakpointIdsIterator = m_breakpointIdToDebuggerBreakpointIds.find(breakpointId);
@@ -439,7 +432,7 @@
     m_breakpointIdToDebuggerBreakpointIds.remove(debuggerBreakpointIdsIterator);
 }
 
-void V8DebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
+void V8DebuggerAgentImpl::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
 {
     if (!checkEnabled(errorString))
         return;
@@ -460,7 +453,7 @@
     resume(errorString);
 }
 
-void V8DebuggerAgent::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location>>& positions)
+void V8DebuggerAgentImpl::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location>>& positions)
 {
     if (!isPaused() || m_currentCallStack.IsEmpty()) {
         *errorString = "Attempt to access callframe when debugger is not on pause";
@@ -482,7 +475,7 @@
     injectedScript.getStepInPositions(errorString, callStack, callFrameId, positions);
 }
 
-void V8DebuggerAgent::getBacktrace(ErrorString* errorString, RefPtr<Array<CallFrame>>& callFrames, RefPtr<StackTrace>& asyncStackTrace)
+void V8DebuggerAgentImpl::getBacktrace(ErrorString* errorString, RefPtr<Array<CallFrame>>& callFrames, RefPtr<StackTrace>& asyncStackTrace)
 {
     if (!assertPaused(errorString))
         return;
@@ -491,7 +484,7 @@
     asyncStackTrace = currentAsyncStackTrace();
 }
 
-bool V8DebuggerAgent::isCallStackEmptyOrBlackboxed()
+bool V8DebuggerAgentImpl::isCallStackEmptyOrBlackboxed()
 {
     ASSERT(enabled());
     for (int index = 0; ; ++index) {
@@ -504,13 +497,13 @@
     return true;
 }
 
-bool V8DebuggerAgent::isTopCallFrameBlackboxed()
+bool V8DebuggerAgentImpl::isTopCallFrameBlackboxed()
 {
     ASSERT(enabled());
     return isCallFrameWithUnknownScriptOrBlackboxed(debugger().callFrameNoScopes(0));
 }
 
-bool V8DebuggerAgent::isCallFrameWithUnknownScriptOrBlackboxed(PassRefPtr<JavaScriptCallFrame> pFrame)
+bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(PassRefPtr<JavaScriptCallFrame> pFrame)
 {
     RefPtr<JavaScriptCallFrame> frame = pFrame;
     if (!frame)
@@ -533,7 +526,7 @@
     return isBlackboxed;
 }
 
-V8DebuggerListener::SkipPauseRequest V8DebuggerAgent::shouldSkipExceptionPause()
+V8DebuggerListener::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipExceptionPause()
 {
     if (m_steppingFromFramework)
         return V8DebuggerListener::NoSkip;
@@ -542,7 +535,7 @@
     return V8DebuggerListener::NoSkip;
 }
 
-V8DebuggerListener::SkipPauseRequest V8DebuggerAgent::shouldSkipStepPause()
+V8DebuggerListener::SkipPauseRequest V8DebuggerAgentImpl::shouldSkipStepPause()
 {
     if (m_steppingFromFramework)
         return V8DebuggerListener::NoSkip;
@@ -566,7 +559,7 @@
     return V8DebuggerListener::StepFrame;
 }
 
-PassRefPtr<TypeBuilder::Debugger::Location> V8DebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
+PassRefPtr<TypeBuilder::Debugger::Location> V8DebuggerAgentImpl::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
 {
     ASSERT(enabled());
     // FIXME: remove these checks once crbug.com/520702 is resolved.
@@ -601,7 +594,7 @@
     return location;
 }
 
-void V8DebuggerAgent::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<TypeBuilder::Debugger::SearchMatch>>& results)
+void V8DebuggerAgentImpl::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<TypeBuilder::Debugger::SearchMatch>>& results)
 {
     ScriptsMap::iterator it = m_scripts.find(scriptId);
     if (it != m_scripts.end())
@@ -610,7 +603,7 @@
         *error = "No script for id: " + scriptId;
 }
 
-void V8DebuggerAgent::setScriptSource(ErrorString* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<CallFrame>>& newCallFrames, TypeBuilder::OptOutput<bool>* stackChanged, RefPtr<StackTrace>& asyncStackTrace)
+void V8DebuggerAgentImpl::setScriptSource(ErrorString* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<CallFrame>>& newCallFrames, TypeBuilder::OptOutput<bool>* stackChanged, RefPtr<StackTrace>& asyncStackTrace)
 {
     if (!checkEnabled(error))
         return;
@@ -626,7 +619,7 @@
     it->value.setSource(newContent);
 }
 
-void V8DebuggerAgent::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<CallFrame>>& newCallFrames, RefPtr<StackTrace>& asyncStackTrace)
+void V8DebuggerAgentImpl::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<CallFrame>>& newCallFrames, RefPtr<StackTrace>& asyncStackTrace)
 {
     if (!isPaused() || m_currentCallStack.IsEmpty()) {
         *errorString = "Attempt to access callframe when debugger is not on pause";
@@ -651,7 +644,7 @@
     asyncStackTrace = currentAsyncStackTrace();
 }
 
-void V8DebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
+void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
 {
     if (!checkEnabled(error))
         return;
@@ -663,7 +656,7 @@
     *scriptSource = it->value.source();
 }
 
-void V8DebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>& details)
+void V8DebuggerAgentImpl::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>& details)
 {
     if (!checkEnabled(errorString))
         return;
@@ -680,7 +673,7 @@
     injectedScript.getFunctionDetails(errorString, functionId, &details);
 }
 
-void V8DebuggerAgent::getGeneratorObjectDetails(ErrorString* errorString, const String& objectId, RefPtr<GeneratorObjectDetails>& details)
+void V8DebuggerAgentImpl::getGeneratorObjectDetails(ErrorString* errorString, const String& objectId, RefPtr<GeneratorObjectDetails>& details)
 {
     if (!checkEnabled(errorString))
         return;
@@ -697,7 +690,7 @@
     injectedScript.getGeneratorObjectDetails(errorString, objectId, &details);
 }
 
-void V8DebuggerAgent::getCollectionEntries(ErrorString* errorString, const String& objectId, RefPtr<TypeBuilder::Array<CollectionEntry>>& entries)
+void V8DebuggerAgentImpl::getCollectionEntries(ErrorString* errorString, const String& objectId, RefPtr<TypeBuilder::Array<CollectionEntry>>& entries)
 {
     if (!checkEnabled(errorString))
         return;
@@ -714,7 +707,7 @@
     injectedScript.getCollectionEntries(errorString, objectId, &entries);
 }
 
-void V8DebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
+void V8DebuggerAgentImpl::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
 {
     ASSERT(enabled());
     if (m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || isPaused())
@@ -726,7 +719,7 @@
     debugger().setPauseOnNextStatement(true);
 }
 
-void V8DebuggerAgent::schedulePauseOnNextStatementIfSteppingInto()
+void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto()
 {
     ASSERT(enabled());
     if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || isPaused())
@@ -738,7 +731,7 @@
     debugger().setPauseOnNextStatement(true);
 }
 
-void V8DebuggerAgent::cancelPauseOnNextStatement()
+void V8DebuggerAgentImpl::cancelPauseOnNextStatement()
 {
     if (m_javaScriptPauseScheduled || isPaused())
         return;
@@ -747,31 +740,31 @@
     debugger().setPauseOnNextStatement(false);
 }
 
-bool V8DebuggerAgent::v8AsyncTaskEventsEnabled() const
+bool V8DebuggerAgentImpl::v8AsyncTaskEventsEnabled() const
 {
     return trackingAsyncCalls();
 }
 
-void V8DebuggerAgent::didReceiveV8AsyncTaskEvent(v8::Local<v8::Context> context, const String& eventType, const String& eventName, int id)
+void V8DebuggerAgentImpl::didReceiveV8AsyncTaskEvent(v8::Local<v8::Context> context, const String& eventType, const String& eventName, int id)
 {
     ASSERT(trackingAsyncCalls());
     ScriptState* state = ScriptState::from(context);
     m_v8AsyncCallTracker->didReceiveV8AsyncTaskEvent(state, eventType, eventName, id);
 }
 
-bool V8DebuggerAgent::v8PromiseEventsEnabled() const
+bool V8DebuggerAgentImpl::v8PromiseEventsEnabled() const
 {
     return m_promiseTracker->isEnabled();
 }
 
-void V8DebuggerAgent::didReceiveV8PromiseEvent(v8::Local<v8::Context> context, v8::Local<v8::Object> promise, v8::Local<v8::Value> parentPromise, int status)
+void V8DebuggerAgentImpl::didReceiveV8PromiseEvent(v8::Local<v8::Context> context, v8::Local<v8::Object> promise, v8::Local<v8::Value> parentPromise, int status)
 {
     ASSERT(m_promiseTracker->isEnabled());
     ScriptState* scriptState = ScriptState::from(context);
     m_promiseTracker->didReceiveV8PromiseEvent(scriptState, promise, parentPromise, status);
 }
 
-void V8DebuggerAgent::pause(ErrorString* errorString)
+void V8DebuggerAgentImpl::pause(ErrorString* errorString)
 {
     if (!checkEnabled(errorString))
         return;
@@ -786,17 +779,17 @@
     debugger().setPauseOnNextStatement(true);
 }
 
-void V8DebuggerAgent::resume(ErrorString* errorString)
+void V8DebuggerAgentImpl::resume(ErrorString* errorString)
 {
     if (!assertPaused(errorString))
         return;
     m_scheduledDebuggerStep = NoStep;
     m_steppingFromFramework = false;
-    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgent::backtraceObjectGroup);
+    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgentImpl::backtraceObjectGroup);
     debugger().continueProgram();
 }
 
-void V8DebuggerAgent::stepOver(ErrorString* errorString)
+void V8DebuggerAgentImpl::stepOver(ErrorString* errorString)
 {
     if (!assertPaused(errorString))
         return;
@@ -808,21 +801,21 @@
     }
     m_scheduledDebuggerStep = StepOver;
     m_steppingFromFramework = isTopCallFrameBlackboxed();
-    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgent::backtraceObjectGroup);
+    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgentImpl::backtraceObjectGroup);
     debugger().stepOverStatement();
 }
 
-void V8DebuggerAgent::stepInto(ErrorString* errorString)
+void V8DebuggerAgentImpl::stepInto(ErrorString* errorString)
 {
     if (!assertPaused(errorString))
         return;
     m_scheduledDebuggerStep = StepInto;
     m_steppingFromFramework = isTopCallFrameBlackboxed();
-    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgent::backtraceObjectGroup);
+    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgentImpl::backtraceObjectGroup);
     debugger().stepIntoStatement();
 }
 
-void V8DebuggerAgent::stepOut(ErrorString* errorString)
+void V8DebuggerAgentImpl::stepOut(ErrorString* errorString)
 {
     if (!assertPaused(errorString))
         return;
@@ -830,11 +823,11 @@
     m_skipNextDebuggerStepOut = false;
     m_recursionLevelForStepOut = 1;
     m_steppingFromFramework = isTopCallFrameBlackboxed();
-    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgent::backtraceObjectGroup);
+    m_injectedScriptManager->releaseObjectGroup(V8DebuggerAgentImpl::backtraceObjectGroup);
     debugger().stepOutOfFunction();
 }
 
-void V8DebuggerAgent::stepIntoAsync(ErrorString* errorString)
+void V8DebuggerAgentImpl::stepIntoAsync(ErrorString* errorString)
 {
     if (!assertPaused(errorString))
         return;
@@ -847,7 +840,7 @@
     stepInto(errorString);
 }
 
-void V8DebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
+void V8DebuggerAgentImpl::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
 {
     if (!checkEnabled(errorString))
         return;
@@ -865,7 +858,7 @@
     setPauseOnExceptionsImpl(errorString, pauseState);
 }
 
-void V8DebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
+void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
 {
     debugger().setPauseOnExceptionsState(static_cast<V8Debugger::PauseOnExceptionsState>(pauseState));
     if (debugger().pauseOnExceptionsState() != pauseState)
@@ -874,7 +867,7 @@
         m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState);
 }
 
-bool V8DebuggerAgent::callStackForId(ErrorString* errorString, const RemoteCallFrameId& callFrameId, v8::Local<v8::Object>* callStack, bool* isAsync)
+bool V8DebuggerAgentImpl::callStackForId(ErrorString* errorString, const RemoteCallFrameId& callFrameId, v8::Local<v8::Object>* callStack, bool* isAsync)
 {
     unsigned asyncOrdinal = callFrameId.asyncStackOrdinal(); // 0 is current call stack
     if (!asyncOrdinal) {
@@ -882,17 +875,17 @@
         *isAsync = false;
         return true;
     }
-    if (!m_currentAsyncCallChain || asyncOrdinal < 1 || asyncOrdinal >= m_currentAsyncCallChain->callStacks().size()) {
+    if (!m_currentAsyncCallChain || asyncOrdinal < 1 || asyncOrdinal > m_currentAsyncCallChain->callStacks().size()) {
         *errorString = "Async call stack not found";
         return false;
     }
-    RefPtrWillBeRawPtr<AsyncCallStack> asyncStack = m_currentAsyncCallChain->callStacks()[asyncOrdinal - 1];
+    RefPtr<AsyncCallStack> asyncStack = m_currentAsyncCallChain->callStacks()[asyncOrdinal - 1];
     *callStack = asyncStack->callFrames(m_isolate);
     *isAsync = true;
     return true;
 }
 
-void V8DebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& exceptionDetails)
+void V8DebuggerAgentImpl::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& exceptionDetails)
 {
     if (!isPaused() || m_currentCallStack.IsEmpty()) {
         *errorString = "Attempt to access callframe when debugger is not on pause";
@@ -931,7 +924,7 @@
     }
 }
 
-InjectedScript V8DebuggerAgent::injectedScriptForEval(ErrorString* errorString, const int* executionContextId)
+InjectedScript V8DebuggerAgentImpl::injectedScriptForEval(ErrorString* errorString, const int* executionContextId)
 {
     InjectedScript injectedScript = executionContextId ? m_injectedScriptManager->injectedScriptForId(*executionContextId) : m_client->defaultInjectedScript();
     if (injectedScript.isEmpty())
@@ -939,7 +932,7 @@
     return injectedScript;
 }
 
-void V8DebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails)
+void V8DebuggerAgentImpl::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, bool persistScript, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, RefPtr<ExceptionDetails>& exceptionDetails)
 {
     if (!checkEnabled(errorString))
         return;
@@ -970,7 +963,7 @@
     *scriptId = scriptValueId;
 }
 
-void V8DebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails)
+void V8DebuggerAgentImpl::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, RefPtr<ExceptionDetails>& exceptionDetails)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1026,7 +1019,7 @@
     }
 }
 
-void V8DebuggerAgent::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const String* callFrameId, const String* functionObjectId)
+void V8DebuggerAgentImpl::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const String* callFrameId, const String* functionObjectId)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1068,7 +1061,7 @@
     injectedScript.setVariableValue(errorString, currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString);
 }
 
-void V8DebuggerAgent::skipStackFrames(ErrorString* errorString, const String* pattern, const bool* skipContentScripts)
+void V8DebuggerAgentImpl::skipStackFrames(ErrorString* errorString, const String* pattern, const bool* skipContentScripts)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1088,7 +1081,7 @@
     m_state->setBoolean(DebuggerAgentState::skipContentScripts, m_skipContentScripts);
 }
 
-void V8DebuggerAgent::setAsyncCallStackDepth(ErrorString* errorString, int depth)
+void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, int depth)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1096,7 +1089,7 @@
     internalSetAsyncCallStackDepth(depth);
 }
 
-void V8DebuggerAgent::enablePromiseTracker(ErrorString* errorString, const bool* captureStacks)
+void V8DebuggerAgentImpl::enablePromiseTracker(ErrorString* errorString, const bool* captureStacks)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1105,7 +1098,7 @@
     m_promiseTracker->setEnabled(true, asBool(captureStacks));
 }
 
-void V8DebuggerAgent::disablePromiseTracker(ErrorString* errorString)
+void V8DebuggerAgentImpl::disablePromiseTracker(ErrorString* errorString)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1113,7 +1106,7 @@
     m_promiseTracker->setEnabled(false, false);
 }
 
-void V8DebuggerAgent::getPromiseById(ErrorString* errorString, int promiseId, const String* objectGroup, RefPtr<RemoteObject>& promise)
+void V8DebuggerAgentImpl::getPromiseById(ErrorString* errorString, int promiseId, const String* objectGroup, RefPtr<RemoteObject>& promise)
 {
     if (!checkEnabled(errorString))
         return;
@@ -1130,22 +1123,22 @@
     promise = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
 }
 
-void V8DebuggerAgent::didUpdatePromise(InspectorFrontend::Debugger::EventType::Enum eventType, PassRefPtr<TypeBuilder::Debugger::PromiseDetails> promise)
+void V8DebuggerAgentImpl::didUpdatePromise(InspectorFrontend::Debugger::EventType::Enum eventType, PassRefPtr<TypeBuilder::Debugger::PromiseDetails> promise)
 {
     if (m_frontend)
         m_frontend->promiseUpdated(eventType, promise);
 }
 
-int V8DebuggerAgent::traceAsyncOperationStarting(const String& description)
+int V8DebuggerAgentImpl::traceAsyncOperationStarting(const String& description)
 {
     v8::HandleScope scope(m_isolate);
     v8::Local<v8::Object> callFrames = debugger().currentCallFramesForAsyncStack();
-    RefPtrWillBeRawPtr<AsyncCallChain> chain = nullptr;
+    RefPtr<AsyncCallChain> chain;
     if (callFrames.IsEmpty()) {
         if (m_currentAsyncCallChain)
             chain = AsyncCallChain::create(nullptr, m_currentAsyncCallChain.get(), m_maxAsyncCallStackDepth);
     } else {
-        chain = AsyncCallChain::create(adoptRefWillBeNoop(new AsyncCallStack(description, callFrames)), m_currentAsyncCallChain.get(), m_maxAsyncCallStackDepth);
+        chain = AsyncCallChain::create(adoptRef(new AsyncCallStack(description, callFrames)), m_currentAsyncCallChain.get(), m_maxAsyncCallStackDepth);
     }
     do {
         ++m_lastAsyncOperationId;
@@ -1173,7 +1166,7 @@
     return m_lastAsyncOperationId;
 }
 
-void V8DebuggerAgent::traceAsyncCallbackStarting(int operationId)
+void V8DebuggerAgentImpl::traceAsyncCallbackStarting(int operationId)
 {
     ASSERT(operationId > 0 || operationId == unknownAsyncOperationId);
     AsyncCallChain* chain = operationId > 0 ? m_asyncOperations.get(operationId) : nullptr;
@@ -1214,7 +1207,7 @@
     }
 }
 
-void V8DebuggerAgent::traceAsyncCallbackCompleted()
+void V8DebuggerAgentImpl::traceAsyncCallbackCompleted()
 {
     if (!m_nestedAsyncCallCount)
         return;
@@ -1232,7 +1225,7 @@
     }
 }
 
-void V8DebuggerAgent::traceAsyncOperationCompleted(int operationId)
+void V8DebuggerAgentImpl::traceAsyncOperationCompleted(int operationId)
 {
     ASSERT(operationId > 0 || operationId == unknownAsyncOperationId);
     bool shouldNotify = false;
@@ -1259,13 +1252,13 @@
         m_frontend->asyncOperationCompleted(operationId);
 }
 
-void V8DebuggerAgent::flushAsyncOperationEvents(ErrorString*)
+void V8DebuggerAgentImpl::flushAsyncOperationEvents(ErrorString*)
 {
     if (!m_frontend)
         return;
 
     for (int operationId : m_asyncOperationNotifications) {
-        RefPtrWillBeRawPtr<AsyncCallChain> chain = m_asyncOperations.get(operationId);
+        RefPtr<AsyncCallChain> chain = m_asyncOperations.get(operationId);
         ASSERT(chain);
         const AsyncCallStackVector& callStacks = chain->callStacks();
         ASSERT(!callStacks.isEmpty());
@@ -1302,7 +1295,7 @@
     m_asyncOperationNotifications.clear();
 }
 
-void V8DebuggerAgent::clearCurrentAsyncOperation()
+void V8DebuggerAgentImpl::clearCurrentAsyncOperation()
 {
     if (m_pendingTraceAsyncOperationCompleted && m_currentAsyncOperationId != unknownAsyncOperationId)
         traceAsyncOperationCompleted(m_currentAsyncOperationId);
@@ -1313,18 +1306,18 @@
     m_currentAsyncCallChain.clear();
 }
 
-void V8DebuggerAgent::resetAsyncCallTracker()
+void V8DebuggerAgentImpl::resetAsyncCallTracker()
 {
     clearCurrentAsyncOperation();
     clearStepIntoAsync();
-    for (auto& listener: m_asyncCallTrackingListeners)
-        listener->resetAsyncOperations();
+    m_client->resetAsyncOperations();
+    m_v8AsyncCallTracker->resetAsyncOperations();
     m_asyncOperations.clear();
     m_asyncOperationNotifications.clear();
     m_asyncOperationBreakpoints.clear();
 }
 
-void V8DebuggerAgent::setAsyncOperationBreakpoint(ErrorString* errorString, int operationId)
+void V8DebuggerAgentImpl::setAsyncOperationBreakpoint(ErrorString* errorString, int operationId)
 {
     if (!trackingAsyncCalls()) {
         *errorString = "Can only perform operation while tracking async call stacks.";
@@ -1341,7 +1334,7 @@
     m_asyncOperationBreakpoints.add(operationId);
 }
 
-void V8DebuggerAgent::removeAsyncOperationBreakpoint(ErrorString* errorString, int operationId)
+void V8DebuggerAgentImpl::removeAsyncOperationBreakpoint(ErrorString* errorString, int operationId)
 {
     if (!trackingAsyncCalls()) {
         *errorString = "Can only perform operation while tracking async call stacks.";
@@ -1354,18 +1347,7 @@
     m_asyncOperationBreakpoints.remove(operationId);
 }
 
-void V8DebuggerAgent::addAsyncCallTrackingListener(AsyncCallTrackingListener* listener)
-{
-    m_asyncCallTrackingListeners.add(listener);
-}
-
-void V8DebuggerAgent::removeAsyncCallTrackingListener(AsyncCallTrackingListener* listener)
-{
-    ASSERT(m_asyncCallTrackingListeners.contains(listener));
-    m_asyncCallTrackingListeners.remove(listener);
-}
-
-void V8DebuggerAgent::willExecuteScript(int scriptId)
+void V8DebuggerAgentImpl::willExecuteScript(int scriptId)
 {
     changeJavaScriptRecursionLevel(+1);
     // Fast return.
@@ -1377,12 +1359,12 @@
     schedulePauseOnNextStatementIfSteppingInto();
 }
 
-void V8DebuggerAgent::didExecuteScript()
+void V8DebuggerAgentImpl::didExecuteScript()
 {
     changeJavaScriptRecursionLevel(-1);
 }
 
-void V8DebuggerAgent::changeJavaScriptRecursionLevel(int step)
+void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step)
 {
     if (m_javaScriptPauseScheduled && !m_skipAllPauses && !isPaused()) {
         // Do not ever loose user's pause request until we have actually paused.
@@ -1415,7 +1397,7 @@
     }
 }
 
-PassRefPtr<Array<CallFrame>> V8DebuggerAgent::currentCallFrames()
+PassRefPtr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames()
 {
     if (!m_pausedScriptState || m_currentCallStack.IsEmpty())
         return Array<CallFrame>::create();
@@ -1430,7 +1412,7 @@
     return injectedScript.wrapCallFrames(currentCallStack, 0);
 }
 
-PassRefPtr<StackTrace> V8DebuggerAgent::currentAsyncStackTrace()
+PassRefPtr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace()
 {
     if (!m_pausedScriptState || !trackingAsyncCalls())
         return nullptr;
@@ -1462,7 +1444,7 @@
     return result.release();
 }
 
-PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> V8DebuggerAgent::currentAsyncStackTraceForConsole()
+PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> V8DebuggerAgentImpl::currentAsyncStackTraceForConsole()
 {
     if (!trackingAsyncCalls())
         return nullptr;
@@ -1483,7 +1465,7 @@
     return result.release();
 }
 
-String V8DebuggerAgent::sourceMapURLForScript(const Script& script, CompileResult compileResult)
+String V8DebuggerAgentImpl::sourceMapURLForScript(const Script& script, CompileResult compileResult)
 {
     bool hasSyntaxError = compileResult != CompileSuccess;
     if (!hasSyntaxError)
@@ -1493,7 +1475,7 @@
 
 // V8DebuggerListener functions
 
-void V8DebuggerAgent::didParseSource(const ParsedScript& parsedScript)
+void V8DebuggerAgentImpl::didParseSource(const ParsedScript& parsedScript)
 {
     Script script = parsedScript.script;
 
@@ -1540,7 +1522,7 @@
     }
 }
 
-V8DebuggerListener::SkipPauseRequest V8DebuggerAgent::didPause(v8::Local<v8::Context> context, v8::Local<v8::Object> callFrames, v8::Local<v8::Value> v8exception, const Vector<String>& hitBreakpoints, bool isPromiseRejection)
+V8DebuggerListener::SkipPauseRequest V8DebuggerAgentImpl::didPause(v8::Local<v8::Context> context, v8::Local<v8::Object> callFrames, v8::Local<v8::Value> v8exception, const Vector<String>& hitBreakpoints, bool isPromiseRejection)
 {
     ScriptState* scriptState = ScriptState::from(context);
     ScriptValue exception(scriptState, v8exception);
@@ -1574,7 +1556,7 @@
         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
         if (!injectedScript.isEmpty()) {
             m_breakReason = isPromiseRejection ? InspectorFrontend::Debugger::Reason::PromiseRejection : InspectorFrontend::Debugger::Reason::Exception;
-            m_breakAuxData = injectedScript.wrapObject(exception, V8DebuggerAgent::backtraceObjectGroup)->openAccessors();
+            m_breakAuxData = injectedScript.wrapObject(exception, V8DebuggerAgentImpl::backtraceObjectGroup)->openAccessors();
             // m_breakAuxData might be null after this.
         }
     } else if (m_pausingOnAsyncOperation) {
@@ -1616,7 +1598,7 @@
     return result;
 }
 
-void V8DebuggerAgent::didContinue()
+void V8DebuggerAgentImpl::didContinue()
 {
     m_pausedScriptState = nullptr;
     m_currentCallStack.Reset();
@@ -1624,12 +1606,12 @@
     m_frontend->resumed();
 }
 
-bool V8DebuggerAgent::canBreakProgram()
+bool V8DebuggerAgentImpl::canBreakProgram()
 {
     return debugger().canBreakProgram();
 }
 
-void V8DebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
+void V8DebuggerAgentImpl::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
 {
     ASSERT(enabled());
     if (m_skipAllPauses || m_pausedScriptState || isCallStackEmptyOrBlackboxed())
@@ -1643,14 +1625,14 @@
     debugger().breakProgram();
 }
 
-void V8DebuggerAgent::clearStepIntoAsync()
+void V8DebuggerAgentImpl::clearStepIntoAsync()
 {
     m_startingStepIntoAsync = false;
     m_pausingOnAsyncOperation = false;
     m_pausingAsyncOperations.clear();
 }
 
-bool V8DebuggerAgent::assertPaused(ErrorString* errorString)
+bool V8DebuggerAgentImpl::assertPaused(ErrorString* errorString)
 {
     if (!m_pausedScriptState) {
         *errorString = "Can only perform operation while paused.";
@@ -1659,25 +1641,25 @@
     return true;
 }
 
-void V8DebuggerAgent::clearBreakDetails()
+void V8DebuggerAgentImpl::clearBreakDetails()
 {
     m_breakReason = InspectorFrontend::Debugger::Reason::Other;
     m_breakAuxData = nullptr;
 }
 
-void V8DebuggerAgent::setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String& condition)
+void V8DebuggerAgentImpl::setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String& condition)
 {
     String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source);
     ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
     resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
 }
 
-void V8DebuggerAgent::removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
+void V8DebuggerAgentImpl::removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
 {
     removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source));
 }
 
-void V8DebuggerAgent::reset()
+void V8DebuggerAgentImpl::reset()
 {
     m_scheduledDebuggerStep = NoStep;
     m_scripts.clear();
@@ -1688,7 +1670,7 @@
         m_frontend->globalObjectCleared();
 }
 
-PassRefPtr<TypeBuilder::Debugger::ExceptionDetails> V8DebuggerAgent::createExceptionDetails(v8::Isolate* isolate, v8::Local<v8::Message> message)
+PassRefPtr<TypeBuilder::Debugger::ExceptionDetails> V8DebuggerAgentImpl::createExceptionDetails(v8::Isolate* isolate, v8::Local<v8::Message> message)
 {
     RefPtr<ExceptionDetails> exceptionDetails = ExceptionDetails::create().setText(toCoreStringWithUndefinedOrNullCheck(message->Get()));
     exceptionDetails->setLine(message->GetLineNumber());
diff --git a/third_party/WebKit/Source/core/inspector/V8DebuggerAgent.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h
similarity index 77%
rename from third_party/WebKit/Source/core/inspector/V8DebuggerAgent.h
rename to third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.h
index 6956e2d5..6e09892 100644
--- a/third_party/WebKit/Source/core/inspector/V8DebuggerAgent.h
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerAgentImpl.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 V8DebuggerAgent_h
-#define V8DebuggerAgent_h
+#ifndef V8DebuggerAgentImpl_h
+#define V8DebuggerAgentImpl_h
 
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/ScriptValue.h"
@@ -12,6 +12,8 @@
 #include "core/inspector/InspectorBaseAgent.h"
 #include "core/inspector/PromiseTracker.h"
 #include "core/inspector/v8/ScriptBreakpoint.h"
+#include "core/inspector/v8/V8DebuggerAgent.h"
+#include "core/inspector/v8/V8DebuggerImpl.h"
 #include "core/inspector/v8/V8DebuggerListener.h"
 #include "wtf/Forward.h"
 #include "wtf/HashMap.h"
@@ -34,48 +36,28 @@
 class ScriptAsyncCallStack;
 class ScriptRegexp;
 class V8AsyncCallTracker;
-class V8Debugger;
 
 typedef String ErrorString;
 
-class CORE_EXPORT V8DebuggerAgent
-    : public NoBaseWillBeGarbageCollectedFinalized<V8DebuggerAgent>
+class CORE_EXPORT V8DebuggerAgentImpl
+    : public V8DebuggerAgent
     , public V8DebuggerListener
     , public InspectorBackendDispatcher::DebuggerCommandHandler
     , public PromiseTracker::Listener {
-    WTF_MAKE_NONCOPYABLE(V8DebuggerAgent);
-    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(V8DebuggerAgent);
-    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(V8DebuggerAgent);
+    WTF_MAKE_NONCOPYABLE(V8DebuggerAgentImpl);
+    WTF_MAKE_FAST_ALLOCATED(V8DebuggerAgentImpl);
 public:
-    enum BreakpointSource {
-        UserBreakpointSource,
-        DebugCommandBreakpointSource,
-        MonitorCommandBreakpointSource
-    };
-
-    static const char backtraceObjectGroup[];
-
-    class CORE_EXPORT Client {
-    public:
-        virtual ~Client() { }
-        virtual void debuggerAgentEnabled() = 0;
-        virtual void debuggerAgentDisabled() = 0;
-        virtual void muteConsole() = 0;
-        virtual void unmuteConsole() = 0;
-        virtual InjectedScript defaultInjectedScript() = 0;
-    };
-
-    V8DebuggerAgent(InjectedScriptManager*, V8Debugger*, Client*, int contextGroupId);
-    ~V8DebuggerAgent() override;
+    V8DebuggerAgentImpl(InjectedScriptManager*, V8DebuggerImpl*, V8DebuggerAgent::Client*, int contextGroupId);
+    ~V8DebuggerAgentImpl() override;
     DECLARE_TRACE();
 
-    void setInspectorState(InspectorState* state) { m_state = state; }
-    void setFrontend(InspectorFrontend::Debugger* frontend) { m_frontend = frontend; }
-    void clearFrontend();
-    void restore();
+    void setInspectorState(InspectorState* state) override { m_state = state; }
+    void setFrontend(InspectorFrontend::Debugger* frontend) override { m_frontend = frontend; }
+    void clearFrontend() override;
+    void restore() override;
     void disable(ErrorString*) final;
 
-    bool isPaused();
+    bool isPaused() override;
 
     // Part of the protocol.
     void enable(ErrorString*) override;
@@ -126,44 +108,33 @@
     void setAsyncOperationBreakpoint(ErrorString*, int operationId) final;
     void removeAsyncOperationBreakpoint(ErrorString*, int operationId) final;
 
-    void schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data);
-    void cancelPauseOnNextStatement();
-    bool canBreakProgram();
-    void breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data);
-    void willExecuteScript(int scriptId);
-    void didExecuteScript();
+    void schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data) override;
+    void cancelPauseOnNextStatement() override;
+    bool canBreakProgram() override;
+    void breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data) override;
+    void willExecuteScript(int scriptId) override;
+    void didExecuteScript() override;
 
-    bool enabled();
-    V8Debugger& debugger() { return *m_debugger; }
+    bool enabled() override;
+    V8DebuggerImpl& debugger() override { return *m_debugger; }
 
-    void setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource, const String& condition = String());
-    void removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource);
+    void setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource, const String& condition = String()) override;
+    void removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource) override;
 
     // Async call stacks implementation
-    PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> currentAsyncStackTraceForConsole();
-    static const int unknownAsyncOperationId;
-    int traceAsyncOperationStarting(const String& description);
-    void traceAsyncCallbackStarting(int operationId);
-    void traceAsyncCallbackCompleted();
-    void traceAsyncOperationCompleted(int operationId);
-    bool trackingAsyncCalls() const { return m_maxAsyncCallStackDepth; }
-
-    class CORE_EXPORT AsyncCallTrackingListener : public WillBeGarbageCollectedMixin {
-    public:
-        virtual ~AsyncCallTrackingListener() { }
-        DEFINE_INLINE_VIRTUAL_TRACE() { }
-        virtual void asyncCallTrackingStateChanged(bool tracking) = 0;
-        virtual void resetAsyncOperations() = 0;
-    };
-    void addAsyncCallTrackingListener(AsyncCallTrackingListener*);
-    void removeAsyncCallTrackingListener(AsyncCallTrackingListener*);
+    PassRefPtrWillBeRawPtr<ScriptAsyncCallStack> currentAsyncStackTraceForConsole() override;
+    int traceAsyncOperationStarting(const String& description) override;
+    void traceAsyncCallbackStarting(int operationId) override;
+    void traceAsyncCallbackCompleted() override;
+    void traceAsyncOperationCompleted(int operationId) override;
+    bool trackingAsyncCalls() const override { return m_maxAsyncCallStackDepth; }
 
     // PromiseTracker::Listener
     void didUpdatePromise(InspectorFrontend::Debugger::EventType::Enum, PassRefPtr<TypeBuilder::Debugger::PromiseDetails>) final;
 
-    InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId);
-    InjectedScriptManager* injectedScriptManager() { return m_injectedScriptManager; }
-    void reset();
+    InjectedScript injectedScriptForEval(ErrorString*, const int* executionContextId) override;
+    InjectedScriptManager* injectedScriptManager()  override { return m_injectedScriptManager; }
+    void reset() override;
 
 private:
     bool checkEnabled(ErrorString*);
@@ -221,9 +192,9 @@
         StepOut
     };
 
-    RawPtrWillBeMember<InjectedScriptManager> m_injectedScriptManager;
-    V8Debugger* m_debugger;
-    Client* m_client;
+    RawPtrWillBeWeakPersistent<InjectedScriptManager> m_injectedScriptManager;
+    V8DebuggerImpl* m_debugger;
+    V8DebuggerAgent::Client* m_client;
     int m_contextGroupId;
     InspectorState* m_state;
     InspectorFrontend::Debugger* m_frontend;
@@ -250,19 +221,18 @@
     bool m_skipContentScripts;
     OwnPtr<ScriptRegexp> m_cachedSkipStackRegExp;
     unsigned m_cachedSkipStackGeneration;
-    WillBeHeapHashSet<RawPtrWillBeWeakMember<AsyncCallTrackingListener>> m_asyncCallTrackingListeners;
     // This field must be destroyed before the listeners set above.
-    OwnPtrWillBeMember<V8AsyncCallTracker> m_v8AsyncCallTracker;
-    OwnPtrWillBeMember<PromiseTracker> m_promiseTracker;
+    OwnPtrWillBePersistent<V8AsyncCallTracker> m_v8AsyncCallTracker;
+    OwnPtr<PromiseTracker> m_promiseTracker;
 
-    using AsyncOperationIdToAsyncCallChain = WillBeHeapHashMap<int, RefPtrWillBeMember<AsyncCallChain>>;
+    using AsyncOperationIdToAsyncCallChain = HashMap<int, RefPtr<AsyncCallChain>>;
     AsyncOperationIdToAsyncCallChain m_asyncOperations;
     int m_lastAsyncOperationId;
     ListHashSet<int> m_asyncOperationNotifications;
     HashSet<int> m_asyncOperationBreakpoints;
     HashSet<int> m_pausingAsyncOperations;
     unsigned m_maxAsyncCallStackDepth;
-    RefPtrWillBeMember<AsyncCallChain> m_currentAsyncCallChain;
+    RefPtr<AsyncCallChain> m_currentAsyncCallChain;
     unsigned m_nestedAsyncCallCount;
     int m_currentAsyncOperationId;
     bool m_pendingTraceAsyncOperationCompleted;
@@ -273,4 +243,4 @@
 } // namespace blink
 
 
-#endif // V8DebuggerAgent_h
+#endif // V8DebuggerAgentImpl_h
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerClient.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerClient.h
index ef14c3f..d22d2b2e 100644
--- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerClient.h
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerClient.h
@@ -12,14 +12,12 @@
 
 namespace blink {
 
-class V8DebuggerListener;
-
 class CORE_EXPORT V8DebuggerClient {
     WTF_MAKE_FAST_ALLOCATED(V8DebuggerClient);
 public:
     virtual ~V8DebuggerClient() { }
     virtual v8::Local<v8::Object> compileDebuggerScript() = 0;
-    virtual void runMessageLoopOnPause(v8::Local<v8::Context>) = 0;
+    virtual void runMessageLoopOnPause(int contextGroupId) = 0;
     virtual void quitMessageLoopOnPause() = 0;
 };
 
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.cpp b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.cpp
index 8bc207f..5c9a6269 100644
--- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.cpp
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.cpp
@@ -540,7 +540,9 @@
     V8DebuggerListener::SkipPauseRequest result = listener->didPause(pausedContext, currentCallFrames(), exception, breakpointIds, isPromiseRejection);
     if (result == V8DebuggerListener::NoSkip) {
         m_runningNestedMessageLoop = true;
-        m_client->runMessageLoopOnPause(pausedContext);
+        int groupId = getGroupId(pausedContext);
+        ASSERT(groupId);
+        m_client->runMessageLoopOnPause(groupId);
         // The listener may have been removed in the nested loop.
         listener = getListenerForContext(pausedContext);
         if (listener)
diff --git a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.h b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.h
index 9fc2873..fec7a4f 100644
--- a/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.h
+++ b/third_party/WebKit/Source/core/inspector/v8/V8DebuggerImpl.h
@@ -54,40 +54,40 @@
 
     bool enabled() const override;
 
-    void addListener(int contextGroupId, V8DebuggerListener*) override;
-    void removeListener(int contextGroupId) override;
+    void addListener(int contextGroupId, V8DebuggerListener*);
+    void removeListener(int contextGroupId);
 
-    String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation) override;
-    void removeBreakpoint(const String& breakpointId) override;
-    void setBreakpointsActivated(bool) override;
+    String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber, bool interstatementLocation);
+    void removeBreakpoint(const String& breakpointId);
+    void setBreakpointsActivated(bool);
 
     PauseOnExceptionsState pauseOnExceptionsState() override;
     void setPauseOnExceptionsState(PauseOnExceptionsState) override;
 
     void setPauseOnNextStatement(bool) override;
     bool pausingOnNextStatement() override;
-    bool canBreakProgram() override;
-    void breakProgram() override;
-    void continueProgram() override;
-    void stepIntoStatement() override;
-    void stepOverStatement() override;
-    void stepOutOfFunction() override;
-    void clearStepping() override;
+    bool canBreakProgram();
+    void breakProgram();
+    void continueProgram();
+    void stepIntoStatement();
+    void stepOverStatement();
+    void stepOutOfFunction();
+    void clearStepping();
 
-    bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, v8::Global<v8::Object>* newCallFrames, TypeBuilder::OptOutput<bool>* stackChanged) override;
-    v8::Local<v8::Object> currentCallFrames() override;
-    v8::Local<v8::Object> currentCallFramesForAsyncStack() override;
-    PassRefPtr<JavaScriptCallFrame> callFrameNoScopes(int index) override;
-    int frameCount() override;
+    bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, v8::Global<v8::Object>* newCallFrames, TypeBuilder::OptOutput<bool>* stackChanged);
+    v8::Local<v8::Object> currentCallFrames();
+    v8::Local<v8::Object> currentCallFramesForAsyncStack();
+    PassRefPtr<JavaScriptCallFrame> callFrameNoScopes(int index);
+    int frameCount();
 
-    bool isPaused() override;
+    bool isPaused();
 
     v8::Local<v8::Value> functionScopes(v8::Local<v8::Function>) override;
     v8::Local<v8::Value> generatorObjectDetails(v8::Local<v8::Object>&) override;
     v8::Local<v8::Value> collectionEntries(v8::Local<v8::Object>&) override;
     v8::MaybeLocal<v8::Value> setFunctionVariableValue(v8::Local<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Local<v8::Value> newValue) override;
 
-    v8::Isolate* isolate() const override { return m_isolate; }
+    v8::Isolate* isolate() const { return m_isolate; }
 
 private:
     void enable();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
index e4fb73a..fb664a1a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -680,13 +680,9 @@
         return;
     parent->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::ChildAnonymousBlockChanged);
     parent->setChildrenInline(child->childrenInline());
-    LayoutObject* nextSibling = child->nextSibling();
 
+    child->moveAllChildrenTo(parent, child->nextSibling(), child->hasLayer());
     parent->children()->removeChildNode(parent, child, child->hasLayer());
-    child->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
-    // Explicitly delete the child's line box tree, or the special anonymous
-    // block handling in willBeDestroyed will cause problems.
-    child->deleteLineBoxTree();
     child->destroy();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
index 446abc9..b69cb4f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
@@ -601,6 +601,7 @@
                     opportunitiesInRun = Character::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion, textJustify);
                 else
                     opportunitiesInRun = Character::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion, textJustify);
+                // TODO(leviw): Why append if there are no expansion opportunities?
                 expansionOpportunities.append(opportunitiesInRun);
                 expansionOpportunityCount += opportunitiesInRun;
             }
@@ -628,7 +629,7 @@
         previousObject = r->m_object;
     }
 
-    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
+    if (isAfterExpansion && expansionOpportunityCount) {
         expansionOpportunities.last()--;
         expansionOpportunityCount--;
     }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
index 4181c78..10985cfa7 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -363,6 +363,8 @@
     // FIXME: This assert should be re-enabled when we move paint invalidation to after compositing update. crbug.com/360286
     // ASSERT(&newPaintInvalidationContainer == containerForPaintInvalidation());
 
+    LayoutRect previousPaintInvalidationRect = this->previousPaintInvalidationRect();
+
     PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationState, newPaintInvalidationContainer);
     clearPaintInvalidationState(paintInvalidationState);
 
@@ -373,10 +375,18 @@
     if (reason == PaintInvalidationLocationChange)
         childTreeWalkState.setForceSubtreeInvalidationWithinContainer();
 
-    // Workaround for crbug.com/533277.
+    // TODO(wangxianzhu): This is a workaround for crbug.com/533277. Will remove when we enable paint offset caching.
     if (reason != PaintInvalidationNone && hasPercentageTransform(styleRef()))
         childTreeWalkState.setForceSubtreeInvalidationWithinContainer();
 
+    // TODO(wangxianzhu): This is a workaround for crbug.com/490725. We don't have enough saved information to do accurate check
+    // of clipping change. Will remove when we remove rect-based paint invalidation.
+    if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()
+        && previousPaintInvalidationRect != this->previousPaintInvalidationRect()
+        && !usesCompositedScrolling()
+        && hasOverflowClip())
+        childTreeWalkState.setForceSubtreeInvalidationRectUpdateWithinContainer();
+
     invalidatePaintOfSubtreesIfNeeded(childTreeWalkState);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 1eb668c..39536a4c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -985,7 +985,10 @@
             double extraSpace = 0;
             bool childShrunk = false;
             if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow)) {
-                extraSpace = availableFreeSpace * child->style()->flexGrow() / totalFlexGrow;
+                if (totalFlexGrow < 1)
+                    extraSpace = availableFreeSpace * child->style()->flexGrow();
+                else
+                    extraSpace = availableFreeSpace * child->style()->flexGrow() / totalFlexGrow;
             } else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink) && child->style()->flexShrink()) {
                 extraSpace = availableFreeSpace * child->style()->flexShrink() * childInnerFlexBaseSize / totalWeightedFlexShrink;
                 childShrunk = true;
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
index 333728c..b2205b7 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -142,28 +142,6 @@
     LayoutUnit distributionOffset = -1;
 };
 
-struct GridTrackForNormalization {
-    GridTrackForNormalization(const GridTrack& track, double flex)
-        : m_track(&track)
-        , m_flex(flex)
-        , m_normalizedFlexValue(track.baseSize() / flex)
-    {
-    }
-
-    // Required by std::sort.
-    GridTrackForNormalization& operator=(const GridTrackForNormalization& o)
-    {
-        m_track = o.m_track;
-        m_flex = o.m_flex;
-        m_normalizedFlexValue = o.m_normalizedFlexValue;
-        return *this;
-    }
-
-    const GridTrack* m_track;
-    double m_flex;
-    LayoutUnit m_normalizedFlexValue;
-};
-
 enum TrackSizeRestriction {
     AllowInfinity,
     ForbidInfinity,
@@ -396,6 +374,11 @@
     return isFloatingOrOutOfFlowPositioned();
 }
 
+static inline double normalizedFlexFraction(const GridTrack& track, double flexFactor)
+{
+    return track.baseSize() / std::max<double>(1, flexFactor);
+}
+
 void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& freeSpace)
 {
     const LayoutUnit initialFreeSpace = freeSpace;
@@ -456,14 +439,12 @@
         return;
 
     // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
-    double normalizedFractionBreadth = 0;
+    double flexFraction = 0;
     if (!hasUndefinedRemainingSpace) {
-        normalizedFractionBreadth = computeNormalizedFractionBreadth(tracks, GridSpan(0, tracks.size() - 1), direction, initialFreeSpace);
+        flexFraction = findFlexFactorUnitSize(tracks, GridSpan(0, tracks.size() - 1), direction, initialFreeSpace);
     } else {
-        for (const auto& trackIndex : flexibleSizedTracksIndex) {
-            GridTrackSize trackSize = gridTrackSize(direction, trackIndex);
-            normalizedFractionBreadth = std::max(normalizedFractionBreadth, tracks[trackIndex].baseSize() / trackSize.maxTrackBreadth().flex());
-        }
+        for (const auto& trackIndex : flexibleSizedTracksIndex)
+            flexFraction = std::max(flexFraction, normalizedFlexFraction(tracks[trackIndex], gridTrackSize(direction, trackIndex).maxTrackBreadth().flex()));
 
         for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
             GridIterator iterator(m_grid, direction, flexibleSizedTracksIndex[i]);
@@ -475,8 +456,7 @@
                 if (i > 0 && span.resolvedInitialPosition.toInt() <= flexibleSizedTracksIndex[i - 1])
                     continue;
 
-                double itemNormalizedFlexBreadth = computeNormalizedFractionBreadth(tracks, span, direction, maxContentForChild(*gridItem, direction, sizingData.columnTracks));
-                normalizedFractionBreadth = std::max(normalizedFractionBreadth, itemNormalizedFlexBreadth);
+                flexFraction = std::max(flexFraction, findFlexFactorUnitSize(tracks, span, direction, maxContentForChild(*gridItem, direction, sizingData.columnTracks)));
             }
         }
     }
@@ -484,7 +464,7 @@
     for (const auto& trackIndex : flexibleSizedTracksIndex) {
         GridTrackSize trackSize = gridTrackSize(direction, trackIndex);
 
-        LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize(), normalizedFractionBreadth * trackSize.maxTrackBreadth().flex());
+        LayoutUnit baseSize = std::max<LayoutUnit>(tracks[trackIndex].baseSize(), flexFraction * trackSize.maxTrackBreadth().flex());
         tracks[trackIndex].setBaseSize(baseSize);
         freeSpace -= baseSize;
     }
@@ -528,59 +508,56 @@
     return valueForLength(trackLength, direction == ForColumns ? contentLogicalWidth() : std::max(LayoutUnit(), computeContentLogicalHeight(MainOrPreferredSize, style()->logicalHeight(), -1)));
 }
 
-static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track1, const GridTrackForNormalization& track2)
+double LayoutGrid::computeFlexFactorUnitSize(const Vector<GridTrack>& tracks, GridTrackSizingDirection direction, double flexFactorSum, LayoutUnit& leftOverSpace, const Vector<size_t, 8>& flexibleTracksIndexes, PassOwnPtr<TrackIndexSet> tracksToTreatAsInflexible) const
 {
-    return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue;
+    // We want to avoid the effect of flex factors sum below 1 making the factor unit size to grow exponentially.
+    double hypotheticalFactorUnitSize = leftOverSpace / std::max<double>(1, flexFactorSum);
+
+    // product of the hypothetical "flex factor unit" and any flexible track's "flex factor" must be grater than such track's "base size".
+    OwnPtr<TrackIndexSet> additionalTracksToTreatAsInflexible = tracksToTreatAsInflexible;
+    bool validFlexFactorUnit = true;
+    for (auto index : flexibleTracksIndexes) {
+        if (additionalTracksToTreatAsInflexible && additionalTracksToTreatAsInflexible->contains(index))
+            continue;
+        LayoutUnit baseSize = tracks[index].baseSize();
+        double flexFactor = gridTrackSize(direction, index).maxTrackBreadth().flex();
+        // treating all such tracks as inflexible.
+        if (baseSize > hypotheticalFactorUnitSize * flexFactor) {
+            leftOverSpace -= baseSize;
+            flexFactorSum -= flexFactor;
+            if (!additionalTracksToTreatAsInflexible)
+                additionalTracksToTreatAsInflexible = adoptPtr(new TrackIndexSet());
+            additionalTracksToTreatAsInflexible->add(index);
+            validFlexFactorUnit = false;
+        }
+    }
+    if (!validFlexFactorUnit)
+        return computeFlexFactorUnitSize(tracks, direction, flexFactorSum, leftOverSpace, flexibleTracksIndexes, additionalTracksToTreatAsInflexible.release());
+    return hypotheticalFactorUnitSize;
 }
 
-double LayoutGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, const GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit spaceToFill) const
+double LayoutGrid::findFlexFactorUnitSize(const Vector<GridTrack>& tracks, const GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit leftOverSpace) const
 {
-    LayoutUnit allocatedSpace;
-    Vector<GridTrackForNormalization> tracksForNormalization;
+    if (leftOverSpace <= 0)
+        return 0;
+
+    double flexFactorSum = 0;
+    Vector<size_t, 8> flexibleTracksIndexes;
     for (const auto& resolvedPosition : tracksSpan) {
-        GridTrack& track = tracks[resolvedPosition.toInt()];
-        allocatedSpace += track.baseSize();
-
-        GridTrackSize trackSize = gridTrackSize(direction, resolvedPosition.toInt());
-        if (!trackSize.maxTrackBreadth().isFlex())
-            continue;
-
-        tracksForNormalization.append(GridTrackForNormalization(track, trackSize.maxTrackBreadth().flex()));
+        size_t trackIndex = resolvedPosition.toInt();
+        GridTrackSize trackSize = gridTrackSize(direction, trackIndex);
+        if (!trackSize.maxTrackBreadth().isFlex()) {
+            leftOverSpace -= tracks[trackIndex].baseSize();
+        } else {
+            flexibleTracksIndexes.append(trackIndex);
+            flexFactorSum += trackSize.maxTrackBreadth().flex();
+        }
     }
 
     // The function is not called if we don't have <flex> grid tracks
-    ASSERT(!tracksForNormalization.isEmpty());
+    ASSERT(!flexibleTracksIndexes.isEmpty());
 
-    std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sortByGridNormalizedFlexValue);
-
-    // These values work together: as we walk over our grid tracks, we increase fractionValueBasedOnGridItemsRatio
-    // to match a grid track's usedBreadth to <flex> ratio until the total fractions sized grid tracks wouldn't
-    // fit into availableLogicalSpaceIgnoringFractionTracks.
-    double accumulatedFractions = 0;
-    LayoutUnit fractionValueBasedOnGridItemsRatio = 0;
-    LayoutUnit availableLogicalSpaceIgnoringFractionTracks = spaceToFill - allocatedSpace;
-
-    for (const auto& track : tracksForNormalization) {
-        if (track.m_normalizedFlexValue > fractionValueBasedOnGridItemsRatio) {
-            // If the normalized flex value (we ordered |tracksForNormalization| by increasing normalized flex value)
-            // will make us overflow our container, then stop. We have the previous step's ratio is the best fit.
-            if (track.m_normalizedFlexValue * accumulatedFractions > availableLogicalSpaceIgnoringFractionTracks)
-                break;
-
-            fractionValueBasedOnGridItemsRatio = track.m_normalizedFlexValue;
-        }
-
-        accumulatedFractions += track.m_flex;
-        // This item was processed so we re-add its used breadth to the available space to accurately count the remaining space.
-        availableLogicalSpaceIgnoringFractionTracks += track.m_track->baseSize();
-    }
-
-    // Let flex factor sum be the sum of the flex factors of the flexible tracks. If this value
-    // is less than 1, set it to 1 instead.
-    if (accumulatedFractions < 1)
-        return availableLogicalSpaceIgnoringFractionTracks;
-
-    return availableLogicalSpaceIgnoringFractionTracks / accumulatedFractions;
+    return computeFlexFactorUnitSize(tracks, direction, flexFactorSum, leftOverSpace, flexibleTracksIndexes);
 }
 
 bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) const
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h
index 5ed9a51..c5b3cc3b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.h
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -135,7 +135,9 @@
     template <TrackSizeComputationPhase> void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, const GridItemsSpanGroupRange&);
     template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, GridSizingData&, LayoutUnit& availableLogicalSpace);
 
-    double computeNormalizedFractionBreadth(Vector<GridTrack>&, const GridSpan& tracksSpan, GridTrackSizingDirection, LayoutUnit availableLogicalSpace) const;
+    typedef HashSet<size_t, DefaultHash<size_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<size_t>> TrackIndexSet;
+    double computeFlexFactorUnitSize(const Vector<GridTrack>&, GridTrackSizingDirection, double flexFactorSum, LayoutUnit& leftOverSpace, const Vector<size_t, 8>& flexibleTracksIndexes, PassOwnPtr<TrackIndexSet> tracksToTreatAsInflexible = nullptr) const;
+    double findFlexFactorUnitSize(const Vector<GridTrack>&, const GridSpan&, GridTrackSizingDirection, LayoutUnit leftOverSpace) const;
 
     GridTrackSize gridTrackSize(GridTrackSizingDirection, size_t) const;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 6b16e5a..db3f1b39 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1360,6 +1360,11 @@
     if (!RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled())
         setPreviousPositionFromPaintInvalidationBacking(newLocation);
 
+    if (!shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() && !paintInvalidationState.forcedSubtreeInvalidationWithinContainer()) {
+        ASSERT(paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinContainer());
+        return PaintInvalidationNone;
+    }
+
     PaintInvalidationReason invalidationReason = paintInvalidationReason(paintInvalidationContainer, oldBounds, oldLocation, newBounds, newLocation);
 
     // We need to invalidate the selection before checking for whether we are doing a full invalidation.
@@ -3212,7 +3217,7 @@
 {
     // paintInvalidationStateIsDirty should be kept in sync with the
     // booleans that are cleared below.
-    ASSERT(paintInvalidationState.forcedSubtreeInvalidationWithinContainer() || paintInvalidationStateIsDirty());
+    ASSERT(paintInvalidationState.forcedSubtreeInvalidationWithinContainer() || paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinContainer() || paintInvalidationStateIsDirty());
     clearShouldDoFullPaintInvalidation();
     m_bitfields.setChildShouldCheckForPaintInvalidation(false);
     m_bitfields.setNeededLayoutBecauseOfChildren(false);
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h
index 4ccfabed..afc1298 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.h
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1198,7 +1198,9 @@
         // Should check for paint invalidation if some ancestor changed location, because this object
         // may also change paint offset or location in paint invalidation container, even if there is
         // no paint invalidation flag set.
-        return paintInvalidationState.forcedSubtreeInvalidationWithinContainer() || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState();
+        return paintInvalidationState.forcedSubtreeInvalidationWithinContainer()
+            || paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinContainer()
+            || shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState();
     }
 
     bool shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() const
@@ -1376,11 +1378,11 @@
     bool containsInlineWithOutlineAndContinuation() const { return m_bitfields.containsInlineWithOutlineAndContinuation(); }
     void setContainsInlineWithOutlineAndContinuation(bool b) { m_bitfields.setContainsInlineWithOutlineAndContinuation(b); }
 
+    const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; }
+
 private:
     void fullyInvalidatePaint(const LayoutBoxModelObject& paintInvalidationContainer, PaintInvalidationReason, const LayoutRect& oldBounds, const LayoutRect& newBounds);
 
-    const LayoutRect& previousPaintInvalidationRect() const { return m_previousPaintInvalidationRect; }
-
     // Adjusts a paint invalidation rect in the space of |m_previousPaintInvalidationRect| and |m_previousPositionFromPaintInvalidationBacking|
     // to be in the space of the |paintInvalidationContainer|,
     // if needed. They can be different only if |paintInvalidationContainer| is a composited scroller.
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index 484a745..0d946974 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -1399,11 +1399,17 @@
             for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
                 LayoutTableCol* column = colElement(cell->col());
                 LayoutTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0;
+                // Table cells paint container's background on the container's backing instead of its own (if any),
+                // so we must invalidate it by the containers.
+                bool invalidated = false;
                 if ((columnGroup && columnGroup->shouldDoFullPaintInvalidation())
                     || (column && column->shouldDoFullPaintInvalidation())
-                    || section->shouldDoFullPaintInvalidation()
-                    || row->shouldDoFullPaintInvalidation())
-                    cell->invalidateDisplayItemClient(*cell);
+                    || section->shouldDoFullPaintInvalidation()) {
+                    section->invalidateDisplayItemClient(*cell);
+                    invalidated = true;
+                }
+                if ((!invalidated || row->isPaintInvalidationContainer()) && row->shouldDoFullPaintInvalidation())
+                    row->invalidateDisplayItemClient(*cell);
             }
         }
     }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index f6d5a93..22283d8b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -382,7 +382,7 @@
 
     // This map holds the collapsed border values for cells with collapsed borders.
     // It is held at LayoutTableSection level to spare memory consumption by table cells.
-    using CellsCollapsedBordersMap = HashMap<pair<const LayoutTableCell*, int>, CollapsedBorderValue>;
+    using CellsCollapsedBordersMap = HashMap<std::pair<const LayoutTableCell*, int>, CollapsedBorderValue>;
     CellsCollapsedBordersMap m_cellsCollapsedBorders;
 };
 
diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
index fa114a4..3c79090 100644
--- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
+++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
@@ -17,6 +17,7 @@
     : m_clipped(false)
     , m_cachedOffsetsEnabled(true)
     , m_forcedSubtreeInvalidationWithinContainer(false)
+    , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false)
     , m_paintInvalidationContainer(*layoutView.containerForPaintInvalidation())
     , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations)
 {
@@ -41,6 +42,7 @@
     : m_clipped(false)
     , m_cachedOffsetsEnabled(true)
     , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer)
+    , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer)
     , m_paintInvalidationContainer(paintInvalidationContainer)
     , m_pendingDelayedPaintInvalidations(next.pendingDelayedPaintInvalidationTargets())
 {
@@ -98,6 +100,7 @@
     : m_clipped(next.m_clipped)
     , m_cachedOffsetsEnabled(next.m_cachedOffsetsEnabled)
     , m_forcedSubtreeInvalidationWithinContainer(next.m_forcedSubtreeInvalidationWithinContainer)
+    , m_forcedSubtreeInvalidationRectUpdateWithinContainer(next.m_forcedSubtreeInvalidationRectUpdateWithinContainer)
     , m_clipRect(next.m_clipRect)
     , m_paintOffset(next.m_paintOffset)
     , m_paintInvalidationContainer(next.m_paintInvalidationContainer)
diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.h b/third_party/WebKit/Source/core/layout/PaintInvalidationState.h
index e43cfd6..eb418f9 100644
--- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.h
+++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.h
@@ -39,6 +39,9 @@
     bool forcedSubtreeInvalidationWithinContainer() const { return m_forcedSubtreeInvalidationWithinContainer; }
     void setForceSubtreeInvalidationWithinContainer() { m_forcedSubtreeInvalidationWithinContainer = true; }
 
+    bool forcedSubtreeInvalidationRectUpdateWithinContainer() const { return m_forcedSubtreeInvalidationRectUpdateWithinContainer; }
+    void setForceSubtreeInvalidationRectUpdateWithinContainer() { m_forcedSubtreeInvalidationRectUpdateWithinContainer = true; }
+
     const LayoutBoxModelObject& paintInvalidationContainer() const { return m_paintInvalidationContainer; }
 
     bool canMapToContainer(const LayoutBoxModelObject* container) const
@@ -61,6 +64,7 @@
     bool m_clipped;
     mutable bool m_cachedOffsetsEnabled;
     bool m_forcedSubtreeInvalidationWithinContainer;
+    bool m_forcedSubtreeInvalidationRectUpdateWithinContainer;
 
     LayoutRect m_clipRect;
 
diff --git a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
index b2c19d5..4d2bed9ce 100644
--- a/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
+++ b/third_party/WebKit/Source/core/layout/TextAutosizer.cpp
@@ -532,6 +532,9 @@
             return;
 
         LocalFrame* mainFrame = m_document->page()->deprecatedLocalMainFrame();
+        if (!mainFrame->view())
+            return;
+
         IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride();
         if (frameSize.isEmpty())
             frameSize = windowSize();
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h b/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h
index 682d8cc0..5b82f34 100644
--- a/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h
+++ b/third_party/WebKit/Source/core/layout/api/LineLayoutSVGInlineText.h
@@ -30,6 +30,17 @@
         return toSVGInlineText()->characterStartsNewTextChunk(position);
     }
 
+    float scalingFactor() const
+    {
+        return toSVGInlineText()->scalingFactor();
+    }
+
+    const Font& scaledFont() const
+    {
+        return toSVGInlineText()->scaledFont();
+    }
+
+
 private:
     LayoutSVGInlineText* toSVGInlineText()
     {
diff --git a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
index 061e927..846bca4 100644
--- a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
+++ b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
@@ -278,6 +278,12 @@
         m_currentCharacterIsSpace = false;
 
     m_current.moveToStartOf(m_nextObject);
+
+    // When the line box tree is created, this position in the line will be snapped to
+    // LayoutUnit's, and those measurements will be used by the paint code.  Do the
+    // equivalent snapping here, to get consistent line measurements.
+    m_width.snapUncommittedWidth();
+
     m_atStart = false;
 }
 
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
index 441f993..11eb3ed 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.h
@@ -38,7 +38,7 @@
 
 struct GlyphOverflow;
 
-typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow>> GlyphOverflowAndFallbackFontsMap;
+typedef HashMap<const InlineTextBox*, std::pair<Vector<const SimpleFontData*>, GlyphOverflow>> GlyphOverflowAndFallbackFontsMap;
 
 class InlineFlowBox : public InlineBox {
 public:
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
index 6982a97..be0af5b 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
@@ -187,6 +187,14 @@
 
 bool InlineTextBox::hasWrappedSelectionNewline() const
 {
+    // TODO(wkorman): We shouldn't need layout at this point and it should
+    // be enforced by DocumentLifecycle. http://crbug.com/537821
+    // Bail out as currently looking up selection state can cause the editing
+    // code can force a re-layout while scrutinizing the editing position, and
+    // InlineTextBox instances are not guaranteed to survive a re-layout.
+    if (lineLayoutItem().needsLayout())
+        return false;
+
     SelectionState state = selectionState();
     return RuntimeEnabledFeatures::selectionPaintingWithoutSelectionGapsEnabled()
         // TODO(wkorman): Remove horizontal and RTL restrictions once operational.
diff --git a/third_party/WebKit/Source/core/layout/line/LineWidth.h b/third_party/WebKit/Source/core/layout/line/LineWidth.h
index 2db3736d..89fca11d 100644
--- a/third_party/WebKit/Source/core/layout/line/LineWidth.h
+++ b/third_party/WebKit/Source/core/layout/line/LineWidth.h
@@ -54,7 +54,11 @@
         return currentWidth() - (whitespaceTreatment == ExcludeWhitespace ? trailingWhitespaceWidth() : 0) + extra <= (m_availableWidth + LayoutUnit::epsilon());
     }
 
+    // Note that m_uncommittedWidth may not be LayoutUnit-snapped at this point.  Because
+    // currentWidth() is used by the code that lays out words in a single LayoutText, it's
+    // expected that offsets will not be snapped until an InlineBox boundary is reached.
     float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
+
     // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
     float uncommittedWidth() const { return m_uncommittedWidth; }
     float committedWidth() const { return m_committedWidth; }
@@ -68,6 +72,7 @@
     void applyOverhang(LineLayoutRubyRun, LineLayoutItem startLayoutItem, LineLayoutItem endLayoutItem);
     void fitBelowFloats(bool isFirstLine = false);
     void setTrailingWhitespaceWidth(float width) { m_trailingWhitespaceWidth = width; }
+    void snapUncommittedWidth() { m_uncommittedWidth = LayoutUnit(m_uncommittedWidth).toFloat(); }
 
     bool shouldIndentText() const { return m_shouldIndentText == IndentText; }
 
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
index 9a8ec3a0..87c93ac4 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutTreeAsText.cpp
@@ -31,10 +31,10 @@
 #include "core/layout/svg/SVGLayoutTreeAsText.h"
 
 #include "core/layout/LayoutTreeAsText.h"
+#include "core/layout/api/LineLayoutSVGInlineText.h"
 #include "core/layout/line/InlineTextBox.h"
 #include "core/layout/svg/LayoutSVGGradientStop.h"
 #include "core/layout/svg/LayoutSVGImage.h"
-#include "core/layout/svg/LayoutSVGInlineText.h"
 #include "core/layout/svg/LayoutSVGResourceClipper.h"
 #include "core/layout/svg/LayoutSVGResourceFilter.h"
 #include "core/layout/svg/LayoutSVGResourceLinearGradient.h"
@@ -400,9 +400,9 @@
     if (fragments.isEmpty())
         return;
 
-    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(textBox->layoutObject());
+    LineLayoutSVGInlineText textLineLayout = LineLayoutSVGInlineText(textBox->lineLayoutItem());
 
-    const SVGComputedStyle& svgStyle = textLayoutObject.style()->svgStyle();
+    const SVGComputedStyle& svgStyle = textLineLayout.style()->svgStyle();
     String text = textBox->lineLayoutItem().text();
 
     unsigned fragmentsSize = fragments.size();
diff --git a/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp b/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
index de16c82..7fdf5d7 100644
--- a/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/line/SVGInlineTextBox.cpp
@@ -30,6 +30,7 @@
 #include "core/layout/LayoutInline.h"
 #include "core/layout/LayoutTheme.h"
 #include "core/layout/PointerEventsHitRules.h"
+#include "core/layout/api/LineLayoutSVGInlineText.h"
 #include "core/layout/line/InlineFlowBox.h"
 #include "core/layout/svg/LayoutSVGInlineText.h"
 #include "core/paint/SVGInlineTextBoxPainter.h"
@@ -77,12 +78,12 @@
 
 int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, LayoutUnit position, bool includePartialGlyphs) const
 {
-    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(this->layoutObject());
+    LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem());
 
-    float scalingFactor = textLayoutObject.scalingFactor();
+    float scalingFactor = lineLayoutItem.scalingFactor();
     ASSERT(scalingFactor);
 
-    const ComputedStyle& style = textLayoutObject.styleRef();
+    const ComputedStyle& style = lineLayoutItem.styleRef();
 
     TextRun textRun = constructTextRun(style, fragment);
 
@@ -93,7 +94,7 @@
     if (!fragmentTransform.isIdentity())
         textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
 
-    return fragment.characterOffset - start() + textLayoutObject.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
+    return fragment.characterOffset - start() + lineLayoutItem.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
 }
 
 LayoutUnit SVGInlineTextBox::positionForOffset(int) const
@@ -107,12 +108,12 @@
 {
     ASSERT(startPosition < endPosition);
 
-    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(this->layoutObject());
+    LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem());
 
-    float scalingFactor = textLayoutObject.scalingFactor();
+    float scalingFactor = lineLayoutItem.scalingFactor();
     ASSERT(scalingFactor);
 
-    const Font& scaledFont = textLayoutObject.scaledFont();
+    const Font& scaledFont = lineLayoutItem.scaledFont();
     const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
     FloatPoint textOrigin(fragment.x, fragment.y);
     if (scalingFactor != 1)
@@ -228,12 +229,12 @@
 {
     LayoutRect textRect;
 
-    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(this->layoutObject());
+    LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem());
 
-    float scalingFactor = textLayoutObject.scalingFactor();
+    float scalingFactor = lineLayoutItem.scalingFactor();
     ASSERT(scalingFactor);
 
-    LayoutUnit baseline = textLayoutObject.scaledFont().fontMetrics().floatAscent() / scalingFactor;
+    LayoutUnit baseline = lineLayoutItem.scaledFont().fontMetrics().floatAscent() / scalingFactor;
 
     AffineTransform fragmentTransform;
     unsigned textFragmentsSize = m_textFragments.size();
diff --git a/third_party/WebKit/Source/core/layout/svg/line/SVGRootInlineBox.cpp b/third_party/WebKit/Source/core/layout/svg/line/SVGRootInlineBox.cpp
index 385ce70..cf2b69a 100644
--- a/third_party/WebKit/Source/core/layout/svg/line/SVGRootInlineBox.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/line/SVGRootInlineBox.cpp
@@ -24,7 +24,7 @@
 #include "config.h"
 #include "core/layout/svg/line/SVGRootInlineBox.h"
 
-#include "core/layout/svg/LayoutSVGInlineText.h"
+#include "core/layout/api/LineLayoutSVGInlineText.h"
 #include "core/layout/svg/LayoutSVGText.h"
 #include "core/layout/svg/line/SVGInlineFlowBox.h"
 #include "core/layout/svg/line/SVGInlineTextBox.h"
@@ -165,7 +165,7 @@
     std::swap(itFirst->value, itLast->value);
 }
 
-static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, LayoutSVGInlineText* firstContext, LayoutSVGInlineText* lastContext, SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
+static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, LineLayoutSVGInlineText firstContext, LineLayoutSVGInlineText lastContext, SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
 {
     first = 0;
     last = 0;
@@ -208,12 +208,12 @@
 
         // Reordering is only necessary for BiDi text that is _absolutely_ positioned.
         if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
-            LayoutSVGInlineText& firstContext = toLayoutSVGInlineText(firstTextBox->layoutObject());
-            LayoutSVGInlineText& lastContext = toLayoutSVGInlineText(lastTextBox->layoutObject());
+            LineLayoutSVGInlineText firstContext = LineLayoutSVGInlineText(firstTextBox->lineLayoutItem());
+            LineLayoutSVGInlineText lastContext = LineLayoutSVGInlineText(lastTextBox->lineLayoutItem());
 
             SVGTextLayoutAttributes* firstAttributes = nullptr;
             SVGTextLayoutAttributes* lastAttributes = nullptr;
-            findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes);
+            findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes);
             swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
         }
 
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 3e985b4..ee3a2fc1 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -56,6 +56,7 @@
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderClient.h"
 #include "core/loader/LinkLoader.h"
+#include "core/loader/ProgressTracker.h"
 #include "core/loader/appcache/ApplicationCacheHost.h"
 #include "core/page/FrameTree.h"
 #include "core/page/Page.h"
@@ -339,6 +340,11 @@
         return true;
     if (policy == NavigationPolicyIgnore)
         return false;
+    if (policy == NavigationPolicyHandledByClient) {
+        // Mark the frame as loading since the embedder is handling the navigation.
+        frameLoader()->progress().progressStarted();
+        return false;
+    }
     if (!LocalDOMWindow::allowPopUp(*m_frame) && !UserGestureIndicator::processingUserGesture())
         return false;
     frameLoader()->client()->loadURLExternally(request, policy);
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.cpp b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
index 913b57d..75477c1 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.cpp
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
@@ -101,6 +101,11 @@
     return NavigationPolicyIgnore;
 }
 
+bool EmptyFrameLoaderClient::hasPendingNavigation()
+{
+    return false;
+}
+
 void EmptyFrameLoaderClient::dispatchWillSendSubmitEvent(HTMLFormElement*)
 {
 }
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h
index 4cb0c16..731829e7 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.h
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -207,6 +207,7 @@
     void dispatchDidChangeThemeColor() override {}
 
     NavigationPolicy decidePolicyForNavigation(const ResourceRequest&, DocumentLoader*, NavigationPolicy) override;
+    bool hasPendingNavigation() override;
 
     void dispatchWillSendSubmitEvent(HTMLFormElement*) override;
     void dispatchWillSubmitForm(HTMLFormElement*) override;
diff --git a/third_party/WebKit/Source/core/loader/FormSubmission.cpp b/third_party/WebKit/Source/core/loader/FormSubmission.cpp
index 74c3c6b..2c957c6 100644
--- a/third_party/WebKit/Source/core/loader/FormSubmission.cpp
+++ b/third_party/WebKit/Source/core/loader/FormSubmission.cpp
@@ -208,7 +208,7 @@
             isMultiPartForm = false;
         }
     }
-    WTF::TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataEncoder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document.charset(), document.defaultCharset());
+    WTF::TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataEncoder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document.characterSet(), document.defaultCharset());
     FormData* domFormData = FormData::create(dataEncoding.encodingForFormSubmission());
 
     bool containsPasswordData = false;
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 4d2b6031..d452037 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -551,9 +551,14 @@
     if (frame->loader().provisionalDocumentLoader())
         return false;
 
+    // A navigation is still scheduled in the embedder, so don't complete yet.
+    if (frame->loader().client()->hasPendingNavigation())
+        return false;
+
     // We might have declined to run the load event due to an imminent content-initiated navigation.
     if (!frame->document()->loadEventFinished())
         return false;
+
     return true;
 }
 
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
index a722e88..72155e46 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
+++ b/third_party/WebKit/Source/core/loader/FrameLoaderClient.h
@@ -98,6 +98,7 @@
     virtual void dispatchDidChangeThemeColor() = 0;
 
     virtual NavigationPolicy decidePolicyForNavigation(const ResourceRequest&, DocumentLoader*, NavigationPolicy) = 0;
+    virtual bool hasPendingNavigation() = 0;
 
     virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) = 0;
     virtual void dispatchWillSubmitForm(HTMLFormElement*) = 0;
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.h b/third_party/WebKit/Source/core/loader/ImageLoader.h
index 84678d1..37a0b76 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.h
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.h
@@ -106,6 +106,11 @@
         return m_hasPendingLoadEvent || m_hasPendingErrorEvent || m_pendingTask;
     }
 
+    bool hasPendingError() const
+    {
+        return m_hasPendingErrorEvent;
+    }
+
     void dispatchPendingEvent(ImageEventSender*);
 
     static void dispatchPendingLoadEvents();
diff --git a/third_party/WebKit/Source/core/loader/NavigationPolicy.h b/third_party/WebKit/Source/core/loader/NavigationPolicy.h
index 7489425..20fae8db 100644
--- a/third_party/WebKit/Source/core/loader/NavigationPolicy.h
+++ b/third_party/WebKit/Source/core/loader/NavigationPolicy.h
@@ -43,6 +43,7 @@
     NavigationPolicyNewForegroundTab,
     NavigationPolicyNewWindow,
     NavigationPolicyNewPopup,
+    NavigationPolicyHandledByClient,
 };
 
 CORE_EXPORT bool navigationPolicyFromMouseEvent(unsigned short button, bool ctrl, bool shift, bool alt, bool meta, NavigationPolicy*);
diff --git a/third_party/WebKit/Source/core/page/PageSerializer.cpp b/third_party/WebKit/Source/core/page/PageSerializer.cpp
index 96d4a42..a847813 100644
--- a/third_party/WebKit/Source/core/page/PageSerializer.cpp
+++ b/third_party/WebKit/Source/core/page/PageSerializer.cpp
@@ -164,7 +164,7 @@
         result.appendLiteral("<meta http-equiv=\"Content-Type\" content=\"");
         MarkupFormatter::appendAttributeValue(result, m_document->suggestedMIMEType(), m_document->isHTMLDocument());
         result.appendLiteral("; charset=");
-        MarkupFormatter::appendAttributeValue(result, m_document->charset(), m_document->isHTMLDocument());
+        MarkupFormatter::appendAttributeValue(result, m_document->characterSet(), m_document->isHTMLDocument());
         if (m_document->isXHTMLDocument())
             result.appendLiteral("\" />");
         else
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 657e59e..86e3467 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -342,13 +342,8 @@
 // FIXME: Instead of hardcode here, we should make a setting flag.
 #if OS(MACOSX)
     static const bool platformSupportsCoordinatedScrollbar = ScrollAnimatorMac::canUseCoordinatedScrollbar();
-    static const bool platformSupportsMainFrameOnly = false; // Don't care.
-#elif OS(ANDROID)
-    static const bool platformSupportsCoordinatedScrollbar = true;
-    static const bool platformSupportsMainFrameOnly = false;
 #else
     static const bool platformSupportsCoordinatedScrollbar = true;
-    static const bool platformSupportsMainFrameOnly = true;
 #endif
 
     bool isMainFrame = isForMainFrame(scrollableArea);
@@ -356,8 +351,7 @@
         ? scrollableArea->layerForHorizontalScrollbar()
         : scrollableArea->layerForVerticalScrollbar();
 
-    bool shouldCreateCoordinatedScrollbar = platformSupportsCoordinatedScrollbar && !(platformSupportsMainFrameOnly && !isMainFrame);
-    if (!shouldCreateCoordinatedScrollbar) {
+    if (!platformSupportsCoordinatedScrollbar) {
         if (scrollbarGraphicsLayer) {
             WebLayer* scrollbarLayer = toWebLayer(scrollbarGraphicsLayer);
             scrollbarLayer->setShouldScrollOnMainThread(true);
diff --git a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainter.cpp
index 1d3ec1d..e036df4 100644
--- a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainter.cpp
@@ -220,28 +220,8 @@
     if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !m_paintLayer.layoutObject()->isLayoutView() && !m_paintLayer.layoutObject()->isDocumentElement())
         return result;
 
-    Optional<SubsequenceRecorder> subsequenceRecorder;
-
-    bool scrollOffsetAccumulationChanged = paintingInfoArg.scrollOffsetAccumulation != m_paintLayer.previousScrollOffsetAccumulationForPainting();
-    if (scrollOffsetAccumulationChanged)
-        m_paintLayer.setPreviousScrollOffsetAccumulationForPainting(paintingInfoArg.scrollOffsetAccumulation);
-
-    if (!isPaintingOverlayScrollbars
-        && !paintingInfoArg.disableSubsequenceCache
-        && !(paintingInfoArg.globalPaintFlags() & GlobalPaintFlattenCompositingLayers)
-        && !(paintFlags & PaintLayerPaintingReflection)
-        && !(paintFlags & PaintLayerPaintingRootBackgroundOnly)) {
-        if (!scrollOffsetAccumulationChanged && !m_paintLayer.needsRepaint() && SubsequenceRecorder::useCachedSubsequenceIfPossible(*context, m_paintLayer))
-            return result;
-        subsequenceRecorder.emplace(*context, m_paintLayer);
-    }
-
     DeprecatedPaintLayerPaintingInfo paintingInfo = paintingInfoArg;
 
-    if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()
-        && (m_paintLayer.layoutObject()->hasOverflowClip() || m_paintLayer.layoutObject()->hasClip()))
-        paintingInfo.disableSubsequenceCache = true;
-
     // Ensure our lists are up-to-date.
     m_paintLayer.stackingNode()->updateLayerListsIfNeeded();
 
@@ -356,10 +336,7 @@
         paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForLayoutObject, paintFlags);
     }
 
-    // Set subsequence not cacheable if the bounding box of this layer and descendants is not fully contained
-    // by paintRect, because later paintRect changes may expose new contents which will need repainting.
-    if (result == MaybeNotFullyPainted && subsequenceRecorder)
-        subsequenceRecorder->setUncacheable();
+    m_paintLayer.setPreviousScrollOffsetAccumulationForPainting(paintingInfoArg.scrollOffsetAccumulation);
 
     return result;
 }
@@ -492,12 +469,39 @@
     LayerListMutationDetector mutationChecker(m_paintLayer.stackingNode());
 #endif
 
-    IntSize scrollOffsetAccumulation = paintingInfo.scrollOffsetAccumulation;
-    if (m_paintLayer.layoutObject()->hasOverflowClip())
-        scrollOffsetAccumulation += m_paintLayer.layoutBox()->scrolledContentOffset();
-
     DeprecatedPaintLayerStackingNodeIterator iterator(*m_paintLayer.stackingNode(), childrenToVisit);
-    while (DeprecatedPaintLayerStackingNode* child = iterator.next()) {
+    DeprecatedPaintLayerStackingNode* child = iterator.next();
+    if (!child)
+        return result;
+
+    DisplayItem::Type subsequenceType;
+    if (childrenToVisit == NegativeZOrderChildren) {
+        subsequenceType = DisplayItem::SubsequenceNegativeZOrder;
+    } else {
+        ASSERT(childrenToVisit == (NormalFlowChildren | PositiveZOrderChildren));
+        subsequenceType = DisplayItem::SubsequenceNormalFlowAndPositiveZOrder;
+    }
+
+    Optional<SubsequenceRecorder> subsequenceRecorder;
+    if (!paintingInfo.disableSubsequenceCache
+        && !(paintingInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers)
+        && !(paintFlags & PaintLayerPaintingReflection)
+        && !(paintFlags & PaintLayerPaintingRootBackgroundOnly)) {
+        if (!m_paintLayer.needsRepaint()
+            && paintingInfo.scrollOffsetAccumulation == m_paintLayer.previousScrollOffsetAccumulationForPainting()
+            && SubsequenceRecorder::useCachedSubsequenceIfPossible(*context, m_paintLayer, subsequenceType))
+            return result;
+        subsequenceRecorder.emplace(*context, m_paintLayer, subsequenceType);
+    }
+
+    IntSize scrollOffsetAccumulationForChildren = paintingInfo.scrollOffsetAccumulation;
+    if (m_paintLayer.layoutObject()->hasOverflowClip())
+        scrollOffsetAccumulationForChildren += m_paintLayer.layoutBox()->scrolledContentOffset();
+
+    bool disableChildSubsequenceCache = !RuntimeEnabledFeatures::slimmingPaintV2Enabled()
+        && (m_paintLayer.layoutObject()->hasOverflowClip() || m_paintLayer.layoutObject()->hasClip());
+
+    for (; child; child = iterator.next()) {
         DeprecatedPaintLayerPainter childPainter(*child->layer());
         // If this Layer should paint into its own backing or a grouped backing, that will be done via CompositedDeprecatedPaintLayerMapping::paintContents()
         // and CompositedDeprecatedPaintLayerMapping::doPaintTask().
@@ -505,7 +509,8 @@
             continue;
 
         DeprecatedPaintLayerPaintingInfo childPaintingInfo = paintingInfo;
-        childPaintingInfo.scrollOffsetAccumulation = scrollOffsetAccumulation;
+        childPaintingInfo.disableSubsequenceCache = disableChildSubsequenceCache;
+        childPaintingInfo.scrollOffsetAccumulation = scrollOffsetAccumulationForChildren;
         // Rare case: accumulate scroll offset of non-stacking-context ancestors up to m_paintLayer.
         for (DeprecatedPaintLayer* parentLayer = child->layer()->parent(); parentLayer != &m_paintLayer; parentLayer = parentLayer->parent()) {
             if (parentLayer->layoutObject()->hasOverflowClip())
@@ -515,6 +520,12 @@
         if (childPainter.paintLayer(context, childPaintingInfo, paintFlags) == MaybeNotFullyPainted)
             result = MaybeNotFullyPainted;
     }
+
+    // Set subsequence not cacheable if the bounding box of this layer and descendants is not fully contained
+    // by paintRect, because later paintRect changes may expose new contents which will need repainting.
+    if (result == MaybeNotFullyPainted && subsequenceRecorder)
+        subsequenceRecorder->setUncacheable();
+
     return result;
 }
 
diff --git a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainterTest.cpp
index 63d65e3..4aa102d8 100644
--- a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerPainterTest.cpp
@@ -17,11 +17,11 @@
     RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(true);
 
     setBodyInnerHTML(
-        "<div id='container1' style='position: relative; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content1' style='width: 100px; height: 100px; background-color: red'></div>"
+        "<div id='container1' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content1' style='position: absolute; width: 100px; height: 100px; background-color: red'></div>"
         "</div>"
-        "<div id='container2' style='position: relative; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content2' style='width: 100px; height: 100px; background-color: green'></div>"
+        "<div id='container2' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content2' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
         "</div>");
     document().view()->updateAllLifecyclePhases();
 
@@ -40,74 +40,76 @@
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
-    toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 100px; background-color: green");
+    toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green");
     document().view()->updateAllLifecyclePhases();
     DeprecatedPaintLayerPainter(rootLayer).paintLayerContents(&context, paintingInfo, PaintLayerPaintingCompositingAllPhases);
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 10,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 11,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, cachedBackgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, cachedBackgroundType),
+        TestDisplayItem(container2Layer, cachedSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     // Repeated painting should just generate the root cached subsequence.
     DeprecatedPaintLayerPainter(rootLayer).paintLayerContents(&context, paintingInfo, PaintLayerPaintingCompositingAllPhases);
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 1,
-        TestDisplayItem(rootLayer, DisplayItem::CachedSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 2,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, cachedSubsequenceType));
 
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 TEST_F(DeprecatedPaintLayerPainterTest, CachedSubsequenceOnInterestRectChange)
@@ -115,21 +117,29 @@
     RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(true);
 
     setBodyInnerHTML(
-        "<div id='container1' style='position: relative; width: 200px; height: 200px; background-color: blue'></div>"
-        "<div id='container2' style='position: absolute; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content2' style='position: relative; top: 200px; width: 100px; height: 100px; background-color: green'></div>"
+        "<div id='container1' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content1' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
         "</div>"
-        "<div id='container3' style='position: absolute; z-index: 2; left: 300px; top: 0; width: 200px; height: 200px; background-color: blue'></div>");
+        "<div id='container2' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content2a' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
+        "  <div id='content2b' style='position: absolute; top: 200px; width: 100px; height: 100px; background-color: green'></div>"
+        "</div>"
+        "<div id='container3' style='position: absolute; z-index: 2; left: 300px; top: 0; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content3' style='position: absolute; width: 200px; height: 200px; background-color: green'></div>"
+        "</div>");
     rootDisplayItemList().invalidateAll();
 
     DeprecatedPaintLayer& rootLayer = *layoutView().layer();
     DeprecatedPaintLayer& htmlLayer = *toLayoutBoxModelObject(document().documentElement()->layoutObject())->layer();
     LayoutObject& container1 = *document().getElementById("container1")->layoutObject();
     DeprecatedPaintLayer& container1Layer = *toLayoutBoxModelObject(container1).layer();
+    LayoutObject& content1 = *document().getElementById("content1")->layoutObject();
     LayoutObject& container2 = *document().getElementById("container2")->layoutObject();
     DeprecatedPaintLayer& container2Layer = *toLayoutBoxModelObject(container2).layer();
+    LayoutObject& content2a = *document().getElementById("content2a")->layoutObject();
     LayoutObject& container3 = *document().getElementById("container3")->layoutObject();
     DeprecatedPaintLayer& container3Layer = *toLayoutBoxModelObject(container3).layer();
+    LayoutObject& content3 = *document().getElementById("content3")->layoutObject();
 
     document().view()->updateAllLifecyclePhases();
     GraphicsContext context(&rootDisplayItemList());
@@ -139,67 +149,74 @@
 
     // Container1 is fully in the interest rect;
     // Container2 is partly (including its stacking chidren) in the interest rect;
-    // Content2 is out of the interest rect and output nothing;
-    // Container3 is fully in the interest rect.
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 14,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container3Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container3, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container3Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    // Content2b is out of the interest rect and output nothing;
+    // Container3 is partly in the interest rect.
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 17,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(container3, backgroundType),
+        TestDisplayItem(container3Layer, subsequenceType),
+        TestDisplayItem(content3, backgroundType),
+        TestDisplayItem(container3Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     // Container1 becomes partly in the interest rect, but uses cached subsequence
     // because it was fully painted before;
     // Container2's intersection with the interest rect changes;
-    // Content2 is out of the interest rect and outputs nothing;
+    // Content2b is out of the interest rect and outputs nothing;
     // Container3 becomes out of the interest rect and outputs nothing.
     DeprecatedPaintLayerPaintingInfo paintingInfo1(&rootLayer, LayoutRect(0, 100, 300, 300), GlobalPaintNormalPhase, LayoutSize());
     DeprecatedPaintLayerPainter(rootLayer).paintLayerContents(&context, paintingInfo1, PaintLayerPaintingCompositingAllPhases);
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 9,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 11,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, cachedBackgroundType),
+        TestDisplayItem(container1Layer, cachedSubsequenceType),
+        TestDisplayItem(container2, cachedBackgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, cachedBackgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     rootDisplayItemList().commitNewDisplayItems();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 11,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 TEST_F(DeprecatedPaintLayerPainterTestForSlimmingPaintV2, CachedSubsequence)
 {
     setBodyInnerHTML(
-        "<div id='container1' style='position: relative; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content1' style='width: 100px; height: 100px; background-color: red'></div>"
+        "<div id='container1' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content1' style='position: absolute; width: 100px; height: 100px; background-color: red'></div>"
         "</div>"
-        "<div id='container2' style='position: relative; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content2' style='width: 100px; height: 100px; background-color: green'></div>"
+        "<div id='container2' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content2' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
         "</div>");
     document().view()->updateAllLifecyclePhases();
 
@@ -213,148 +230,168 @@
     LayoutObject& content2 = *document().getElementById("content2")->layoutObject();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
-    toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 100px; background-color: green");
-    updateLifecyclePhasesToPaintForSlimmingPaintV2Clean(LayoutRect::infiniteRect());
+    toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green");
+    updateLifecyclePhasesToPaintClean(LayoutRect::infiniteRect());
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 10,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 11,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, cachedBackgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, cachedBackgroundType),
+        TestDisplayItem(container2Layer, cachedSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     compositeForSlimmingPaintV2();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     // Repeated painting should just generate the root cached subsequence.
-    updateLifecyclePhasesToPaintForSlimmingPaintV2Clean();
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 1,
-        TestDisplayItem(rootLayer, DisplayItem::CachedSubsequence));
+    setNeedsDisplayWithoutInvalidationForRoot();
+    updateLifecyclePhasesToPaintClean();
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 2,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, cachedSubsequenceType));
 
     compositeForSlimmingPaintV2();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(content2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 TEST_F(DeprecatedPaintLayerPainterTestForSlimmingPaintV2, CachedSubsequenceOnInterestRectChange)
 {
     setBodyInnerHTML(
-        "<div id='container1' style='position: relative; width: 200px; height: 200px; background-color: blue'></div>"
-        "<div id='container2' style='position: absolute; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
-        "  <div id='content2' style='position: relative; top: 200px; width: 100px; height: 100px; background-color: green'></div>"
+        "<div id='container1' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content1' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
         "</div>"
-        "<div id='container3' style='position: absolute; z-index: 2; left: 300px; top: 0; width: 200px; height: 200px; background-color: blue'></div>");
-    rootDisplayItemList().invalidateAll();
+        "<div id='container2' style='position: relative; z-index: 1; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content2a' style='position: absolute; width: 100px; height: 100px; background-color: green'></div>"
+        "  <div id='content2b' style='position: absolute; top: 200px; width: 100px; height: 100px; background-color: green'></div>"
+        "</div>"
+        "<div id='container3' style='position: absolute; z-index: 2; left: 300px; top: 0; width: 200px; height: 200px; background-color: blue'>"
+        "  <div id='content3' style='position: absolute; width: 200px; height: 200px; background-color: green'></div>"
+        "</div>");
+    setNeedsDisplayForRoot();
 
     DeprecatedPaintLayer& rootLayer = *layoutView().layer();
     DeprecatedPaintLayer& htmlLayer = *toLayoutBoxModelObject(document().documentElement()->layoutObject())->layer();
     LayoutObject& container1 = *document().getElementById("container1")->layoutObject();
     DeprecatedPaintLayer& container1Layer = *toLayoutBoxModelObject(container1).layer();
+    LayoutObject& content1 = *document().getElementById("content1")->layoutObject();
     LayoutObject& container2 = *document().getElementById("container2")->layoutObject();
     DeprecatedPaintLayer& container2Layer = *toLayoutBoxModelObject(container2).layer();
+    LayoutObject& content2a = *document().getElementById("content2a")->layoutObject();
     LayoutObject& container3 = *document().getElementById("container3")->layoutObject();
     DeprecatedPaintLayer& container3Layer = *toLayoutBoxModelObject(container3).layer();
+    LayoutObject& content3 = *document().getElementById("content3")->layoutObject();
 
     document().view()->updateAllLifecyclePhases(LayoutRect(0, 0, 400, 300));
 
     // Container1 is fully in the interest rect;
     // Container2 is partly (including its stacking chidren) in the interest rect;
-    // Content2 is out of the interest rect and output nothing;
-    // Container3 is fully in the interest rect.
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 14,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container3Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container3, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container3Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    // Content2b is out of the interest rect and output nothing;
+    // Container3 is partly in the interest rect.
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 17,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(container3, backgroundType),
+        TestDisplayItem(container3Layer, subsequenceType),
+        TestDisplayItem(content3, backgroundType),
+        TestDisplayItem(container3Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
+    setNeedsDisplayWithoutInvalidationForRoot();
+    
     // Container1 becomes partly in the interest rect, but uses cached subsequence
     // because it was fully painted before;
     // Container2's intersection with the interest rect changes;
-    // Content2 is out of the interest rect and outputs nothing;
+    // Content2b is out of the interest rect and outputs nothing;
     // Container3 becomes out of the interest rect and outputs nothing.
-    updateLifecyclePhasesToPaintForSlimmingPaintV2Clean(LayoutRect(0, 100, 300, 300));
+    updateLifecyclePhasesToPaintClean(LayoutRect(0, 100, 300, 300));
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 9,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::BoxDecorationBackground)),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().newDisplayItems(), 11,
+        TestDisplayItem(layoutView(), cachedBackgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, cachedBackgroundType),
+        TestDisplayItem(container1Layer, cachedSubsequenceType),
+        TestDisplayItem(container2, cachedBackgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, cachedBackgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     compositeForSlimmingPaintV2();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 11,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container1, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container1Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2Layer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(container2, DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(container2Layer, DisplayItem::EndSubsequence),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 13,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(htmlLayer, subsequenceType),
+        TestDisplayItem(container1, backgroundType),
+        TestDisplayItem(container1Layer, subsequenceType),
+        TestDisplayItem(content1, backgroundType),
+        TestDisplayItem(container1Layer, endSubsequenceType),
+        TestDisplayItem(container2, backgroundType),
+        TestDisplayItem(container2Layer, subsequenceType),
+        TestDisplayItem(content2a, backgroundType),
+        TestDisplayItem(container2Layer, endSubsequenceType),
+        TestDisplayItem(htmlLayer, endSubsequenceType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.cpp
index 0e412652..19a06df 100644
--- a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.cpp
@@ -88,6 +88,7 @@
     , m_nextTopmostScrollChild(0)
     , m_topmostScrollChild(0)
     , m_needsCompositedScrolling(false)
+    , m_scrollbarManager(*this)
     , m_scrollCorner(nullptr)
     , m_resizer(nullptr)
 #if ENABLE(ASSERT)
@@ -142,8 +143,7 @@
             frameView->removeResizerArea(box());
     }
 
-    destroyScrollbar(HorizontalScrollbar);
-    destroyScrollbar(VerticalScrollbar);
+    m_scrollbarManager.dispose();
 
     if (m_scrollCorner)
         m_scrollCorner->destroy();
@@ -159,8 +159,7 @@
 
 DEFINE_TRACE(DeprecatedPaintLayerScrollableArea)
 {
-    visitor->trace(m_hBar);
-    visitor->trace(m_vBar);
+    visitor->trace(m_scrollbarManager);
     ScrollableArea::trace(visitor);
 }
 
@@ -205,15 +204,15 @@
     // See crbug.com/343132.
     DisableCompositingQueryAsserts disabler;
 
-    ASSERT(scrollbar == m_hBar.get() || scrollbar == m_vBar.get());
-    ASSERT(scrollbar == m_hBar.get() ? !layerForHorizontalScrollbar() : !layerForVerticalScrollbar());
+    ASSERT(scrollbar == horizontalScrollbar() || scrollbar == verticalScrollbar());
+    ASSERT(scrollbar == horizontalScrollbar() ? !layerForHorizontalScrollbar() : !layerForVerticalScrollbar());
 
     IntRect scrollRect = rect;
     // If we are not yet inserted into the tree, there is no need to issue paint invaldiations.
     if (!box().isLayoutView() && !box().parent())
         return;
 
-    if (scrollbar == m_vBar.get())
+    if (scrollbar == verticalScrollbar())
         scrollRect.move(verticalScrollbarStart(0, box().size().width()), box().borderTop());
     else
         scrollRect.move(horizontalScrollbarStart(0), box().size().height() - box().borderBottom() - scrollbar->height());
@@ -653,12 +652,13 @@
     ASSERT(box().hasOverflowClip());
 
     if (needsScrollbarReconstruction()) {
-        if (m_hBar)
-            destroyScrollbar(HorizontalScrollbar);
-        if (m_vBar)
-            destroyScrollbar(VerticalScrollbar);
+        m_scrollbarManager.setCanDetachScrollbars(false);
+        setHasHorizontalScrollbar(false);
+        setHasVerticalScrollbar(false);
     }
 
+    m_scrollbarManager.setCanDetachScrollbars(true);
+
     scrollOffset = adjustedScrollOffset();
     computeScrollDimensions();
     bool hasHorizontalOverflow = this->hasHorizontalOverflow();
@@ -674,10 +674,14 @@
     autoHorizontalScrollBarChanged = (box().hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow)) || (box().style()->overflowX() == OSCROLL && !horizontalScrollbar());
     autoVerticalScrollBarChanged = (box().hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow)) || (box().style()->overflowY() == OSCROLL && !verticalScrollbar());
     if (!visualViewportSuppliesScrollbars() && (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged)) {
-        if (box().hasAutoHorizontalScrollbar() || (box().style()->overflowX() == OSCROLL && !horizontalScrollbar()))
-            setHasHorizontalScrollbar(box().style()->overflowX() == OSCROLL ? true : hasHorizontalOverflow);
-        if (box().hasAutoVerticalScrollbar() || (box().style()->overflowY() == OSCROLL && !verticalScrollbar()))
-            setHasVerticalScrollbar(box().style()->overflowY() == OSCROLL ? true : hasVerticalOverflow);
+        if (box().hasAutoHorizontalScrollbar())
+            setHasHorizontalScrollbar(hasHorizontalOverflow);
+        else if (box().style()->overflowX() == OSCROLL)
+            setHasHorizontalScrollbar(true);
+        if (box().hasAutoVerticalScrollbar())
+            setHasVerticalScrollbar(hasVerticalOverflow);
+        else if (box().style()->overflowX() == OSCROLL)
+            setHasVerticalScrollbar(true);
     }
 }
 
@@ -696,6 +700,8 @@
         scrollPositionChanged(-origin + adjustedScrollOffset(), ProgrammaticScroll);
     }
 
+    m_scrollbarManager.setCanDetachScrollbars(false);
+
     bool hasHorizontalOverflow = this->hasHorizontalOverflow();
     bool hasVerticalOverflow = this->hasVerticalOverflow();
 
@@ -869,19 +875,19 @@
     // When switching to another value, we need to re-enable them (see bug 11985).
     if (needsHorizontalScrollbar && oldStyle && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) {
         ASSERT(hasHorizontalScrollbar());
-        m_hBar->setEnabled(true);
+        horizontalScrollbar()->setEnabled(true);
     }
 
     if (needsVerticalScrollbar && oldStyle && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) {
         ASSERT(hasVerticalScrollbar());
-        m_vBar->setEnabled(true);
+        verticalScrollbar()->setEnabled(true);
     }
 
     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
-    if (m_hBar)
-        m_hBar->styleChanged();
-    if (m_vBar)
-        m_vBar->styleChanged();
+    if (horizontalScrollbar())
+        horizontalScrollbar()->styleChanged();
+    if (verticalScrollbar())
+        verticalScrollbar()->styleChanged();
 
     updateScrollCornerStyle();
     updateResizerAreaSet();
@@ -919,27 +925,27 @@
 
 IntRect DeprecatedPaintLayerScrollableArea::rectForHorizontalScrollbar(const IntRect& borderBoxRect) const
 {
-    if (!m_hBar)
+    if (!hasHorizontalScrollbar())
         return IntRect();
 
     const IntRect& scrollCorner = scrollCornerRect();
 
     return IntRect(horizontalScrollbarStart(borderBoxRect.x()),
-        borderBoxRect.maxY() - box().borderBottom() - m_hBar->height(),
+        borderBoxRect.maxY() - box().borderBottom() - horizontalScrollbar()->height(),
         borderBoxRect.width() - (box().borderLeft() + box().borderRight()) - scrollCorner.width(),
-        m_hBar->height());
+        horizontalScrollbar()->height());
 }
 
 IntRect DeprecatedPaintLayerScrollableArea::rectForVerticalScrollbar(const IntRect& borderBoxRect) const
 {
-    if (!m_vBar)
+    if (!hasVerticalScrollbar())
         return IntRect();
 
     const IntRect& scrollCorner = scrollCornerRect();
 
     return IntRect(verticalScrollbarStart(borderBoxRect.x(), borderBoxRect.maxX()),
         borderBoxRect.y() + box().borderTop(),
-        m_vBar->width(),
+        verticalScrollbar()->width(),
         borderBoxRect.height() - (box().borderTop() + box().borderBottom()) - scrollCorner.height());
 }
 
@@ -947,23 +953,23 @@
 {
     if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
         return minX + box().borderLeft();
-    return maxX - box().borderRight() - m_vBar->width();
+    return maxX - box().borderRight() - verticalScrollbar()->width();
 }
 
 LayoutUnit DeprecatedPaintLayerScrollableArea::horizontalScrollbarStart(int minX) const
 {
     int x = minX + box().borderLeft();
     if (box().style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
-        x += m_vBar ? m_vBar->width() : resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer).width();
+        x += hasVerticalScrollbar() ? verticalScrollbar()->width() : resizerCornerRect(box().pixelSnappedBorderBoxRect(), ResizerForPointer).width();
     return x;
 }
 
 IntSize DeprecatedPaintLayerScrollableArea::scrollbarOffset(const Scrollbar* scrollbar) const
 {
-    if (scrollbar == m_vBar.get())
+    if (scrollbar == verticalScrollbar())
         return IntSize(verticalScrollbarStart(0, box().size().width()), box().borderTop());
 
-    if (scrollbar == m_hBar.get())
+    if (scrollbar == horizontalScrollbar())
         return IntSize(horizontalScrollbarStart(0), box().size().height() - box().borderBottom() - scrollbar->height());
 
     ASSERT_NOT_REACHED();
@@ -1009,68 +1015,25 @@
     LayoutObject* actualLayoutObject = layoutObjectForScrollbar(box());
     bool shouldUseCustom = actualLayoutObject->isBox() && actualLayoutObject->style()->hasPseudoStyle(SCROLLBAR);
     bool hasAnyScrollbar = hasScrollbar();
-    bool hasCustom = (m_hBar && m_hBar->isCustomScrollbar()) || (m_vBar && m_vBar->isCustomScrollbar());
+    bool hasCustom = (hasHorizontalScrollbar() && horizontalScrollbar()->isCustomScrollbar()) || (hasVerticalScrollbar() && verticalScrollbar()->isCustomScrollbar());
     return hasAnyScrollbar && (shouldUseCustom != hasCustom);
 }
 
-PassRefPtrWillBeRawPtr<Scrollbar> DeprecatedPaintLayerScrollableArea::createScrollbar(ScrollbarOrientation orientation)
-{
-    RefPtrWillBeRawPtr<Scrollbar> widget = nullptr;
-    LayoutObject* actualLayoutObject = layoutObjectForScrollbar(box());
-    bool hasCustomScrollbarStyle = actualLayoutObject->isBox() && actualLayoutObject->style()->hasPseudoStyle(SCROLLBAR);
-    if (hasCustomScrollbarStyle) {
-        widget = LayoutScrollbar::createCustomScrollbar(this, orientation, actualLayoutObject->node());
-    } else {
-        ScrollbarControlSize scrollbarSize = RegularScrollbar;
-        if (actualLayoutObject->style()->hasAppearance())
-            scrollbarSize = LayoutTheme::theme().scrollbarControlSizeForPart(actualLayoutObject->style()->appearance());
-        widget = Scrollbar::create(this, orientation, scrollbarSize);
-        if (orientation == HorizontalScrollbar)
-            didAddScrollbar(widget.get(), HorizontalScrollbar);
-        else
-            didAddScrollbar(widget.get(), VerticalScrollbar);
-    }
-    box().document().view()->addChild(widget.get());
-    return widget.release();
-}
-
-void DeprecatedPaintLayerScrollableArea::destroyScrollbar(ScrollbarOrientation orientation)
-{
-    RefPtrWillBeMember<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
-    if (!scrollbar)
-        return;
-
-    if (!scrollbar->isCustomScrollbar())
-        willRemoveScrollbar(scrollbar.get(), orientation);
-
-    toFrameView(scrollbar->parent())->removeChild(scrollbar.get());
-    scrollbar->disconnectFromScrollableArea();
-    scrollbar = nullptr;
-}
-
 void DeprecatedPaintLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
 {
     if (hasScrollbar == hasHorizontalScrollbar())
         return;
 
-    if (hasScrollbar) {
-        // This doesn't hit in any tests, but since the equivalent code in setHasVerticalScrollbar
-        // does, presumably this code does as well.
-        DisableCompositingQueryAsserts disabler;
-        m_hBar = createScrollbar(HorizontalScrollbar);
-    } else {
-        if (!layerForHorizontalScrollbar())
-            m_hBar->invalidate();
-        // Otherwise we will remove the layer and just need recompositing.
+    if (!hasScrollbar && !layerForHorizontalScrollbar())
+        horizontalScrollbar()->invalidate();
 
-        destroyScrollbar(HorizontalScrollbar);
-    }
+    m_scrollbarManager.setHasHorizontalScrollbar(hasScrollbar);
 
     // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
-    if (m_hBar)
-        m_hBar->styleChanged();
-    if (m_vBar)
-        m_vBar->styleChanged();
+    if (hasHorizontalScrollbar())
+        horizontalScrollbar()->styleChanged();
+    if (hasVerticalScrollbar())
+        verticalScrollbar()->styleChanged();
 
     // These are valid because we want to invalidate display item clients on the current backing.
     DisablePaintInvalidationStateAsserts paintInvalidationAssertDisabler;
@@ -1087,23 +1050,16 @@
     if (hasScrollbar == hasVerticalScrollbar())
         return;
 
-    if (hasScrollbar) {
-        // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html
-        DisableCompositingQueryAsserts disabler;
-        m_vBar = createScrollbar(VerticalScrollbar);
-    } else {
-        if (!layerForVerticalScrollbar())
-            m_vBar->invalidate();
-        // Otherwise we will remove the layer and just need recompositing.
+    if (!hasScrollbar && !layerForVerticalScrollbar())
+        verticalScrollbar()->invalidate();
 
-        destroyScrollbar(VerticalScrollbar);
-    }
+    m_scrollbarManager.setHasVerticalScrollbar(hasScrollbar);
 
     // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
-    if (m_hBar)
-        m_hBar->styleChanged();
-    if (m_vBar)
-        m_vBar->styleChanged();
+    if (hasHorizontalScrollbar())
+        horizontalScrollbar()->styleChanged();
+    if (hasVerticalScrollbar())
+        verticalScrollbar()->styleChanged();
 
     // These are valid because we want to invalidate display item clients on the current backing.
     DisablePaintInvalidationStateAsserts paintInvalidationAssertDisabler;
@@ -1117,16 +1073,16 @@
 
 int DeprecatedPaintLayerScrollableArea::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
 {
-    if (!m_vBar || (m_vBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_vBar->shouldParticipateInHitTesting())))
+    if (!hasVerticalScrollbar() || (verticalScrollbar()->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !verticalScrollbar()->shouldParticipateInHitTesting())))
         return 0;
-    return m_vBar->width();
+    return verticalScrollbar()->width();
 }
 
 int DeprecatedPaintLayerScrollableArea::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
 {
-    if (!m_hBar || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_hBar->shouldParticipateInHitTesting())))
+    if (!hasHorizontalScrollbar() || (horizontalScrollbar()->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !horizontalScrollbar()->shouldParticipateInHitTesting())))
         return 0;
-    return m_hBar->height();
+    return horizontalScrollbar()->height();
 }
 
 void DeprecatedPaintLayerScrollableArea::positionOverflowControls()
@@ -1189,25 +1145,25 @@
     }
 
     int resizeControlSize = max(resizeControlRect.height(), 0);
-    if (m_vBar && m_vBar->shouldParticipateInHitTesting()) {
+    if (hasVerticalScrollbar() && verticalScrollbar()->shouldParticipateInHitTesting()) {
         LayoutRect vBarRect(verticalScrollbarStart(0, box().size().width()),
             box().borderTop(),
-            m_vBar->width(),
-            box().size().height() - (box().borderTop() + box().borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+            verticalScrollbar()->width(),
+            box().size().height() - (box().borderTop() + box().borderBottom()) - (hasHorizontalScrollbar() ? horizontalScrollbar()->height() : resizeControlSize));
         if (vBarRect.contains(localPoint)) {
-            result.setScrollbar(m_vBar.get());
+            result.setScrollbar(verticalScrollbar());
             return true;
         }
     }
 
     resizeControlSize = max(resizeControlRect.width(), 0);
-    if (m_hBar && m_hBar->shouldParticipateInHitTesting()) {
+    if (hasHorizontalScrollbar() && horizontalScrollbar()->shouldParticipateInHitTesting()) {
         LayoutRect hBarRect(horizontalScrollbarStart(0),
-            box().size().height() - box().borderBottom() - m_hBar->height(),
-            box().size().width() - (box().borderLeft() + box().borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
-            m_hBar->height());
+            box().size().height() - box().borderBottom() - horizontalScrollbar()->height(),
+            box().size().width() - (box().borderLeft() + box().borderRight()) - (hasVerticalScrollbar() ? verticalScrollbar()->width() : resizeControlSize),
+            horizontalScrollbar()->height());
         if (hBarRect.contains(localPoint)) {
-            result.setScrollbar(m_hBar.get());
+            result.setScrollbar(horizontalScrollbar());
             return true;
         }
     }
@@ -1508,4 +1464,108 @@
     return frame->settings()->viewportMetaEnabled();
 }
 
+DeprecatedPaintLayerScrollableArea::ScrollbarManager::ScrollbarManager(DeprecatedPaintLayerScrollableArea& scrollableArea)
+    : m_scrollableArea(&scrollableArea)
+    , m_canDetachScrollbars(0)
+    , m_hBarIsAttached(0)
+    , m_vBarIsAttached(0)
+{
+}
+
+void DeprecatedPaintLayerScrollableArea::ScrollbarManager::dispose()
+{
+    m_canDetachScrollbars = m_hBarIsAttached = m_vBarIsAttached = 0;
+    destroyScrollbar(HorizontalScrollbar);
+    destroyScrollbar(VerticalScrollbar);
+}
+
+void DeprecatedPaintLayerScrollableArea::ScrollbarManager::setCanDetachScrollbars(bool detach)
+{
+    ASSERT(!m_hBarIsAttached || m_hBar);
+    ASSERT(!m_vBarIsAttached || m_vBar);
+    m_canDetachScrollbars = detach ? 1 : 0;
+    if (!detach) {
+        if (m_hBar && !m_hBarIsAttached)
+            destroyScrollbar(HorizontalScrollbar, true);
+        if (m_vBar && !m_vBarIsAttached)
+            destroyScrollbar(VerticalScrollbar, true);
+    }
+}
+
+void DeprecatedPaintLayerScrollableArea::ScrollbarManager::setHasHorizontalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar) {
+        // This doesn't hit in any tests, but since the equivalent code in setHasVerticalScrollbar
+        // does, presumably this code does as well.
+        DisableCompositingQueryAsserts disabler;
+        if (!m_hBar)
+            m_hBar = createScrollbar(HorizontalScrollbar);
+        m_hBarIsAttached = 1;
+    } else {
+        m_hBarIsAttached = 0;
+        if (!m_canDetachScrollbars)
+            destroyScrollbar(HorizontalScrollbar);
+    }
+}
+
+void DeprecatedPaintLayerScrollableArea::ScrollbarManager::setHasVerticalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar) {
+        DisableCompositingQueryAsserts disabler;
+        if (!m_vBar)
+            m_vBar = createScrollbar(VerticalScrollbar);
+        m_vBarIsAttached = 1;
+    } else {
+        m_vBarIsAttached = 0;
+        if (!m_canDetachScrollbars)
+            destroyScrollbar(VerticalScrollbar);
+    }
+}
+
+PassRefPtrWillBeRawPtr<Scrollbar> DeprecatedPaintLayerScrollableArea::ScrollbarManager::createScrollbar(ScrollbarOrientation orientation)
+{
+    ASSERT(orientation == HorizontalScrollbar ? !m_hBarIsAttached : !m_vBarIsAttached);
+    RefPtrWillBeRawPtr<Scrollbar> widget = nullptr;
+    LayoutObject* actualLayoutObject = layoutObjectForScrollbar(m_scrollableArea->box());
+    bool hasCustomScrollbarStyle = actualLayoutObject->isBox() && actualLayoutObject->style()->hasPseudoStyle(SCROLLBAR);
+    if (hasCustomScrollbarStyle) {
+        widget = LayoutScrollbar::createCustomScrollbar(m_scrollableArea.get(), orientation, actualLayoutObject->node());
+    } else {
+        ScrollbarControlSize scrollbarSize = RegularScrollbar;
+        if (actualLayoutObject->style()->hasAppearance())
+            scrollbarSize = LayoutTheme::theme().scrollbarControlSizeForPart(actualLayoutObject->style()->appearance());
+        widget = Scrollbar::create(m_scrollableArea.get(), orientation, scrollbarSize);
+        if (orientation == HorizontalScrollbar)
+            m_scrollableArea->didAddScrollbar(widget.get(), HorizontalScrollbar);
+        else
+            m_scrollableArea->didAddScrollbar(widget.get(), VerticalScrollbar);
+    }
+    m_scrollableArea->box().document().view()->addChild(widget.get());
+    return widget.release();
+}
+
+void DeprecatedPaintLayerScrollableArea::ScrollbarManager::destroyScrollbar(ScrollbarOrientation orientation, bool invalidate)
+{
+    RefPtrWillBeMember<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
+    ASSERT(orientation == HorizontalScrollbar ? !m_hBarIsAttached: !m_vBarIsAttached);
+    if (!scrollbar)
+        return;
+
+    if (invalidate)
+        scrollbar->invalidate();
+    if (!scrollbar->isCustomScrollbar())
+        m_scrollableArea->willRemoveScrollbar(scrollbar.get(), orientation);
+
+    toFrameView(scrollbar->parent())->removeChild(scrollbar.get());
+    scrollbar->disconnectFromScrollableArea();
+    scrollbar = nullptr;
+}
+
+DEFINE_TRACE(DeprecatedPaintLayerScrollableArea::ScrollbarManager)
+{
+    visitor->trace(m_scrollableArea);
+    visitor->trace(m_hBar);
+    visitor->trace(m_vBar);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.h
index cb28579f..2e1f5af 100644
--- a/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/DeprecatedPaintLayerScrollableArea.h
@@ -67,6 +67,55 @@
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DeprecatedPaintLayerScrollableArea);
     friend class Internals;
 
+private:
+    class ScrollbarManager {
+        DISALLOW_ALLOCATION();
+
+        // Helper class to manage the life cycle of Scrollbar objects.  Some layout containers
+        // (e.g., flexbox, table) run multi-pass layout on their children, applying different
+        // constraints.  If a child has overflow:auto, it may gain and lose scrollbars multiple
+        // times during multi-pass layout, causing pointless allocation/deallocation thrashing,
+        // and potentially leading to other problems (crbug.com/528940).
+
+        // ScrollbarManager allows a ScrollableArea to delay the destruction of a scrollbar that
+        // is no longer needed, until the end of multi-pass layout.  If the scrollbar is then
+        // re-added before multi-pass layout finishes, the previously "deleted" scrollbar will
+        // be restored, rather than constructing a new one.
+    public:
+        ScrollbarManager(DeprecatedPaintLayerScrollableArea&);
+
+        void dispose();
+
+        // When canDetachScrollbars is true, calls to setHas*Scrollbar(false) will NOT destroy
+        // an existing scrollbar, but instead detach it without destroying it.  If, subsequently,
+        // setHas*Scrollbar(true) is called, the existing scrollbar will be reattached.  When
+        // setCanDetachScrollbars(false) is called, any detached scrollbars will be destructed.
+        bool canDetachScrollbars() const { return m_canDetachScrollbars; }
+        void setCanDetachScrollbars(bool);
+
+        Scrollbar* horizontalScrollbar() const { return m_hBarIsAttached ? m_hBar.get(): nullptr; }
+        Scrollbar* verticalScrollbar() const { return m_vBarIsAttached ? m_vBar.get() : nullptr; }
+        bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
+        bool hasVerticalScrollbar() const { return verticalScrollbar(); }
+
+        void setHasHorizontalScrollbar(bool hasScrollbar);
+        void setHasVerticalScrollbar(bool hasScrollbar);
+
+        DECLARE_TRACE();
+
+    private:
+        PassRefPtrWillBeRawPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
+        void destroyScrollbar(ScrollbarOrientation, bool invalidate = false);
+
+    private:
+        RawPtrWillBeMember<DeprecatedPaintLayerScrollableArea> m_scrollableArea;
+        RefPtrWillBeMember<Scrollbar> m_hBar;
+        RefPtrWillBeMember<Scrollbar> m_vBar;
+        unsigned m_canDetachScrollbars: 1;
+        unsigned m_hBarIsAttached: 1;
+        unsigned m_vBarIsAttached: 1;
+    };
+
 public:
     // FIXME: We should pass in the LayoutBox but this opens a window
     // for crashers during DeprecatedPaintLayer setup (see crbug.com/368062).
@@ -81,8 +130,8 @@
     bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
     bool hasVerticalScrollbar() const { return verticalScrollbar(); }
 
-    Scrollbar* horizontalScrollbar() const override { return m_hBar.get(); }
-    Scrollbar* verticalScrollbar() const override { return m_vBar.get(); }
+    Scrollbar* horizontalScrollbar() const override { return m_scrollbarManager.horizontalScrollbar(); }
+    Scrollbar* verticalScrollbar() const override { return m_scrollbarManager.verticalScrollbar(); }
 
     HostWindow* hostWindow() const override;
 
@@ -162,7 +211,7 @@
 
     bool updateAfterCompositingChange() override;
 
-    bool hasScrollbar() const { return m_hBar || m_vBar; }
+    bool hasScrollbar() const { return hasHorizontalScrollbar() || hasVerticalScrollbar(); }
 
     LayoutScrollbarPart* scrollCorner() const { return m_scrollCorner; }
 
@@ -254,9 +303,6 @@
     LayoutUnit horizontalScrollbarStart(int minX) const;
     IntSize scrollbarOffset(const Scrollbar*) const;
 
-    PassRefPtrWillBeRawPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
-    void destroyScrollbar(ScrollbarOrientation);
-
     void setHasHorizontalScrollbar(bool hasScrollbar);
     void setHasVerticalScrollbar(bool hasScrollbar);
 
@@ -289,15 +335,14 @@
     // The width/height of our scrolled area.
     LayoutRect m_overflowRect;
 
+    // ScrollbarManager holds the Scrollbar instances.
+    ScrollbarManager m_scrollbarManager;
+
     // This is the (scroll) offset from scrollOrigin().
     DoubleSize m_scrollOffset;
 
     IntPoint m_cachedOverlayScrollbarOffset;
 
-    // For areas with overflow, we have a pair of scrollbars.
-    RefPtrWillBeMember<Scrollbar> m_hBar;
-    RefPtrWillBeMember<Scrollbar> m_vBar;
-
     // LayoutObject to hold our custom scroll corner.
     LayoutScrollbarPart* m_scrollCorner;
 
diff --git a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.cpp b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.cpp
index 14f7035..b9532fa 100644
--- a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.cpp
+++ b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.cpp
@@ -31,8 +31,8 @@
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 2,
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(textInlineBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(textInlineBox, foregroundType));
 
     div.focus();
     document().view()->updateAllLifecyclePhases();
@@ -43,8 +43,8 @@
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 3,
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(textInlineBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(textInlineBox, foregroundType),
         TestDisplayItem(divLayoutObject, DisplayItem::Caret)); // New!
 }
 
@@ -64,8 +64,8 @@
     rootDisplayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 2,
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(firstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(firstTextBox, foregroundType));
 
     div.setAttribute(HTMLNames::styleAttr, "width: 10px; height: 200px");
     document().view()->updateAllLifecyclePhases();
@@ -80,9 +80,9 @@
     InlineTextBox& secondTextBox = *newText.firstTextBox()->nextTextBox();
 
     EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 3,
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(newFirstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
-        TestDisplayItem(secondTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)));
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(newFirstTextBox, foregroundType),
+        TestDisplayItem(secondTextBox, foregroundType));
 }
 
 TEST_F(DisplayItemListPaintTestForSlimmingPaintV2, FullDocumentPaintingWithCaret)
@@ -91,39 +91,33 @@
     document().page()->focusController().setActive(true);
     document().page()->focusController().setFocused(true);
     DeprecatedPaintLayer& rootLayer = *layoutView().layer();
-    DeprecatedPaintLayer& htmlLayer = *toLayoutBoxModelObject(document().documentElement()->layoutObject())->layer();
     Element& div = *toElement(document().body()->firstChild());
     LayoutObject& divLayoutObject = *document().body()->firstChild()->layoutObject();
     InlineTextBox& textInlineBox = *toLayoutText(div.firstChild()->layoutObject())->firstTextBox();
 
     document().view()->updateAllLifecyclePhases();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 6,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(textInlineBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 4,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(textInlineBox, foregroundType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     div.focus();
     document().view()->updateAllLifecyclePhases();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 7,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(textInlineBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 5,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(textInlineBox, foregroundType),
         TestDisplayItem(divLayoutObject, DisplayItem::Caret), // New!
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 TEST_F(DisplayItemListPaintTestForSlimmingPaintV2, InlineRelayout)
 {
     setBodyInnerHTML("<div id='div' style='width:100px; height: 200px'>AAAAAAAAAA BBBBBBBBBB</div>");
     DeprecatedPaintLayer& rootLayer = *layoutView().layer();
-    DeprecatedPaintLayer& htmlLayer = *toLayoutBoxModelObject(document().documentElement()->layoutObject())->layer();
     Element& div = *toElement(document().body()->firstChild());
     LayoutBlock& divBlock = *toLayoutBlock(document().body()->firstChild()->layoutObject());
     LayoutText& text = *toLayoutText(divBlock.firstChild());
@@ -131,13 +125,11 @@
 
     document().view()->updateAllLifecyclePhases();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 6,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(firstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 4,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(firstTextBox, foregroundType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 
     div.setAttribute(HTMLNames::styleAttr, "width: 10px; height: 200px");
     document().view()->updateAllLifecyclePhases();
@@ -146,14 +138,12 @@
     InlineTextBox& newFirstTextBox = *newText.firstTextBox();
     InlineTextBox& secondTextBox = *newText.firstTextBox()->nextTextBox();
 
-    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 7,
-        TestDisplayItem(rootLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(layoutView(), DisplayItem::BoxDecorationBackground),
-        TestDisplayItem(htmlLayer, DisplayItem::BeginSubsequence),
-        TestDisplayItem(newFirstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
-        TestDisplayItem(secondTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
-        TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence),
-        TestDisplayItem(rootLayer, DisplayItem::EndSubsequence));
+    EXPECT_DISPLAY_LIST(rootDisplayItemList().displayItems(), 5,
+        TestDisplayItem(layoutView(), backgroundType),
+        TestDisplayItem(rootLayer, subsequenceType),
+        TestDisplayItem(newFirstTextBox, foregroundType),
+        TestDisplayItem(secondTextBox, foregroundType),
+        TestDisplayItem(rootLayer, endSubsequenceType));
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h
index c0729f0..28d3e76 100644
--- a/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h
+++ b/third_party/WebKit/Source/core/paint/DisplayItemListPaintTest.h
@@ -30,8 +30,6 @@
     {
         RenderingTest::SetUp();
         enableCompositing();
-        // TODO(wangxianzhu): Update the test expectations when we enable the feature permanently.
-        RuntimeEnabledFeatures::setSlimmingPaintSubsequenceCachingEnabled(false);
     }
     void TearDown() override
     {
@@ -53,13 +51,21 @@
 protected:
     LayoutView& layoutView() { return *document().layoutView(); }
     DisplayItemList& rootDisplayItemList() { return *layoutView().layer()->graphicsLayerBacking()->displayItemList(); }
+    void setNeedsDisplayForRoot()
+    {
+        layoutView().layer()->graphicsLayerBacking()->setNeedsDisplay();
+    }
+    void setNeedsDisplayWithoutInvalidationForRoot()
+    {
+        layoutView().layer()->graphicsLayerBacking()->setNeedsDisplayWithoutInvalidateForTesting();
+    }
 
     // Expose some document lifecycle steps for checking new display items before commiting.
-    void updateLifecyclePhasesToPaintForSlimmingPaintV2Clean(const LayoutRect& interestRect = LayoutRect::infiniteRect())
+    void updateLifecyclePhasesToPaintClean(const LayoutRect& interestRect = LayoutRect::infiniteRect())
     {
         document().view()->updateLifecyclePhasesInternal(FrameView::OnlyUpToCompositingCleanPlusScrolling);
         document().view()->invalidateTreeIfNeededRecursive();
-        document().view()->paintForSlimmingPaintV2(interestRect);
+        document().view()->synchronizedPaint(interestRect);
     }
     void compositeForSlimmingPaintV2() { document().view()->compositeForSlimmingPaintV2(); }
 
@@ -111,6 +117,15 @@
         } \
     } while (false);
 
+// Shorter names for frequently used display item types in tests.
+const DisplayItem::Type backgroundType = DisplayItem::BoxDecorationBackground;
+const DisplayItem::Type cachedBackgroundType = DisplayItem::drawingTypeToCachedDrawingType(backgroundType);
+const DisplayItem::Type foregroundType = DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground);
+const DisplayItem::Type cachedForegroundType = DisplayItem::drawingTypeToCachedDrawingType(foregroundType);
+const DisplayItem::Type subsequenceType = DisplayItem::SubsequenceNormalFlowAndPositiveZOrder;
+const DisplayItem::Type endSubsequenceType = DisplayItem::subsequenceTypeToEndSubsequenceType(subsequenceType);
+const DisplayItem::Type cachedSubsequenceType = DisplayItem::subsequenceTypeToCachedSubsequenceType(subsequenceType);
+
 } // namespace blink
 
 #endif // DisplayItemListPaintTest_h
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
index 2bb26c9..93f9734 100644
--- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -488,17 +488,10 @@
     int selHeight = std::max(0, roundToInt(selectionBottom - selectionTop));
 
     FloatPoint localOrigin(boxRect.x().toFloat(), (boxRect.y() - deltaY).toFloat());
-
-    LayoutUnit selectionWidth = m_inlineTextBox.logicalWidth();
     LayoutRect selectionRect = LayoutRect(font.selectionRectForText(textRun, localOrigin, selHeight, sPos, ePos));
-    if (m_inlineTextBox.hasWrappedSelectionNewline()) {
+    if (m_inlineTextBox.hasWrappedSelectionNewline())
         expandToIncludeNewlineForSelection(selectionRect);
-        // TODO(wkorman): Make this work with RTL and vertical text.
-        selectionWidth += m_inlineTextBox.newlineSpaceWidth();
-    }
-    FloatRect clipRect(localOrigin, FloatSize(selectionWidth.toFloat(), selHeight));
-    // TODO(wkorman): Experiment with not clipping.
-    context->clip(clipRect);
+
     context->fillRect(FloatRect(selectionRect), c);
 }
 
diff --git a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp
index dc04baf..6653fb7 100644
--- a/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFEConvolveMatrixElement.cpp
@@ -66,8 +66,7 @@
     ASSERT(contextElement());
     if (parseError == NoError && (firstInteger()->baseValue()->value() < 1 || secondInteger()->baseValue()->value() < 1)) {
         contextElement()->document().accessSVGExtensions().reportWarning(
-            "feConvolveMatrix: problem parsing order=\"" + value
-            + "\". Filtered element will not be displayed.");
+            "feConvolveMatrix: problem parsing order=\"" + value + "\".");
     }
 }
 
@@ -166,36 +165,25 @@
 
     int orderXValue = orderX()->currentValue()->value();
     int orderYValue = orderY()->currentValue()->value();
-    if (!hasAttribute(SVGNames::orderAttr)) {
+    if (!m_order->isSpecified()) {
         orderXValue = 3;
         orderYValue = 3;
     }
-    // Spec says order must be > 0. Bail if it is not.
-    if (orderXValue < 1 || orderYValue < 1)
-        return nullptr;
-    RefPtrWillBeRawPtr<SVGNumberList> kernelMatrix = this->m_kernelMatrix->currentValue();
-    size_t kernelMatrixSize = kernelMatrix->length();
-    // The spec says this is a requirement, and should bail out if fails
-    if (orderXValue * orderYValue != static_cast<int>(kernelMatrixSize))
-        return nullptr;
 
     int targetXValue = m_targetX->currentValue()->value();
-    int targetYValue = m_targetY->currentValue()->value();
-    if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue))
-        return nullptr;
     // The spec says the default value is: targetX = floor ( orderX / 2 ))
-    if (!hasAttribute(SVGNames::targetXAttr))
+    if (!m_targetX->isSpecified())
         targetXValue = static_cast<int>(floorf(orderXValue / 2));
-    if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue))
-        return nullptr;
+
+    int targetYValue = m_targetY->currentValue()->value();
     // The spec says the default value is: targetY = floor ( orderY / 2 ))
-    if (!hasAttribute(SVGNames::targetYAttr))
+    if (!m_targetY->isSpecified())
         targetYValue = static_cast<int>(floorf(orderYValue / 2));
 
     float divisorValue = m_divisor->currentValue()->value();
-    if (hasAttribute(SVGNames::divisorAttr) && !divisorValue)
-        return nullptr;
-    if (!hasAttribute(SVGNames::divisorAttr)) {
+    if (!m_divisor->isSpecified()) {
+        RefPtrWillBeRawPtr<SVGNumberList> kernelMatrix = m_kernelMatrix->currentValue();
+        size_t kernelMatrixSize = kernelMatrix->length();
         for (size_t i = 0; i < kernelMatrixSize; ++i)
             divisorValue += kernelMatrix->at(i)->value();
         if (!divisorValue)
diff --git a/third_party/WebKit/Source/core/svg/SVGParserUtilities.h b/third_party/WebKit/Source/core/svg/SVGParserUtilities.h
index 476fbabb..3254da1 100644
--- a/third_party/WebKit/Source/core/svg/SVGParserUtilities.h
+++ b/third_party/WebKit/Source/core/svg/SVGParserUtilities.h
@@ -27,7 +27,7 @@
 #include "platform/text/ParserUtilities.h"
 #include "wtf/HashSet.h"
 
-typedef pair<unsigned, unsigned> UnicodeRange;
+typedef std::pair<unsigned, unsigned> UnicodeRange;
 typedef Vector<UnicodeRange> UnicodeRanges;
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
index ca35671..fce14cf 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -106,26 +106,6 @@
     return SVGRectTearOff::create(SVGRect::create(), 0, PropertyIsNotAnimVal);
 }
 
-float SVGSVGElement::pixelUnitToMillimeterX() const
-{
-    return 1 / cssPixelsPerMillimeter;
-}
-
-float SVGSVGElement::pixelUnitToMillimeterY() const
-{
-    return 1 / cssPixelsPerMillimeter;
-}
-
-float SVGSVGElement::screenPixelToMillimeterX() const
-{
-    return pixelUnitToMillimeterX();
-}
-
-float SVGSVGElement::screenPixelToMillimeterY() const
-{
-    return pixelUnitToMillimeterY();
-}
-
 SVGViewSpec* SVGSVGElement::currentView()
 {
     if (!m_viewSpec)
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.h b/third_party/WebKit/Source/core/svg/SVGSVGElement.h
index dfa58222..7b90b426 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.h
@@ -57,11 +57,6 @@
     // 'SVGSVGElement' functions
     PassRefPtrWillBeRawPtr<SVGRectTearOff> viewport() const;
 
-    float pixelUnitToMillimeterX() const;
-    float pixelUnitToMillimeterY() const;
-    float screenPixelToMillimeterX() const;
-    float screenPixelToMillimeterY() const;
-
     bool useCurrentView() const { return m_useCurrentView; }
     SVGViewSpec* currentView();
 
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.idl b/third_party/WebKit/Source/core/svg/SVGSVGElement.idl
index 4884885..c565ac39f 100644
--- a/third_party/WebKit/Source/core/svg/SVGSVGElement.idl
+++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.idl
@@ -69,10 +69,6 @@
 
     // TODO(philipj): The following was part of SVG 1.1:
     // http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGSVGElement
-    [Measure] readonly attribute float pixelUnitToMillimeterX;
-    [Measure] readonly attribute float pixelUnitToMillimeterY;
-    [Measure] readonly attribute float screenPixelToMillimeterX;
-    [Measure] readonly attribute float screenPixelToMillimeterY;
     [Measure] Element getElementById(DOMString elementId);
 };
 
diff --git a/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.h b/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.h
index 3282f393..c4e5a18 100644
--- a/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.h
+++ b/third_party/WebKit/Source/core/svg/animation/SMILTimeContainer.h
@@ -131,7 +131,7 @@
     Timer<SMILTimeContainer> m_wakeupTimer;
     Timer<SMILTimeContainer> m_animationPolicyOnceTimer;
 
-    using ElementAttributePair = pair<RawPtrWillBeWeakMember<SVGElement>, QualifiedName>;
+    using ElementAttributePair = std::pair<RawPtrWillBeWeakMember<SVGElement>, QualifiedName>;
     using AnimationsLinkedHashSet = WillBeHeapLinkedHashSet<RawPtrWillBeWeakMember<SVGSMILElement>>;
     using GroupedAnimationsMap = WillBeHeapHashMap<ElementAttributePair, OwnPtrWillBeMember<AnimationsLinkedHashSet>>;
     GroupedAnimationsMap m_scheduledAnimations;
diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
index a41bdd15..c1ba3fc 100644
--- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
+++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFEImage.cpp
@@ -190,18 +190,17 @@
     if (auto* layoutObject = referencedLayoutObject())
         return createImageFilterForLayoutObject(*layoutObject, builder);
 
-    FloatRect dstRect = filterPrimitiveSubregion();
-
     RefPtr<SkImage> image = m_image ? m_image->imageForCurrentFrame() : nullptr;
     if (!image) {
         // "A href reference that is an empty image (zero width or zero height), that fails
         // to download, is non-existent, or that cannot be displayed (e.g. because it is
         // not in a supported image format) fills the filter primitive subregion with
         // transparent black."
-        return adoptRef(SkPictureImageFilter::Create(nullptr, dstRect));
+        return createTransparentBlack(builder);
     }
 
     FloatRect srcRect = FloatRect(FloatPoint(), m_image->size());
+    FloatRect dstRect = filterPrimitiveSubregion();
 
     m_preserveAspectRatio->transformRect(dstRect, srcRect);
 
diff --git a/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp b/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
index 1f80b26..e3e79bc 100644
--- a/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
+++ b/third_party/WebKit/Source/core/testing/NullExecutionContext.cpp
@@ -39,7 +39,7 @@
     return DOMTimer::visiblePageAlignmentInterval();
 }
 
-bool NullExecutionContext::isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck privilegeContextCheck) const
+bool NullExecutionContext::isSecureContext(String& errorMessage, const SecureContextCheck privilegeContextCheck) const
 {
     return true;
 }
diff --git a/third_party/WebKit/Source/core/testing/NullExecutionContext.h b/third_party/WebKit/Source/core/testing/NullExecutionContext.h
index d5197a50..cc995631 100644
--- a/third_party/WebKit/Source/core/testing/NullExecutionContext.h
+++ b/third_party/WebKit/Source/core/testing/NullExecutionContext.h
@@ -42,7 +42,7 @@
     void addConsoleMessage(PassRefPtrWillBeRawPtr<ConsoleMessage>) override { }
     void logExceptionToConsole(const String& errorMessage, int scriptId, const String& sourceURL, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack>) override { }
 
-    bool isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck = StandardPrivilegeCheck) const override;
+    bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const override;
 
     DEFINE_INLINE_TRACE()
     {
diff --git a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
index 40be89c33..a319b17d 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceResourceTiming.cpp
@@ -32,6 +32,7 @@
 #include "config.h"
 #include "core/timing/PerformanceResourceTiming.h"
 
+#include "core/timing/PerformanceBase.h"
 #include "platform/network/ResourceRequest.h"
 #include "platform/network/ResourceResponse.h"
 #include "platform/network/ResourceTimingInfo.h"
@@ -43,7 +44,7 @@
     ASSERT(seconds >= 0.0);
     if (!seconds)
         return 0.0;
-    return (seconds - timeOrigin) * 1000.0;
+    return PerformanceBase::clampTimeResolution(seconds - timeOrigin) * 1000.0;
 }
 
 PerformanceResourceTiming::PerformanceResourceTiming(const ResourceTimingInfo& info, double timeOrigin, double startTime, double lastRedirectEndTime, bool allowTimingDetails, bool allowRedirectDetails)
diff --git a/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp b/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp
index ce7df6b..52f8333 100644
--- a/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp
+++ b/third_party/WebKit/Source/core/timing/PerformanceTiming.cpp
@@ -39,6 +39,7 @@
 #include "core/loader/DocumentLoadTiming.h"
 #include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoader.h"
+#include "core/timing/PerformanceBase.h"
 #include "platform/network/ResourceLoadTiming.h"
 #include "platform/network/ResourceResponse.h"
 
@@ -47,7 +48,8 @@
 static unsigned long long toIntegerMilliseconds(double seconds)
 {
     ASSERT(seconds >= 0);
-    return static_cast<unsigned long long>(seconds * 1000.0);
+    double clampedSeconds = PerformanceBase::clampTimeResolution(seconds);
+    return static_cast<unsigned long long>(clampedSeconds * 1000.0);
 }
 
 static double toDoubleSeconds(unsigned long long integerMilliseconds)
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index e7c4d2e..a1cb643 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -359,12 +359,12 @@
         addConsoleMessage(consoleMessage.release());
 }
 
-bool WorkerGlobalScope::isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck privilegeContextCheck) const
+bool WorkerGlobalScope::isSecureContext(String& errorMessage, const SecureContextCheck privilegeContextCheck) const
 {
     // Until there are APIs that are available in workers and that
     // require a privileged context test that checks ancestors, just do
     // a simple check here. Once we have a need for a real
-    // |isPrivilegedContext| check here, we can check the responsible
+    // |isSecureContext| check here, we can check the responsible
     // document for a privileged context at worker creation time, pass
     // it in via WorkerThreadStartupData, and check it here.
     return securityOrigin()->isPotentiallyTrustworthy(errorMessage);
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
index a4a092be..b7ffa07 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -139,7 +139,7 @@
 
     virtual void scriptLoaded(size_t scriptSize, size_t cachedMetadataSize) { }
 
-    bool isPrivilegedContext(String& errorMessage, const PrivilegeContextCheck = StandardPrivilegeCheck) const override;
+    bool isSecureContext(String& errorMessage, const SecureContextCheck = StandardSecureContextCheck) const override;
 
     DECLARE_VIRTUAL_TRACE();
 
diff --git a/third_party/WebKit/Source/devtools/.devtools b/third_party/WebKit/Source/devtools/.devtools
new file mode 100644
index 0000000..089072f
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/.devtools
@@ -0,0 +1,9 @@
+{
+    "mappings": [
+        { "folder": "/front_end/", "url": "chrome-devtools://devtools/bundled/" }
+    ],
+
+    "excludes": [
+        "/front_end/Images/"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 7998969a5..ba54512 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -167,7 +167,6 @@
             'front_end/sdk/WorkerManager.js',
         ],
         'devtools_workspace_js_files': [
-            'front_end/workspace/ExcludedFolderManager.js',
             'front_end/workspace/FileManager.js',
             'front_end/workspace/FileSystemMapping.js',
             'front_end/workspace/IsolatedFileSystem.js',
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationControlPane.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationControlPane.js
index 4469dca..0cc3da5 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationControlPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationControlPane.js
@@ -61,18 +61,17 @@
     _updateAnimationsPlaybackRate: function(event)
     {
         /**
-         * @param {?Protocol.Error} error
          * @param {number} playbackRate
          * @this {WebInspector.AnimationControlPane}
          */
-        function setPlaybackRate(error, playbackRate)
+        function setPlaybackRate(playbackRate)
         {
             this._animationsPlaybackSlider.value = WebInspector.AnimationTimeline.GlobalPlaybackRates.indexOf(playbackRate);
             this._animationsPlaybackLabel.textContent = playbackRate + "x";
         }
 
         if (this._target)
-            this._target.animationAgent().getPlaybackRate(setPlaybackRate.bind(this));
+            WebInspector.AnimationModel.fromTarget(this._target).playbackRatePromise().then(setPlaybackRate.bind(this));
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
index 3938c54..d388b6d 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
@@ -75,6 +75,26 @@
     },
 
     /**
+     * @return {!Promise.<number>}
+     */
+    playbackRatePromise: function()
+    {
+        /**
+         * @param {?Protocol.Error} error
+         * @param {number} playbackRate
+         * @return {number}
+         */
+        function callback(error, playbackRate)
+        {
+            if (error)
+                return 1;
+            return playbackRate;
+        }
+
+        return this._agent.getPlaybackRate(callback).catchException(1);
+    },
+
+    /**
      * @param {number} playbackRate
      */
     setPlaybackRate: function(playbackRate)
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
index e8a2b96..a2c4cfb1 100644
--- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
+++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -228,24 +228,18 @@
     _updateAnimationsPlaybackRate: function()
     {
         /**
-         * @param {?Protocol.Error} error
          * @param {number} playbackRate
          * @this {WebInspector.AnimationTimeline}
          */
-        function setPlaybackRate(error, playbackRate)
+        function syncPlaybackRate(playbackRate)
         {
-            if (playbackRate === 0) {
-                playbackRate = 1;
-                if (target)
-                    WebInspector.AnimationModel.fromTarget(target).setPlaybackRate(1);
-            }
             this._underlyingPlaybackRate = playbackRate;
             this._updatePlaybackControls();
         }
 
         delete this._paused;
         for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page))
-            target.animationAgent().getPlaybackRate(setPlaybackRate.bind(this));
+            WebInspector.AnimationModel.fromTarget(target).playbackRatePromise().then(syncPlaybackRate.bind(this));
     },
 
     /**
@@ -329,6 +323,10 @@
     {
         this._reset();
         this._updateAnimationsPlaybackRate();
+        if (this._underlyingPlaybackRate === 0) {
+            this._underlyingPlaybackRate = 1;
+            this._updatePlaybackControls();
+        }
         if (this._scrubberPlayer)
             this._scrubberPlayer.cancel();
         delete this._scrubberPlayer;
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/FileSystemWorkspaceBinding.js b/third_party/WebKit/Source/devtools/front_end/bindings/FileSystemWorkspaceBinding.js
index e852a40c..d4e51a1 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/FileSystemWorkspaceBinding.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/FileSystemWorkspaceBinding.js
@@ -198,6 +198,20 @@
         callback.call(null, files);
         delete this._callbacks[requestId];
     },
+
+    dispose: function()
+    {
+        this._isolatedFileSystemManager.removeEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, this._fileSystemAdded, this);
+        this._isolatedFileSystemManager.removeEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this);
+        InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this);
+        InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAPI.Events.IndexingWorked, this._onIndexingWorked, this);
+        InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAPI.Events.IndexingDone, this._onIndexingDone, this);
+        InspectorFrontendHost.events.removeEventListener(InspectorFrontendHostAPI.Events.SearchCompleted, this._onSearchCompleted, this);
+        for (var fileSystem of this._boundFileSystems.values()) {
+            fileSystem.dispose();
+            this._boundFileSystems.remove(fileSystem._fileSystem.normalizedPath());
+        }
+    }
 }
 
 /**
@@ -515,7 +529,7 @@
      */
     excludeFolder: function(path)
     {
-        this._fileSystemWorkspaceBinding._isolatedFileSystemManager.excludedFolderManager().addExcludedFolder(this._fileSystem.path(), path);
+        this._fileSystem.addExcludedFolder(path);
     },
 
     /**
@@ -610,8 +624,3 @@
 
     __proto__: WebInspector.Object.prototype
 }
-
-/**
- * @type {!WebInspector.FileSystemWorkspaceBinding}
- */
-WebInspector.fileSystemWorkspaceBinding;
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/NetworkMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/NetworkMapping.js
index d56d130..4bcb4a0a 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/NetworkMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/NetworkMapping.js
@@ -26,6 +26,18 @@
     {
         var fileSystem = /** @type {!WebInspector.IsolatedFileSystem} */ (event.data);
         this._fileSystemMapping.addFileSystem(fileSystem.path());
+
+        var mappings = fileSystem.projectProperty("mappings");
+        for (var i = 0; Array.isArray(mappings) && i < mappings.length; ++i) {
+            var mapping = mappings[i];
+            if (!mapping || typeof mapping !== "object")
+                continue;
+            var folder = mapping["folder"];
+            var url = mapping["url"];
+            if (typeof folder !== "string" || typeof url !== "string")
+                continue;
+            this._fileSystemMapping.addNonConfigurableFileMapping(fileSystem.path(), url, folder);
+        }
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/common/TestBase.js b/third_party/WebKit/Source/devtools/front_end/common/TestBase.js
index 7d568b5..5b9cb4bef 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/TestBase.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/TestBase.js
@@ -109,10 +109,11 @@
  * Run specified test on a fresh instance of the test suite.
  * @param {string} name Name of a test method from implementation class.
  */
-WebInspector.TestBase.prototype.runTest = function(testName)
+WebInspector.TestBase.prototype.dispatch = function(args)
 {
+    var methodName = args.shift();
     try {
-        this[testName]();
+        this[methodName].apply(this, args);
         if (!this.controlTaken_)
             this.reportOk_();
     } catch (e) {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
index 65e6d85..fb6bd15 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
@@ -490,26 +490,6 @@
 }
 
 /**
- * @constructor
- * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator}
- */
-WebInspector.DOMBreakpointsSidebarPane.MarkerDecorator = function()
-{
-}
-
-WebInspector.DOMBreakpointsSidebarPane.MarkerDecorator.prototype = {
-    /**
-     * @override
-     * @param {!WebInspector.DOMNode} node
-     * @return {?{title: string, color: string}}
-     */
-    decorate: function(node)
-    {
-        return { title: WebInspector.UIString("DOM Breakpoint"), color: "rgb(105, 140, 254)" };
-    }
-}
-
-/**
  * @type {!WebInspector.DOMBreakpointsSidebarPane}
  */
 WebInspector.domBreakpointsSidebarPane;
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
index 1d2d126..2c17cfa8 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -624,3 +624,26 @@
      */
     decorate: function(node) { }
 }
+
+/**
+ * @constructor
+ * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator}
+ * @param {!Runtime.Extension} extension
+ */
+WebInspector.DOMPresentationUtils.GenericDecorator = function(extension)
+{
+    this._title = WebInspector.UIString(extension.title(WebInspector.platform()));
+    this._color = extension.descriptor()['color'];
+}
+
+WebInspector.DOMPresentationUtils.GenericDecorator.prototype = {
+    /**
+     * @override
+     * @param {!WebInspector.DOMNode} node
+     * @return {?{title: string, color: string}}
+     */
+    decorate: function(node)
+    {
+        return { title: this._title, color: this._color };
+    }
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/components/module.json b/third_party/WebKit/Source/devtools/front_end/components/module.json
index 3d444463..e646be3 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/components/module.json
@@ -10,8 +10,10 @@
         },
         {
             "type": "@WebInspector.DOMPresentationUtils.MarkerDecorator",
-            "className": "WebInspector.DOMBreakpointsSidebarPane.MarkerDecorator",
-            "marker": "breakpoint-marker"
+            "className": "WebInspector.DOMPresentationUtils.GenericDecorator",
+            "marker": "breakpoint-marker",
+            "title": "DOM Breakpoint",
+            "color": "rgb(105, 140, 254)"
         },
         {
             "type": "setting",
diff --git a/third_party/WebKit/Source/devtools/front_end/devtools.js b/third_party/WebKit/Source/devtools/front_end/devtools.js
index 91fc50d..3a8f26b 100644
--- a/third_party/WebKit/Source/devtools/front_end/devtools.js
+++ b/third_party/WebKit/Source/devtools/front_end/devtools.js
@@ -894,25 +894,25 @@
 if (window.domAutomationController) {
     var uiTests = {};
 
-    uiTests._tryRun = function()
+    uiTests._dispatchIfReady = function()
     {
-        if (uiTests._testSuite && uiTests._pendingTestName) {
-            var name = uiTests._pendingTestName;
-            delete uiTests._pendingTestName;
-            uiTests._testSuite.runTest(name);
+        if (uiTests._testSuite && uiTests._pendingDispatchArgs) {
+            var args = uiTests._pendingDispatchArgs;
+            delete uiTests._pendingDispatchArgs;
+            uiTests._testSuite.dispatch(args);
         }
     }
 
-    uiTests.runTest = function(name)
+    uiTests.dispatchOnTestSuite = function(args)
     {
-        uiTests._pendingTestName = name;
-        uiTests._tryRun();
+        uiTests._pendingDispatchArgs = args;
+        uiTests._dispatchIfReady();
     };
 
-    uiTests.testSuiteReady = function(testSuiteConstructor, testBase)
+    uiTests.testSuiteReady = function(testSuiteConstructor)
     {
         uiTests._testSuite = testSuiteConstructor(window.domAutomationController);
-        uiTests._tryRun();
+        uiTests._dispatchIfReady();
     };
 
     window.uiTests = uiTests;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index ee8ed20..7c1e149 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -50,8 +50,6 @@
 
     this._contentElement = createElement("div");
     var crumbsContainer = createElement("div");
-    if (Runtime.experiments.isEnabled("materialDesign"))
-        this._initializeActionsToolbar();
     stackElement.appendChild(this._contentElement);
     stackElement.appendChild(crumbsContainer);
 
@@ -105,29 +103,6 @@
 WebInspector.ElementsPanel._elementsSidebarViewTitleSymbol = Symbol("title");
 
 WebInspector.ElementsPanel.prototype = {
-    _initializeActionsToolbar: function()
-    {
-        this._nodeActionsElement = createElementWithClass("div", "node-actions-container");
-        var button = this._nodeActionsElement.createChild("div", "node-actions-toggle");
-        button.addEventListener("click", this._toggleActionsToolbar.bind(this, undefined));
-        this._nodeActionsToolbar = new WebInspector.Toolbar();
-        this._nodeActionsElement.appendChild(this._nodeActionsToolbar.element);
-        this._nodeActionsToolbar.element.addEventListener("mousedown", consumeEvent);
-        WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.MarkersChanged, this._markersChanged, this);
-
-        this._editAsHTMLButton = new WebInspector.ToolbarButton(WebInspector.UIString("Edit as HTML"), "edit-toolbar-item");
-        this._editAsHTMLButton.setAction("elements.edit-as-html");
-        this._nodeActionsToolbar.appendToolbarItem(this._editAsHTMLButton);
-        this._nodeActionsToolbar.element.classList.add("node-actions-toolbar");
-        this._hideElementButton = new WebInspector.ToolbarButton(WebInspector.UIString("Hide element"), "visibility-off-toolbar-item");
-        this._hideElementButton.setAction("elements.hide-element");
-        this._nodeActionsToolbar.appendToolbarItem(this._hideElementButton);
-        this._forceElementStateButton = new WebInspector.ToolbarMenuButton(WebInspector.UIString("Force element state"), "pin-toolbar-item", this._showForceElementStateMenu.bind(this));
-        this._nodeActionsToolbar.appendToolbarItem(this._forceElementStateButton);
-        this._breakpointsButton = new WebInspector.ToolbarMenuButton(WebInspector.UIString("Toggle breakpoints"), "add-breakpoint-toolbar-item", this._showBreakpointsMenu.bind(this));
-        this._nodeActionsToolbar.appendToolbarItem(this._breakpointsButton);
-    },
-
     _toggleHideElement: function()
     {
         var node = this.selectedDOMNode();
@@ -137,128 +112,13 @@
         treeOutline.toggleHideElement(node);
     },
 
-    /**
-     * @param {!WebInspector.DOMNode} node
-     */
-    _updateActionsToolbar: function(node)
-    {
-        if (!Runtime.experiments.isEnabled("materialDesign"))
-            return;
-        var classText = node.getAttribute("class");
-        var treeOutline = this._treeOutlineForNode(node);
-        this._hideElementButton.setToggled(treeOutline && treeOutline.isToggledToHidden(node));
-        this._editAsHTMLButton.setToggled(false);
-        this._breakpointsButton.setEnabled(!node.pseudoType());
-        this._breakpointsButton.setToggled(WebInspector.domBreakpointsSidebarPane.hasBreakpoints(node));
-        this._forceElementStateButton.setEnabled(node.nodeType() === Node.ELEMENT_NODE && !node.pseudoType());
-        this._forceElementStateButton.setToggled(!!WebInspector.CSSStyleModel.fromNode(node).pseudoState(node).length);
-
-        var treeElement = this._treeOutlineForNode(node).selectedTreeElement;
-        if (!treeElement)
-            return;
-        if (node.nodeType() !== Node.ELEMENT_NODE) {
-            this._nodeActionsElement.remove();
-            return;
-        }
-
-        var actionsToolbar = this._nodeActionsElement;
-        if (actionsToolbar.__node !== node) {
-            treeElement.gutterElement().appendChild(actionsToolbar);
-            this._positionActionsToolbar();
-            actionsToolbar.__node = node;
-            this._toggleActionsToolbar(false);
-        }
-    },
-
     _toggleEditAsHTML: function()
     {
         var node = this.selectedDOMNode();
         var treeOutline = this._treeOutlineForNode(node);
         if (!node || !treeOutline)
             return;
-
-        var startEditing = true;
-        if (Runtime.experiments.isEnabled("materialDesign")) {
-            startEditing = !this._editAsHTMLButton.toggled();
-            this._editAsHTMLButton.setToggled(startEditing);
-        }
-        treeOutline.toggleEditAsHTML(node, startEditing, this._updateActionsToolbar.bind(this, node));
-    },
-
-    /**
-     * @param {!WebInspector.ContextMenu} contextMenu
-     */
-    _showBreakpointsMenu: function(contextMenu)
-    {
-        var node = this.selectedDOMNode();
-        if (!node)
-            return;
-        WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(node, contextMenu, false);
-    },
-
-    /**
-     * @param {!WebInspector.ContextMenu} contextMenu
-     */
-    _showForceElementStateMenu: function(contextMenu)
-    {
-        var node = this.selectedDOMNode();
-        if (!node)
-            return;
-        WebInspector.ElementsTreeElement.populateForcedPseudoStateItems(contextMenu, node);
-    },
-
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _decorationsClicked: function(event)
-    {
-        var node = /** @type {!WebInspector.DOMNode} */(event.data);
-        this.selectDOMNode(node, true);
-        this._toggleActionsToolbar(true);
-    },
-
-    /**
-     * @param {boolean=} toggled
-     */
-    _toggleActionsToolbar: function(toggled)
-    {
-        if (toggled === undefined)
-            toggled = !this._actionsToolbarShown();
-        this._nodeActionsElement.classList.toggle("expanded", toggled);
-        this._positionActionsToolbar();
-    },
-
-    _positionActionsToolbar: function()
-    {
-        if (!this._actionsToolbarShown())
-            return;
-        var toolbarElement = this._nodeActionsToolbar.element;
-        if (toolbarElement.totalOffsetTop() < this.element.totalOffsetTop()) {
-            toolbarElement.style.top = this._nodeActionsElement.parentElement.offsetHeight + "px";
-            toolbarElement.classList.add("node-actions-toolbar-below");
-        } else {
-            toolbarElement.style.top = "";
-            toolbarElement.classList.remove("node-actions-toolbar-below");
-        }
-    },
-
-    /**
-     * @return {boolean}
-     */
-    _actionsToolbarShown: function()
-    {
-        return this._nodeActionsElement.classList.contains("expanded");
-    },
-
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _markersChanged: function(event)
-    {
-        var node = /** @type {!WebInspector.DOMNode} */ (event.data);
-        if (node !== this.selectedDOMNode())
-            return;
-        this._updateActionsToolbar(node);
+        treeOutline.toggleEditAsHTML(node);
     },
 
     _loadSidebarViews: function()
@@ -317,7 +177,6 @@
         treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this);
         treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.NodePicked, this._onNodePicked, this);
         treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, this._updateBreadcrumbIfNeeded, this);
-        treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.DecorationsClicked, this._decorationsClicked, this);
         this._treeOutlines.push(treeOutline);
         this._modelToTreeOutline.set(domModel, treeOutline);
 
@@ -452,7 +311,6 @@
         if (selectedNode) {
             selectedNode.setAsInspectedNode();
             this._lastValidSelectedNode = selectedNode;
-            this._updateActionsToolbar(selectedNode);
         }
         WebInspector.notifications.dispatchEventToListeners(WebInspector.NotificationService.Events.SelectedNodeChanged);
         this._selectedNodeChangedForTest();
@@ -1304,23 +1162,3 @@
         return { color: "orange", title: WebInspector.UIString("Element state: %s", ":" + WebInspector.CSSStyleModel.fromNode(node).pseudoState(node).join(", :")) };
     }
 }
-
-/**
- * @constructor
- * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator}
- */
-WebInspector.ElementsPanel.HiddenMarkerDecorator = function()
-{
-}
-
-WebInspector.ElementsPanel.HiddenMarkerDecorator.prototype = {
-    /**
-     * @override
-     * @param {!WebInspector.DOMNode} node
-     * @return {?{title: string, color: string}}
-     */
-    decorate: function(node)
-    {
-        return { color: "#555", title: WebInspector.UIString("Element is hidden") };
-    }
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
index ec4d823..0255b86 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeElement.js
@@ -41,8 +41,8 @@
     this._node = node;
 
     this._gutterContainer = this.listItemElement.createChild("div", "gutter-container");
+    this._gutterContainer.addEventListener("click", this._showContextMenu.bind(this));
     this._decorationsElement = this._gutterContainer.createChild("div", "hidden");
-    this._decorationsElement.addEventListener("mousedown", this._decorationsClicked.bind(this));
 
     this._elementCloseTag = elementCloseTag;
 
@@ -50,8 +50,6 @@
         this._canAddAttributes = true;
     this._searchQuery = null;
     this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit;
-    if (this._node.nodeType() === Node.ELEMENT_NODE && this._node.parentNode && this._node.parentNode.nodeType() === Node.DOCUMENT_NODE && !this._node.parentNode.parentNode)
-        this.setCollapsible(false);
 }
 
 WebInspector.ElementsTreeElement.InitialChildrenLimit = 500;
@@ -165,19 +163,6 @@
     },
 
     /**
-     * @return {!Element}
-     */
-    gutterElement: function()
-    {
-        return this._gutterContainer;
-    },
-
-    _decorationsClicked: function()
-    {
-        this.treeOutline.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.DecorationsClicked, this._node);
-    },
-
-    /**
      * @param {string} searchQuery
      */
     highlightSearchResults: function(searchQuery)
@@ -526,6 +511,14 @@
     },
 
     /**
+     * @param {!Event} event
+     */
+    _showContextMenu: function(event)
+    {
+        this.treeOutline.showContextMenu(this, event);
+    },
+
+    /**
      * @param {!WebInspector.ContextMenu} contextMenu
      * @param {!Event} event
      */
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
index d51739a..73b6698 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -93,8 +93,7 @@
 WebInspector.ElementsTreeOutline.Events = {
     NodePicked: "NodePicked",
     SelectedNodeChanged: "SelectedNodeChanged",
-    ElementsTreeUpdated: "ElementsTreeUpdated",
-    DecorationsClicked: "DecorationsClicked"
+    ElementsTreeUpdated: "ElementsTreeUpdated"
 }
 
 /**
@@ -886,7 +885,17 @@
     _contextMenuEventFired: function(event)
     {
         var treeElement = this._treeElementFromEvent(event);
-        if (!(treeElement instanceof WebInspector.ElementsTreeElement) || WebInspector.isEditing())
+        if (treeElement instanceof WebInspector.ElementsTreeElement)
+            this.showContextMenu(treeElement, event);
+    },
+
+    /**
+     * @param {!WebInspector.ElementsTreeElement} treeElement
+     * @param {!Event} event
+     */
+    showContextMenu: function(treeElement, event)
+    {
+        if (WebInspector.isEditing())
             return;
 
         var contextMenu = new WebInspector.ContextMenu(event);
@@ -1333,6 +1342,8 @@
     {
         var treeElement = new WebInspector.ElementsTreeElement(node, closingTag);
         treeElement.setExpandable(!closingTag && this._hasVisibleChildren(node));
+        if (node.nodeType() === Node.ELEMENT_NODE && node.parentNode && node.parentNode.nodeType() === Node.DOCUMENT_NODE && !node.parentNode.parentNode)
+            treeElement.setCollapsible(false);
         treeElement.selectable = this._selectEnabled;
         return treeElement;
     },
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
index 45eeca07..f848849 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
+++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
@@ -322,57 +322,22 @@
     color: #ccc;
 }
 
-.elements-disclosure li.selected .selection > .node-actions-container {
-    visibility: visible;
-}
-
-.node-actions-container {
+.elements-disclosure li.selected .gutter-container:not(.has-decoration) {
     position: absolute;
-    z-index: 10000;
     left: 0px;
-    height: 13px;
-    background-color: hsla(0,100%,100%,0.3);
-}
-
-.node-actions-toolbar {
-    position: absolute;
-    top: -30px;
-    left: 2px;
-    background: white;
-    border-radius: 3px;
-    border: 1px solid #B1B1B1;
-    visibility: hidden;
-    box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37)
-
-}
-
-.node-actions-toggle {
-    -webkit-mask-position: -201px -26px;
     width: 16.25px;
-    height: 20px;
-    transform: scale(0.8) rotate(90deg);
+    height: 18px;
+    transform: rotate(-90deg) translateX(-13px) scale(0.8);
+    transform-origin: 0% 0%;
     -webkit-mask-image: url(Images/toolbarButtonGlyphs.png);
+    -webkit-mask-position: -201px -27px;
     -webkit-mask-size: 352px 168px;
-    background-color: #FFFFFF;
-    z-index: 1;
-    margin-top: -3px;
+    background-color: white;
     cursor: pointer;
 }
 
 @media (-webkit-min-device-pixel-ratio: 1.5) {
-.node-actions-toggle {
+.elements-disclosure li.selected .gutter-container {
     -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png);
 }
 } /* media */
-
-.gutter-container.has-decorations .node-actions-toggle {
-    opacity: 0;
-}
-
-.node-actions-container.expanded > .node-actions-toolbar {
-    visibility: visible;
-}
-
-.node-actions-toolbar-below {
-    margin-top: 2px;
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/module.json b/third_party/WebKit/Source/devtools/front_end/elements/module.json
index c90f8f9..15089b86 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/elements/module.json
@@ -99,8 +99,10 @@
         },
         {
             "type": "@WebInspector.DOMPresentationUtils.MarkerDecorator",
-            "className": "WebInspector.ElementsPanel.HiddenMarkerDecorator",
-            "marker": "hidden-marker"
+            "className": "WebInspector.DOMPresentationUtils.GenericDecorator",
+            "marker": "hidden-marker",
+            "title": "Element is hidden",
+            "color": "#555"
         }
     ],
     "dependencies": [
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 1022c1ef..205ec13f2 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -209,8 +209,8 @@
         WebInspector.workspace = new WebInspector.Workspace();
         WebInspector.fileSystemMapping = new WebInspector.FileSystemMapping();
 
-        WebInspector.fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, WebInspector.workspace);
-        WebInspector.networkMapping = new WebInspector.NetworkMapping(WebInspector.workspace, WebInspector.fileSystemWorkspaceBinding, WebInspector.fileSystemMapping);
+        var fileSystemWorkspaceBinding = new WebInspector.FileSystemWorkspaceBinding(WebInspector.isolatedFileSystemManager, WebInspector.workspace);
+        WebInspector.networkMapping = new WebInspector.NetworkMapping(WebInspector.workspace, fileSystemWorkspaceBinding, WebInspector.fileSystemMapping);
         WebInspector.networkProjectManager = new WebInspector.NetworkProjectManager(WebInspector.targetManager, WebInspector.workspace, WebInspector.networkMapping);
         WebInspector.presentationConsoleMessageHelper = new WebInspector.PresentationConsoleMessageHelper(WebInspector.workspace);
         WebInspector.cssWorkspaceBinding = new WebInspector.CSSWorkspaceBinding(WebInspector.targetManager, WebInspector.workspace, WebInspector.networkMapping);
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Tests.js b/third_party/WebKit/Source/devtools/front_end/main/Tests.js
index 684ba91..994b843ce 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Tests.js
@@ -371,15 +371,6 @@
     this.takeControl();
 };
 
-TestSuite.prototype.testReattachAfterCrash = function()
-{
-    var target = WebInspector.targetManager.mainTarget();
-    target.pageAgent().navigate("about:crash");
-    target.pageAgent().navigate("about:blank");
-    target.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.ExecutionContextCreated, this.releaseControl, this);
-};
-
-
 TestSuite.prototype.testSharedWorker = function()
 {
     function didEvaluateInConsole(resultText) {
@@ -428,6 +419,11 @@
     WebInspector.overridesSupport._emulateTouchEventsInTarget(WebInspector.targetManager.mainTarget(), true, "mobile");
 };
 
+TestSuite.prototype.switchToPanel = function(panelName)
+{
+    this.showPanel(panelName).then(this.releaseControl.bind(this));
+    this.takeControl();
+}
 
 // Regression test for crbug.com/370035.
 TestSuite.prototype.testDeviceMetricsOverrides = function()
@@ -814,34 +810,11 @@
     return evt;
 };
 
-/**
- * Run specified test.
- * @param {string} name Name of a test method from TestSuite class.
- * @override
- */
-TestSuite.prototype.runTest = function(name)
-{
-    var test = WebInspector.TestBase.prototype.runTest.bind(this, name);
-    if (TestSuite._populatedInterface)
-        test();
-    else
-        TestSuite._pendingTest = test;
-};
-
-function runTests()
-{
-    TestSuite._populatedInterface = true;
-    var test = TestSuite._pendingTest;
-    delete TestSuite._pendingTest;
-    if (test)
-        test();
-}
-
-WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.InspectorAgentEnabledForTests, runTests);
-
 return new TestSuite();
 
 }
 
-if (window.uiTests)
-    window.uiTests.testSuiteReady(createTestSuite, WebInspector.TestBase);
+if (window.uiTests) {
+    WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.InspectorAgentEnabledForTests,
+        window.uiTests.testSuiteReady.bind(null, createTestSuite));
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
index 00264ffd..a09aa76d 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSStyleModel.js
@@ -277,6 +277,7 @@
             if (!mediaPayload)
                 return null;
             this._domModel.markUndoableState();
+            this._fireStyleSheetChanged(media.parentStyleSheetId);
             return WebInspector.CSSMedia.parsePayload(this, mediaPayload);
         }
 
@@ -355,6 +356,7 @@
             if (error || !rulePayload)
                 return null;
             this._domModel.markUndoableState();
+            this._fireStyleSheetChanged(styleSheetId);
             return new WebInspector.CSSRule(this, rulePayload);
         }
 
@@ -541,10 +543,13 @@
          */
         function callback(error)
         {
-            if (!error && majorChange)
-                this._domModel.markUndoableState();
+            if (error)
+                return error;
 
-            return error;
+            if (majorChange)
+                this._domModel.markUndoableState();
+            this._fireStyleSheetChanged(styleSheetId);
+            return null;
         }
     },
 
@@ -939,6 +944,7 @@
             if (majorChange)
                 this._cssModel._domModel.markUndoableState();
             this._reinitialize(stylePayload);
+            this._cssModel._fireStyleSheetChanged(this.styleSheetId);
             return true;
         }
 
@@ -1052,6 +1058,7 @@
             if (error || !selectorPayload)
                 return null;
             this._cssModel._domModel.markUndoableState();
+            this._cssModel._fireStyleSheetChanged(/** @type {string} */(this.styleSheetId));
             return WebInspector.CSSRuleSelector.parseSelectorListPayload(selectorPayload);
         }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js b/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
index 7baa5d1..7ccd25c 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/InspectorBackend.js
@@ -731,6 +731,7 @@
 
 InspectorBackendClass.AgentPrototype.PromisifiedDomains = {
     "Accessibility": true,
+    "Animation": true,
     "CSS": true,
     "Emulation": true,
     "Profiler": true
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
index d70c472..7e8658d 100644
--- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -428,7 +428,7 @@
     WebInspector.VBox.call(this, true);
     this.registerRequiredCSS("security/mainView.css");
     this.registerRequiredCSS("security/lockIcon.css");
-    this.setMinimumSize(100, 100);
+    this.setMinimumSize(200, 100);
 
     this.contentElement.classList.add("security-main-view");
 
diff --git a/third_party/WebKit/Source/devtools/front_end/security/mainView.css b/third_party/WebKit/Source/devtools/front_end/security/mainView.css
index f4a0779..216315b 100644
--- a/third_party/WebKit/Source/devtools/front_end/security/mainView.css
+++ b/third_party/WebKit/Source/devtools/front_end/security/mainView.css
@@ -5,6 +5,12 @@
 
 .security-main-view {
     -webkit-user-select: text;
+    overflow-x: hidden;
+    overflow-y: auto;
+}
+
+.security-main-view > div {
+    flex-shrink: 0;
 }
 
 .security-summary-section-title {
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemDialog.js b/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemDialog.js
index f727d66..8422931 100644
--- a/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemDialog.js
+++ b/third_party/WebKit/Source/devtools/front_end/settings/EditFileSystemDialog.js
@@ -47,8 +47,8 @@
 
     WebInspector.fileSystemMapping.addEventListener(WebInspector.FileSystemMapping.Events.FileMappingAdded, this._fileMappingAdded, this);
     WebInspector.fileSystemMapping.addEventListener(WebInspector.FileSystemMapping.Events.FileMappingRemoved, this._fileMappingRemoved, this);
-    WebInspector.isolatedFileSystemManager.excludedFolderManager().addEventListener(WebInspector.ExcludedFolderManager.Events.ExcludedFolderAdded, this._excludedFolderAdded, this);
-    WebInspector.isolatedFileSystemManager.excludedFolderManager().addEventListener(WebInspector.ExcludedFolderManager.Events.ExcludedFolderRemoved, this._excludedFolderRemoved, this);
+    WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.ExcludedFolderAdded, this._excludedFolderAdded, this);
+    WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.ExcludedFolderRemoved, this._excludedFolderRemoved, this);
 
     var blockHeader = contents.createChild("div", "block-header");
     blockHeader.textContent = WebInspector.UIString("Mappings");
@@ -73,15 +73,17 @@
     blockHeader.textContent = WebInspector.UIString("Excluded folders");
     this._excludedFolderListSection = contents.createChild("div", "section excluded-folders-section");
     this._excludedFolderListContainer = this._excludedFolderListSection.createChild("div", "settings-list-container");
-    var excludedFolderEntries = WebInspector.isolatedFileSystemManager.excludedFolderManager().excludedFolders(fileSystemPath);
 
     this._excludedFolderList = new WebInspector.EditableSettingsList([pathColumn], this._excludedFolderValueProvider.bind(this), this._excludedFolderValidate.bind(this), this._excludedFolderEdit.bind(this));
     this._excludedFolderList.addEventListener(WebInspector.SettingsList.Events.Removed, this._excludedFolderRemovedfromList.bind(this));
     this._excludedFolderList.element.classList.add("excluded-folders-list");
     this._excludedFolderListContainer.appendChild(this._excludedFolderList.element);
-    this._excludedFolderEntries = new Map();
-    for (var i = 0; i < excludedFolderEntries.length; ++i)
-        this._addExcludedFolderRow(excludedFolderEntries[i]);
+    /** @type {!Set<string>} */
+    this._excludedFolderEntries = new Set();
+    for (var folder of WebInspector.isolatedFileSystemManager.fileSystem(fileSystemPath).excludedFolders().values())
+        this._addExcludedFolderRow(folder, false);
+    for (var folder of WebInspector.isolatedFileSystemManager.fileSystem(fileSystemPath).nonConfigurableExcludedFolders().values())
+        this._addExcludedFolderRow(folder, true);
 
     this.element.tabIndex = 0;
     this._hasMappingChanges = false;
@@ -116,7 +118,7 @@
         const minHeight = 150;
         var maxHeight = this._container.offsetHeight - 10;
         maxHeight = Math.max(minHeight, maxHeight);
-        var maxWidth = Math.min(540, this._container.offsetWidth - 10);
+        var maxWidth = Math.min(740, this._container.offsetWidth - 10);
         maxWidth = Math.max(minWidth, maxWidth);
         this._dialogElement.style.maxHeight = maxHeight + "px";
         this._dialogElement.style.width = maxWidth + "px";
@@ -172,7 +174,7 @@
         var entry = this._entries[itemId];
         switch (columnId) {
         case "url":
-            return entry.urlPrefix;
+            return entry.configurable ? entry.urlPrefix : WebInspector.UIString("%s (via .devtools)", entry.urlPrefix);
         case "path":
             return entry.pathPrefix;
         default:
@@ -270,25 +272,38 @@
             return;
 
         this._entries[urlPrefix] = entry;
-        this._fileMappingsList.addItem(urlPrefix, null);
+        // Insert configurable entries before non-configurable.
+        var insertBefore = null;
+        if (entry.configurable) {
+            for (var prefix in this._entries) {
+                if (!this._entries[prefix].configurable) {
+                    insertBefore = prefix;
+                    break;
+                }
+            }
+        }
+        this._fileMappingsList.addItem(urlPrefix, insertBefore, !entry.configurable);
         this._resize();
     },
 
+    /**
+     * @param {!WebInspector.Event} event
+     */
     _excludedFolderAdded: function(event)
     {
-        var entry = /** @type {!WebInspector.ExcludedFolderManager.Entry} */ (event.data);
-        this._addExcludedFolderRow(entry);
+        var path = /** @type {string} */ (event.data);
+        this._addExcludedFolderRow(path, false);
     },
 
+    /**
+     * @param {!WebInspector.Event} event
+     */
     _excludedFolderRemoved: function(event)
     {
-        var entry = /** @type {!WebInspector.ExcludedFolderManager.Entry} */ (event.data);
-        var fileSystemPath = entry.fileSystemPath;
-        if (!fileSystemPath || this._fileSystemPath !== fileSystemPath)
-            return;
-        delete this._excludedFolderEntries[entry.path];
-        if (this._excludedFolderList.itemForId(entry.path))
-            this._excludedFolderList.removeItem(entry.path);
+        var path = /** @type {string} */ (event.data);
+        delete this._excludedFolderEntries[path];
+        if (this._excludedFolderList.itemForId(path))
+            this._excludedFolderList.removeItem(path);
     },
 
     /**
@@ -329,11 +344,10 @@
      */
     _excludedFolderEdit: function(itemId, data)
     {
-        var fileSystemPath = this._fileSystemPath;
         if (itemId)
-            WebInspector.isolatedFileSystemManager.excludedFolderManager().removeExcludedFolder(fileSystemPath, itemId);
+            WebInspector.isolatedFileSystemManager.fileSystem(this._fileSystemPath).removeExcludedFolder(itemId);
         var excludedFolderPath = data["path"];
-        WebInspector.isolatedFileSystemManager.excludedFolderManager().addExcludedFolder(fileSystemPath, excludedFolderPath);
+        WebInspector.isolatedFileSystemManager.fileSystem(this._fileSystemPath).addExcludedFolder(excludedFolderPath);
     },
 
     /**
@@ -344,20 +358,24 @@
         var itemId = /** @type{?string} */ (event.data);
         if (!itemId)
             return;
-        WebInspector.isolatedFileSystemManager.excludedFolderManager().removeExcludedFolder(this._fileSystemPath, itemId);
+        WebInspector.isolatedFileSystemManager.fileSystem(this._fileSystemPath).removeExcludedFolder(itemId);
     },
 
     /**
-     * @param {!WebInspector.ExcludedFolderManager.Entry} entry
+     * @param {string} path
+     * @param {boolean} readOnly
      */
-    _addExcludedFolderRow: function(entry)
+    _addExcludedFolderRow: function(path, readOnly)
     {
-        var fileSystemPath = entry.fileSystemPath;
-        if (!fileSystemPath || this._fileSystemPath !== fileSystemPath)
+        if (this._excludedFolderEntries.has(path))
             return;
-        var path = entry.path;
-        this._excludedFolderEntries.set(path, entry);
-        this._excludedFolderList.addItem(path, null);
+        this._excludedFolderEntries.add(path);
+        if (readOnly && !this._firstNonConfigurableExcludedFolder)
+            this._firstNonConfigurableExcludedFolder = WebInspector.UIString("%s (via .devtools)", path);
+
+        // Insert configurable entries before non-configurable.
+        var insertBefore = readOnly ? null : this._firstNonConfigurableExcludedFolder;
+        this._excludedFolderList.addItem(readOnly ? WebInspector.UIString("%s (via .devtools)", path) : path, insertBefore, readOnly);
         this._resize();
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
index 1c88ca5..e6b9467 100644
--- a/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
+++ b/third_party/WebKit/Source/devtools/front_end/settings/SettingsScreen.js
@@ -340,7 +340,7 @@
     WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this);
 
     this._commonSection = this._appendSection(WebInspector.UIString("Common"));
-    var folderExcludeSetting = WebInspector.isolatedFileSystemManager.excludedFolderManager().workspaceFolderExcludePatternSetting();
+    var folderExcludeSetting = WebInspector.isolatedFileSystemManager.workspaceFolderExcludePatternSetting();
     var folderExcludePatternInput = WebInspector.SettingsUI.createSettingInputField(WebInspector.UIString("Folder exclude pattern"), folderExcludeSetting, false, 0, "270px", WebInspector.SettingsUI.regexValidator);
     this._commonSection.appendChild(folderExcludePatternInput);
 
@@ -696,6 +696,8 @@
     /** @type {!Array.<?string>} */
     this._ids = [];
     this._columns = columns;
+    /** @type {!Set<string>} */
+    this._editableEntries = new Set();
 }
 
 WebInspector.SettingsList.Events = {
@@ -708,13 +710,16 @@
     /**
      * @param {?string} itemId
      * @param {?string=} beforeId
+     * @param {boolean=} readOnly
      * @return {!Element}
      */
-    addItem: function(itemId, beforeId)
+    addItem: function(itemId, beforeId, readOnly)
     {
+        if (!readOnly && itemId)
+            this._editableEntries.add(itemId);
         var listItem = createElementWithClass("div", "settings-list-item");
         listItem._id = itemId;
-        if (typeof beforeId !== "undefined")
+        if (beforeId)
             this.element.insertBefore(listItem, this.itemForId(beforeId));
         else
             this.element.appendChild(listItem);
@@ -729,10 +734,12 @@
             listItem.columnElements[column.id] = columnElement;
             this._itemRenderer(columnElement, column, itemId);
         }
-        var removeItemButton = this._createRemoveButton(removeItemClicked.bind(this));
-        listItemContents.addEventListener("click", this.selectItem.bind(this, itemId), false);
-        listItemContents.addEventListener("dblclick", this._onDoubleClick.bind(this, itemId), false);
-        listItemContents.appendChild(removeItemButton);
+        if (!readOnly) {
+            var removeItemButton = this._createRemoveButton(removeItemClicked.bind(this));
+            listItemContents.addEventListener("click", this.selectItem.bind(this, itemId), false);
+            listItemContents.addEventListener("dblclick", this._onDoubleClick.bind(this, itemId), false);
+            listItemContents.appendChild(removeItemButton);
+        }
 
         this._listItems.set(itemId || "", listItem);
         if (typeof beforeId !== "undefined")
@@ -804,12 +811,12 @@
     },
 
     /**
-     * @param {?string} itemId
+     * @param {string} itemId
      * @return {?Element}
      */
     itemForId: function(itemId)
     {
-        return this._listItems.get(itemId || "") || null;
+        return this._listItems.get(itemId) || null;
     },
 
     /**
@@ -827,11 +834,11 @@
      */
     selectItem: function(id, event)
     {
-        if (typeof this._selectedId !== "undefined")
+        if (this._selectedId)
             this.itemForId(this._selectedId).classList.remove("selected");
 
         this._selectedId = id;
-        if (typeof this._selectedId !== "undefined")
+        if (this._selectedId)
             this.itemForId(this._selectedId).classList.add("selected");
 
         this.dispatchEventToListeners(WebInspector.SettingsList.Events.Selected, id);
@@ -883,12 +890,14 @@
      * @override
      * @param {?string} itemId
      * @param {?string=} beforeId
+     * @param {boolean=} readOnly
      * @return {!Element}
      */
-    addItem: function(itemId, beforeId)
+    addItem: function(itemId, beforeId, readOnly)
     {
-        var listItem = WebInspector.SettingsList.prototype.addItem.call(this, itemId, beforeId);
-        listItem.classList.add("editable");
+        var listItem = WebInspector.SettingsList.prototype.addItem.call(this, itemId, beforeId, readOnly);
+        if (!readOnly)
+            listItem.classList.add("editable");
         return listItem;
     },
 
@@ -959,11 +968,13 @@
         var value = this._valuesProvider(itemId, columnId);
 
         var textElement = /** @type {!HTMLSpanElement} */ (columnElement.createChild("span", "list-column-text"));
-        columnElement.addEventListener("click", rowClicked.bind(this), false);
+        if (this._editableEntries.has(itemId))
+            columnElement.addEventListener("click", rowClicked.bind(this), false);
         this._textElements.get(itemId).set(columnId, textElement);
         this._setTextElementContent(itemId, columnId, value);
 
-        this._createEditElement(columnElement, column, itemId, value);
+        if (this._editableEntries.has(itemId))
+            this._createEditElement(columnElement, column, itemId, value);
 
         /**
          * @param {!Event} event
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/helpScreen.css b/third_party/WebKit/Source/devtools/front_end/ui/helpScreen.css
index 1a9b528..4510eee 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/helpScreen.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/helpScreen.css
@@ -325,6 +325,17 @@
     border-radius: 2px;
 }
 
+.settings-tab .settings-list .settings-list-item:not(.editable) {
+    background-color: #eee;
+}
+
+.excluded-folders-list .settings-list-item:not(.editable) .settings-list-column-path:before,
+.settings-list-item:not(.editable) .list-column.settings-list-column-url:before {
+    content: "\1F512";
+    margin-right: 5px;
+}
+
+
 .settings-tab .settings-list .settings-list-item .settings-list-item-contents {
     width: 100%;
     height: 40px;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js
index 79008f36..e43d1437 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/treeoutline.js
@@ -823,9 +823,10 @@
         this._listItemNode.classList.add("expanded");
         this._childrenListNode.classList.add("expanded");
 
-        this.onexpand();
-        if (this.treeOutline)
+        if (this.treeOutline) {
+            this.onexpand();
             this.treeOutline.dispatchEventToListeners(TreeOutline.Events.ElementExpanded, this);
+        }
     },
 
     /**
@@ -943,7 +944,7 @@
 
     _populateIfNeeded: function()
     {
-        if (this._expandable && !this._children) {
+        if (this.treeOutline && this._expandable && !this._children) {
             this._children = [];
             this.onpopulate();
         }
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/ExcludedFolderManager.js b/third_party/WebKit/Source/devtools/front_end/workspace/ExcludedFolderManager.js
deleted file mode 100644
index ce6918f..0000000
--- a/third_party/WebKit/Source/devtools/front_end/workspace/ExcludedFolderManager.js
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @constructor
- * @extends {WebInspector.Object}
- */
-WebInspector.ExcludedFolderManager = function()
-{
-    WebInspector.Object.call(this);
-    this._excludedFoldersSetting = WebInspector.settings.createLocalSetting("workspaceExcludedFolders", {});
-    var defaultCommonExcludedFolders = [
-        "/\\.git/",
-        "/\\.sass-cache/",
-        "/\\.hg/",
-        "/\\.idea/",
-        "/\\.svn/",
-        "/\\.cache/",
-        "/\\.project/"
-    ];
-    var defaultWinExcludedFolders = [
-        "/Thumbs.db$",
-        "/ehthumbs.db$",
-        "/Desktop.ini$",
-        "/\\$RECYCLE.BIN/"
-    ];
-    var defaultMacExcludedFolders = [
-        "/\\.DS_Store$",
-        "/\\.Trashes$",
-        "/\\.Spotlight-V100$",
-        "/\\.AppleDouble$",
-        "/\\.LSOverride$",
-        "/Icon$",
-        "/\\._.*$"
-    ];
-    var defaultLinuxExcludedFolders = [
-        "/.*~$"
-    ];
-    var defaultExcludedFolders = defaultCommonExcludedFolders;
-    if (WebInspector.isWin())
-        defaultExcludedFolders = defaultExcludedFolders.concat(defaultWinExcludedFolders);
-    else if (WebInspector.isMac())
-        defaultExcludedFolders = defaultExcludedFolders.concat(defaultMacExcludedFolders);
-    else
-        defaultExcludedFolders = defaultExcludedFolders.concat(defaultLinuxExcludedFolders);
-    var defaultExcludedFoldersPattern = defaultExcludedFolders.join("|");
-    this._workspaceFolderExcludePatternSetting = WebInspector.settings.createRegExpSetting("workspaceFolderExcludePattern", defaultExcludedFoldersPattern, WebInspector.isWin() ? "i" : "");
-    /** @type {!Object.<string, !Array.<!WebInspector.ExcludedFolderManager.Entry>>} */
-    this._excludedFolders = {};
-    this._loadFromSettings();
-}
-
-WebInspector.ExcludedFolderManager.Events = {
-    ExcludedFolderAdded: "ExcludedFolderAdded",
-    ExcludedFolderRemoved: "ExcludedFolderRemoved"
-}
-
-WebInspector.ExcludedFolderManager.prototype = {
-    /**
-     * @return {!WebInspector.Setting}
-     */
-    workspaceFolderExcludePatternSetting: function()
-    {
-        return this._workspaceFolderExcludePatternSetting;
-    },
-
-    _loadFromSettings: function()
-    {
-        var savedExcludedFolders = this._excludedFoldersSetting.get();
-        this._excludedFolders = {};
-        for (var fileSystemPath in savedExcludedFolders) {
-            var savedExcludedFoldersForPath = savedExcludedFolders[fileSystemPath];
-
-            this._excludedFolders[fileSystemPath] = [];
-            var excludedFolders = this._excludedFolders[fileSystemPath];
-
-            for (var i = 0; i < savedExcludedFoldersForPath.length; ++i) {
-                var savedEntry = savedExcludedFoldersForPath[i];
-                var entry = new WebInspector.ExcludedFolderManager.Entry(savedEntry.fileSystemPath, savedEntry.path);
-                excludedFolders.push(entry);
-            }
-        }
-    },
-
-    _saveToSettings: function()
-    {
-        var savedExcludedFolders = this._excludedFolders;
-        this._excludedFoldersSetting.set(savedExcludedFolders);
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @param {string} excludedFolderPath
-     */
-    addExcludedFolder: function(fileSystemPath, excludedFolderPath)
-    {
-        if (!this._excludedFolders[fileSystemPath])
-            this._excludedFolders[fileSystemPath] = [];
-        var entry = new WebInspector.ExcludedFolderManager.Entry(fileSystemPath, excludedFolderPath);
-        this._excludedFolders[fileSystemPath].push(entry);
-        this._saveToSettings();
-        this.dispatchEventToListeners(WebInspector.ExcludedFolderManager.Events.ExcludedFolderAdded, entry);
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @param {string} path
-     */
-    removeExcludedFolder: function(fileSystemPath, path)
-    {
-        var entry = this._excludedFolderEntryForPath(fileSystemPath, path);
-        if (!entry)
-            return;
-        this._excludedFolders[fileSystemPath].remove(entry);
-        this._saveToSettings();
-        this.dispatchEventToListeners(WebInspector.ExcludedFolderManager.Events.ExcludedFolderRemoved, entry);
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     */
-    removeFileSystem: function(fileSystemPath)
-    {
-        delete this._excludedFolders[fileSystemPath];
-        this._saveToSettings();
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @param {string} path
-     * @return {?WebInspector.ExcludedFolderManager.Entry}
-     */
-    _excludedFolderEntryForPath: function(fileSystemPath, path)
-    {
-        var entries = this._excludedFolders[fileSystemPath];
-        if (!entries)
-            return null;
-
-        for (var i = 0; i < entries.length; ++i) {
-            if (entries[i].path === path)
-                return entries[i];
-        }
-        return null;
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @param {string} folderPath
-     * @return {boolean}
-     */
-    isFileExcluded: function(fileSystemPath, folderPath)
-    {
-        var excludedFolders = this._excludedFolders[fileSystemPath] || [];
-        for (var i = 0; i < excludedFolders.length; ++i) {
-            var entry = excludedFolders[i];
-            if (entry.path === folderPath)
-                return true;
-        }
-        var regex = this._workspaceFolderExcludePatternSetting.asRegExp();
-        return !!(regex && regex.test(folderPath));
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @return {!Array.<!WebInspector.ExcludedFolderManager.Entry>}
-     */
-    excludedFolders: function(fileSystemPath)
-    {
-        var excludedFolders = this._excludedFolders[fileSystemPath];
-        return excludedFolders ? excludedFolders.slice() : [];
-    },
-
-    __proto__: WebInspector.Object.prototype
-}
-
-/**
- * @constructor
- * @param {string} fileSystemPath
- * @param {string} path
- */
-WebInspector.ExcludedFolderManager.Entry = function(fileSystemPath, path)
-{
-    this.fileSystemPath = fileSystemPath;
-    this.path = path;
-}
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/FileSystemMapping.js b/third_party/WebKit/Source/devtools/front_end/workspace/FileSystemMapping.js
index 7c514f5..d6e1591 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/FileSystemMapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/FileSystemMapping.js
@@ -59,7 +59,7 @@
 
             for (var i = 0; i < savedFileSystemMappings.length; ++i) {
                 var savedEntry = savedFileSystemMappings[i];
-                var entry = new WebInspector.FileSystemMapping.Entry(savedEntry.fileSystemPath, savedEntry.urlPrefix, savedEntry.pathPrefix);
+                var entry = new WebInspector.FileSystemMapping.Entry(savedEntry.fileSystemPath, savedEntry.urlPrefix, savedEntry.pathPrefix, true);
                 fileSystemMappings.push(entry);
             }
         }
@@ -69,9 +69,16 @@
 
     _saveToSettings: function()
     {
-        var savedMapping = this._fileSystemMappings;
-        this._fileSystemMappingSetting.set(savedMapping);
-
+        var setting = {};
+        for (var fileSystemPath in this._fileSystemMappings) {
+            setting[fileSystemPath] = [];
+            var entries = this._fileSystemMappings[fileSystemPath];
+            for (var entry of entries) {
+                if (entry.configurable)
+                    setting[fileSystemPath].push(entry);
+            }
+        }
+        this._fileSystemMappingSetting.set(setting);
         this._rebuildIndexes();
     },
 
@@ -121,7 +128,28 @@
      */
     addFileMapping: function(fileSystemPath, urlPrefix, pathPrefix)
     {
-        var entry = new WebInspector.FileSystemMapping.Entry(fileSystemPath, urlPrefix, pathPrefix);
+        this._innerAddFileMapping(fileSystemPath, urlPrefix, pathPrefix, true);
+    },
+
+    /**
+     * @param {string} fileSystemPath
+     * @param {string} urlPrefix
+     * @param {string} pathPrefix
+     */
+    addNonConfigurableFileMapping: function(fileSystemPath, urlPrefix, pathPrefix)
+    {
+        this._innerAddFileMapping(fileSystemPath, urlPrefix, pathPrefix, false);
+    },
+
+    /**
+     * @param {string} fileSystemPath
+     * @param {string} urlPrefix
+     * @param {string} pathPrefix
+     * @param {boolean} configurable
+     */
+    _innerAddFileMapping: function(fileSystemPath, urlPrefix, pathPrefix, configurable)
+    {
+        var entry = new WebInspector.FileSystemMapping.Entry(fileSystemPath, urlPrefix, pathPrefix, configurable);
         this._fileSystemMappings[fileSystemPath].push(entry);
         this._saveToSettings();
         this.dispatchEventToListeners(WebInspector.FileSystemMapping.Events.FileMappingAdded, entry);
@@ -274,6 +302,11 @@
         this.addFileMapping(fileSystemPath, urlPrefix, pathPrefix);
     },
 
+    resetForTesting: function()
+    {
+        this._fileSystemMappings = {};
+    },
+
     __proto__: WebInspector.Object.prototype
 }
 
@@ -282,12 +315,14 @@
  * @param {string} fileSystemPath
  * @param {string} urlPrefix
  * @param {string} pathPrefix
+ * @param {boolean} configurable
  */
-WebInspector.FileSystemMapping.Entry = function(fileSystemPath, urlPrefix, pathPrefix)
+WebInspector.FileSystemMapping.Entry = function(fileSystemPath, urlPrefix, pathPrefix, configurable)
 {
     this.fileSystemPath = fileSystemPath;
     this.urlPrefix = urlPrefix;
     this.pathPrefix = pathPrefix;
+    this.configurable = configurable;
 }
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystem.js b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystem.js
index 4e7f7a7..9386c0d7f 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystem.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystem.js
@@ -32,15 +32,62 @@
  * @constructor
  * @param {!WebInspector.IsolatedFileSystemManager} manager
  * @param {string} path
- * @param {string} name
- * @param {string} rootURL
+ * @param {!DOMFileSystem} domFileSystem
  */
-WebInspector.IsolatedFileSystem = function(manager, path, name, rootURL)
+WebInspector.IsolatedFileSystem = function(manager, path, domFileSystem)
 {
     this._manager = manager;
     this._path = path;
-    this._name = name;
-    this._rootURL = rootURL;
+    this._domFileSystem = domFileSystem;
+    this._excludedFoldersSetting = WebInspector.settings.createLocalSetting("workspaceExcludedFolders", {});
+    /** @type {!Set<string>} */
+    this._excludedFolders = new Set(this._excludedFoldersSetting.get()[path]);
+    /** @type {!Set<string>} */
+    this._nonConfigurableExcludedFolders = new Set();
+}
+
+/**
+ * @constructor
+ * @param {!WebInspector.IsolatedFileSystemManager} manager
+ * @param {string} path
+ * @param {string} name
+ * @param {string} rootURL
+ * @return {!Promise<?WebInspector.IsolatedFileSystem>}
+ */
+WebInspector.IsolatedFileSystem.create = function(manager, path, name, rootURL)
+{
+    return new Promise(promiseBody);
+
+    /**
+     * @param {function(?WebInspector.IsolatedFileSystem)} resolve
+     * @param {function(!Error)} reject
+     */
+    function promiseBody(resolve, reject)
+    {
+        var domFileSystem = InspectorFrontendHost.isolatedFileSystem(name, rootURL);
+        if (!domFileSystem) {
+            resolve(null);
+            return;
+        }
+        var fileSystem = new WebInspector.IsolatedFileSystem(manager, path, domFileSystem);
+        fileSystem.requestFileContent(".devtools", onConfigAvailable);
+
+        /**
+         * @param {?string} projectText
+         */
+        function onConfigAvailable(projectText)
+        {
+            if (projectText) {
+                try {
+                    var projectObject = JSON.parse(projectText);
+                    fileSystem._initializeProject(typeof projectObject === "object" ? /** @type {!Object} */ (projectObject) : null);
+                } catch (e) {
+                    WebInspector.console.error("Invalid project file: " + projectText);
+                }
+            }
+            resolve(fileSystem);
+        }
+    }
 }
 
 /**
@@ -84,27 +131,28 @@
     },
 
     /**
-     * @return {string}
+     * @param {?Object} projectObject
      */
-    name: function()
+    _initializeProject: function(projectObject)
     {
-        return this._name;
+        this._projectObject = projectObject;
+
+        var projectExcludes = this.projectProperty("excludes");
+        if (Array.isArray(projectExcludes)) {
+            for (var folder of /** @type {!Array<*>} */ (projectExcludes)) {
+                if (typeof folder === "string")
+                    this._nonConfigurableExcludedFolders.add(folder);
+            }
+        }
     },
 
     /**
-     * @return {string}
+     * @param {string} key
+     * @return {*}
      */
-    rootURL: function()
+    projectProperty: function(key)
     {
-        return this._rootURL;
-    },
-
-    /**
-     * @param {function(?DOMFileSystem)} callback
-     */
-    _requestFileSystem: function(callback)
-    {
-        this._manager.requestDOMFileSystem(this._path, callback);
+        return this._projectObject ? this._projectObject[key] : null;
     },
 
     /**
@@ -114,20 +162,8 @@
      */
     requestFilesRecursive: function(path, fileCallback, finishedCallback)
     {
-        var domFileSystem;
-        var pendingRequests = 0;
-        this._requestFileSystem(fileSystemLoaded.bind(this));
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            ++pendingRequests;
-            this._requestEntries(domFileSystem, path, innerCallback.bind(this));
-        }
+        var pendingRequests = 1;
+        this._requestEntries(path, innerCallback.bind(this));
 
         /**
          * @param {!Array.<!FileEntry>} entries
@@ -138,15 +174,14 @@
             for (var i = 0; i < entries.length; ++i) {
                 var entry = entries[i];
                 if (!entry.isDirectory) {
-                    if (this._manager.excludedFolderManager().isFileExcluded(this._path, entry.fullPath))
+                    if (this._isFileExcluded(entry.fullPath))
                         continue;
                     fileCallback(entry.fullPath.substr(1));
-                }
-                else {
-                    if (this._manager.excludedFolderManager().isFileExcluded(this._path, entry.fullPath + "/"))
+                } else {
+                    if (this._isFileExcluded(entry.fullPath + "/"))
                         continue;
                     ++pendingRequests;
-                    this._requestEntries(domFileSystem, entry.fullPath, innerCallback.bind(this));
+                    this._requestEntries(entry.fullPath, innerCallback.bind(this));
                 }
             }
             if (finishedCallback && (--pendingRequests === 0))
@@ -161,22 +196,12 @@
      */
     createFile: function(path, name, callback)
     {
-        this._requestFileSystem(fileSystemLoaded.bind(this));
         var newFileIndex = 1;
         if (!name)
             name = "NewFile";
         var nameCandidate;
 
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getDirectory(path, null, dirEntryLoaded.bind(this), errorHandler.bind(this));
-        }
+        this._domFileSystem.root.getDirectory(path, null, dirEntryLoaded.bind(this), errorHandler.bind(this));
 
         /**
          * @param {!DirectoryEntry} dirEntry
@@ -230,18 +255,7 @@
      */
     deleteFile: function(path)
     {
-        this._requestFileSystem(fileSystemLoaded.bind(this));
-
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
-        }
+        this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
 
         /**
          * @param {!FileEntry} fileEntry
@@ -273,17 +287,7 @@
      */
     requestMetadata: function(path, callback)
     {
-        this._requestFileSystem(fileSystemLoaded);
-
-        /**
-         * @param {?DOMFileSystem} fs
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getFile(path, null, fileEntryLoaded, errorHandler);
-        }
+        this._domFileSystem.root.getFile(path, null, fileEntryLoaded, errorHandler);
 
         /**
          * @param {!FileEntry} entry
@@ -316,18 +320,7 @@
      */
     requestFileContent: function(path, callback)
     {
-        this._requestFileSystem(fileSystemLoaded.bind(this));
-
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
-        }
+        this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
 
         /**
          * @param {!FileEntry} entry
@@ -386,19 +379,8 @@
      */
     setFileContent: function(path, content, callback)
     {
-        this._requestFileSystem(fileSystemLoaded.bind(this));
         WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.FileSavedInWorkspace);
-
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getFile(path, { create: true }, fileEntryLoaded.bind(this), errorHandler.bind(this));
-        }
+        this._domFileSystem.root.getFile(path, { create: true }, fileEntryLoaded.bind(this), errorHandler.bind(this));
 
         /**
          * @param {!FileEntry} entry
@@ -452,18 +434,8 @@
         }
         var fileEntry;
         var dirEntry;
-        this._requestFileSystem(fileSystemLoaded.bind(this));
 
-        /**
-         * @param {?DOMFileSystem} fs
-         * @this {WebInspector.IsolatedFileSystem}
-         */
-        function fileSystemLoaded(fs)
-        {
-            var domFileSystem = /** @type {!DOMFileSystem} */ (fs);
-            console.assert(domFileSystem);
-            domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
-        }
+        this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
 
         /**
          * @param {!FileEntry} entry
@@ -564,13 +536,12 @@
     },
 
     /**
-     * @param {!DOMFileSystem} domFileSystem
      * @param {string} path
      * @param {function(!Array.<!FileEntry>)} callback
      */
-    _requestEntries: function(domFileSystem, path, callback)
+    _requestEntries: function(path, callback)
     {
-        domFileSystem.root.getDirectory(path, null, innerCallback.bind(this), errorHandler);
+        this._domFileSystem.root.getDirectory(path, null, innerCallback.bind(this), errorHandler);
 
         /**
          * @param {!DirectoryEntry} dirEntry
@@ -587,5 +558,67 @@
             console.error(errorMessage + " when requesting entry '" + path + "'");
             callback([]);
         }
+    },
+
+    _saveExcludedFolders: function()
+    {
+        var settingValue = this._excludedFoldersSetting.get();
+        settingValue[this._path] = Array.from(this._excludedFolders.values());
+        this._excludedFoldersSetting.set(settingValue);
+    },
+
+    /**
+     * @param {string} path
+     */
+    addExcludedFolder: function(path)
+    {
+        this._excludedFolders.add(path);
+        this._saveExcludedFolders();
+        this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.ExcludedFolderAdded, path);
+    },
+
+    /**
+     * @param {string} path
+     */
+    removeExcludedFolder: function(path)
+    {
+        this._excludedFolders.delete(path);
+        this._saveExcludedFolders();
+        this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.ExcludedFolderRemoved, path);
+    },
+
+    fileSystemRemoved: function()
+    {
+        var settingValue = this._excludedFoldersSetting.get();
+        delete settingValue[this._path];
+        this._excludedFoldersSetting.set(settingValue);
+    },
+
+    /**
+     * @param {string} folderPath
+     * @return {boolean}
+     */
+    _isFileExcluded: function(folderPath)
+    {
+        if (this._nonConfigurableExcludedFolders.has(folderPath) || this._excludedFolders.has(folderPath))
+            return true;
+        var regex = this._manager.workspaceFolderExcludePatternSetting().asRegExp();
+        return !!(regex && regex.test(folderPath));
+    },
+
+    /**
+     * @return {!Set<string>}
+     */
+    excludedFolders: function()
+    {
+        return this._excludedFolders;
+    },
+
+    /**
+     * @return {!Set<string>}
+     */
+    nonConfigurableExcludedFolders: function()
+    {
+        return this._nonConfigurableExcludedFolders;
     }
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js
index 6066615..ee355fa 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js
@@ -36,13 +36,12 @@
 {
     /** @type {!Object.<string, !WebInspector.IsolatedFileSystem>} */
     this._fileSystems = {};
-    /** @type {!Object.<string, !Array.<function(?DOMFileSystem)>>} */
-    this._pendingFileSystemRequests = {};
-    this._excludedFolderManager = new WebInspector.ExcludedFolderManager();
 
     InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.FileSystemsLoaded, this._onFileSystemsLoaded, this);
     InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.FileSystemRemoved, this._onFileSystemRemoved, this);
     InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.FileSystemAdded, this._onFileSystemAdded, this);
+
+    this._initExcludePatterSetting();
 }
 
 /** @typedef {!{fileSystemName: string, rootURL: string, fileSystemPath: string}} */
@@ -50,24 +49,17 @@
 
 WebInspector.IsolatedFileSystemManager.Events = {
     FileSystemAdded: "FileSystemAdded",
-    FileSystemRemoved: "FileSystemRemoved"
+    FileSystemRemoved: "FileSystemRemoved",
+    ExcludedFolderAdded: "ExcludedFolderAdded",
+    ExcludedFolderRemoved: "ExcludedFolderRemoved"
 }
 
 WebInspector.IsolatedFileSystemManager.prototype = {
     /**
-     * @return {!WebInspector.ExcludedFolderManager}
-     */
-    excludedFolderManager: function()
-    {
-        return this._excludedFolderManager;
-    },
-
-    /**
      * @param {function()} callback
      */
     initialize: function(callback)
     {
-        console.assert(!this._loaded);
         this._initializeCallback = callback;
         InspectorFrontendHost.requestFileSystems();
     },
@@ -91,38 +83,33 @@
     _onFileSystemsLoaded: function(event)
     {
         var fileSystems = /** @type {!Array.<!WebInspector.IsolatedFileSystemManager.FileSystem>} */ (event.data);
-        var addedFileSystemPaths = {};
-        for (var i = 0; i < fileSystems.length; ++i) {
-            this._innerAddFileSystem(fileSystems[i]);
-            addedFileSystemPaths[fileSystems[i].fileSystemPath] = true;
-        }
-
-        this._loaded = true;
-
-        this._initializeCallback();
-        delete this._initializeCallback;
-        this._processPendingFileSystemRequests();
+        var promises = [];
+        for (var i = 0; i < fileSystems.length; ++i)
+            promises.push(this._innerAddFileSystem(fileSystems[i]));
+        Promise.all(promises).then(this._initializeCallback);
     },
 
     /**
      * @param {!WebInspector.IsolatedFileSystemManager.FileSystem} fileSystem
+     * @return {!Promise}
      */
     _innerAddFileSystem: function(fileSystem)
     {
         var fileSystemPath = fileSystem.fileSystemPath;
-        var isolatedFileSystem = new WebInspector.IsolatedFileSystem(this, fileSystemPath, fileSystem.fileSystemName, fileSystem.rootURL);
-        this._fileSystems[fileSystemPath] = isolatedFileSystem;
-        this.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, isolatedFileSystem);
-    },
+        var promise = WebInspector.IsolatedFileSystem.create(this, fileSystemPath, fileSystem.fileSystemName, fileSystem.rootURL);
+        return promise.then(storeFileSystem.bind(this));
 
-    _processPendingFileSystemRequests: function()
-    {
-        for (var fileSystemPath in this._pendingFileSystemRequests) {
-            var callbacks = this._pendingFileSystemRequests[fileSystemPath];
-            for (var i = 0; i < callbacks.length; ++i)
-                callbacks[i](this._isolatedFileSystem(fileSystemPath));
+        /**
+         * @param {?WebInspector.IsolatedFileSystem} fileSystem
+         * @this {WebInspector.IsolatedFileSystemManager}
+         */
+        function storeFileSystem(fileSystem)
+        {
+            if (!fileSystem)
+                return;
+            this._fileSystems[fileSystemPath] = fileSystem;
+            this.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, fileSystem);
         }
-        delete this._pendingFileSystemRequests;
     },
 
     /**
@@ -151,40 +138,12 @@
      */
     _fileSystemRemoved: function(fileSystemPath)
     {
-        this._excludedFolderManager.removeFileSystem(fileSystemPath);
         var isolatedFileSystem = this._fileSystems[fileSystemPath];
         delete this._fileSystems[fileSystemPath];
-        if (isolatedFileSystem)
+        if (isolatedFileSystem) {
+            isolatedFileSystem.fileSystemRemoved();
             this.dispatchEventToListeners(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, isolatedFileSystem);
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @return {?DOMFileSystem}
-     */
-    _isolatedFileSystem: function(fileSystemPath)
-    {
-        var fileSystem = this._fileSystems[fileSystemPath];
-        if (!fileSystem)
-            return null;
-        if (!InspectorFrontendHost.isolatedFileSystem)
-            return null;
-        return InspectorFrontendHost.isolatedFileSystem(fileSystem.name(), fileSystem.rootURL());
-    },
-
-    /**
-     * @param {string} fileSystemPath
-     * @param {function(?DOMFileSystem)} callback
-     */
-    requestDOMFileSystem: function(fileSystemPath, callback)
-    {
-        if (!this._loaded) {
-            if (!this._pendingFileSystemRequests[fileSystemPath])
-                this._pendingFileSystemRequests[fileSystemPath] = this._pendingFileSystemRequests[fileSystemPath] || [];
-            this._pendingFileSystemRequests[fileSystemPath].push(callback);
-            return;
         }
-        callback(this._isolatedFileSystem(fileSystemPath));
     },
 
     /**
@@ -195,6 +154,64 @@
         return Object.keys(this._fileSystems);
     },
 
+    /**
+     * @param {string} fileSystemPath
+     * @return {?WebInspector.IsolatedFileSystem}
+     */
+    fileSystem: function(fileSystemPath)
+    {
+        return this._fileSystems[fileSystemPath];
+    },
+
+    _initExcludePatterSetting: function()
+    {
+        var defaultCommonExcludedFolders = [
+            "/\\.devtools",
+            "/\\.git/",
+            "/\\.sass-cache/",
+            "/\\.hg/",
+            "/\\.idea/",
+            "/\\.svn/",
+            "/\\.cache/",
+            "/\\.project/"
+        ];
+        var defaultWinExcludedFolders = [
+            "/Thumbs.db$",
+            "/ehthumbs.db$",
+            "/Desktop.ini$",
+            "/\\$RECYCLE.BIN/"
+        ];
+        var defaultMacExcludedFolders = [
+            "/\\.DS_Store$",
+            "/\\.Trashes$",
+            "/\\.Spotlight-V100$",
+            "/\\.AppleDouble$",
+            "/\\.LSOverride$",
+            "/Icon$",
+            "/\\._.*$"
+        ];
+        var defaultLinuxExcludedFolders = [
+            "/.*~$"
+        ];
+        var defaultExcludedFolders = defaultCommonExcludedFolders;
+        if (WebInspector.isWin())
+            defaultExcludedFolders = defaultExcludedFolders.concat(defaultWinExcludedFolders);
+        else if (WebInspector.isMac())
+            defaultExcludedFolders = defaultExcludedFolders.concat(defaultMacExcludedFolders);
+        else
+            defaultExcludedFolders = defaultExcludedFolders.concat(defaultLinuxExcludedFolders);
+        var defaultExcludedFoldersPattern = defaultExcludedFolders.join("|");
+        this._workspaceFolderExcludePatternSetting = WebInspector.settings.createRegExpSetting("workspaceFolderExcludePattern", defaultExcludedFoldersPattern, WebInspector.isWin() ? "i" : "");
+    },
+
+    /**
+     * @return {!WebInspector.Setting}
+     */
+    workspaceFolderExcludePatternSetting: function()
+    {
+        return this._workspaceFolderExcludePatternSetting;
+    },
+
     __proto__: WebInspector.Object.prototype
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
index b2a07ac..b712cae 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/UISourceCode.js
@@ -318,22 +318,18 @@
      */
     _commitContent: function(content)
     {
+        var wasPersisted = false;
         if (this._project.canSetFileContent()) {
-            this._project.setFileContent(this, content, this._contentCommitted.bind(this, content, true));
-            return;
-        }
-        if (this._project.workspace().hasResourceContentTrackingExtensions()) {
-            this._contentCommitted(content, true);
-            return;
-        }
-
-        if (this._originURL && WebInspector.fileManager.isURLSaved(this._originURL)) {
-            WebInspector.fileManager.save(this._originURL, content, false, this._contentCommitted.bind(this, content));
+            this._project.setFileContent(this, content, function() { });
+            wasPersisted = true;
+        } else if (this._project.workspace().hasResourceContentTrackingExtensions()) {
+            wasPersisted = true;
+        } else if (this._originURL && WebInspector.fileManager.isURLSaved(this._originURL)) {
+            WebInspector.fileManager.save(this._originURL, content, false, function() { });
             WebInspector.fileManager.close(this._originURL);
-            return;
+            wasPersisted = true;
         }
-
-        this._contentCommitted(content, false);
+        this._contentCommitted(content, wasPersisted);
     },
 
     /**
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/module.json b/third_party/WebKit/Source/devtools/front_end/workspace/module.json
index 13d6aba0..87ef11d 100644
--- a/third_party/WebKit/Source/devtools/front_end/workspace/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/workspace/module.json
@@ -1,7 +1,6 @@
 {
     "dependencies": ["common", "host", "platform"],
     "scripts": [
-        "ExcludedFolderManager.js",
         "FileManager.js",
         "FileSystemMapping.js",
         "IsolatedFileSystem.js",
diff --git a/third_party/WebKit/Source/devtools/scripts/generate_protocol_externs.py b/third_party/WebKit/Source/devtools/scripts/generate_protocol_externs.py
index 1cf87c1f..fca2d63 100755
--- a/third_party/WebKit/Source/devtools/scripts/generate_protocol_externs.py
+++ b/third_party/WebKit/Source/devtools/scripts/generate_protocol_externs.py
@@ -41,6 +41,7 @@
 
 promisified_domains = {
     "Accessibility",
+    "Animation",
     "CSS",
     "Emulation",
     "Profiler"
diff --git a/third_party/WebKit/Source/modules/InitModules.cpp b/third_party/WebKit/Source/modules/InitModules.cpp
index 439be2a..ac4736b2 100644
--- a/third_party/WebKit/Source/modules/InitModules.cpp
+++ b/third_party/WebKit/Source/modules/InitModules.cpp
@@ -28,6 +28,11 @@
     ASSERT(!isInitialized());
 
     // Strings must be initialized before calling CoreInitializer::init().
+    const unsigned modulesStaticStringsCount = EventNames::EventModulesNamesCount
+        + EventTargetNames::EventTargetModulesNamesCount
+        + IndexedDBNames::IndexedDBNamesCount;
+    StringImpl::reserveStaticStringsCapacityForSize(modulesStaticStringsCount);
+
     EventNames::initModules();
     EventTargetNames::initModules();
     Document::registerEventFactory(EventModulesFactory::create());
diff --git a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
index 1818e9f..50efc83c 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.cpp
@@ -81,7 +81,7 @@
     return parent;
 }
 
-void AXARIAGridCell::rowIndexRange(pair<unsigned, unsigned>& rowRange)
+void AXARIAGridCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange)
 {
     AXObject* parent = parentObjectUnignored();
     if (!parent)
@@ -111,7 +111,7 @@
     rowRange.second = 1;
 }
 
-void AXARIAGridCell::columnIndexRange(pair<unsigned, unsigned>& columnRange)
+void AXARIAGridCell::columnIndexRange(std::pair<unsigned, unsigned>& columnRange)
 {
     AXObject* parent = parentObjectUnignored();
     if (!parent)
diff --git a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
index 8dfe8047..cc51327 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXARIAGridCell.h
@@ -45,9 +45,9 @@
     ~AXARIAGridCell() override;
 
     // fills in the start location and row span of cell
-    void rowIndexRange(pair<unsigned, unsigned>& rowRange) override;
+    void rowIndexRange(std::pair<unsigned, unsigned>& rowRange) override;
     // fills in the start location and column span of cell
-    void columnIndexRange(pair<unsigned, unsigned>& columnRange) override;
+    void columnIndexRange(std::pair<unsigned, unsigned>& columnRange) override;
     AccessibilityRole scanToDecideHeaderRole() final;
 
 protected:
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index 90193dd..80cd90a 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -2246,20 +2246,6 @@
     return 0;
 }
 
-void AXLayoutObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result)
-{
-    bool isMulti = isMultiSelectable();
-
-    for (const auto& child : children()) {
-        // Every child should have aria-role option, and if so, check for selected attribute/state.
-        if (child->isSelected() && child->ariaRoleAttribute() == ListBoxOptionRole) {
-            result.append(child);
-            if (!isMulti)
-                return;
-        }
-    }
-}
-
 bool AXLayoutObject::nodeIsTextControl(const Node* node) const
 {
     if (!node)
@@ -2554,35 +2540,6 @@
     }
 }
 
-void AXLayoutObject::ariaSelectedRows(AccessibilityChildrenVector& result)
-{
-    // Get all the rows.
-    AccessibilityChildrenVector allRows;
-    if (isTree())
-        ariaTreeRows(allRows);
-    else if (isAXTable() && toAXTable(this)->supportsSelectedRows())
-        allRows = toAXTable(this)->rows();
-
-    // Determine which rows are selected.
-    bool isMulti = isMultiSelectable();
-
-    // Prefer active descendant over aria-selected.
-    AXObject* activeDesc = activeDescendant();
-    if (activeDesc && (activeDesc->isTreeItem() || activeDesc->isTableRow())) {
-        result.append(activeDesc);
-        if (!isMulti)
-            return;
-    }
-
-    for (const auto& row : allRows) {
-        if (row->isSelected()) {
-            result.append(row);
-            if (!isMulti)
-                break;
-        }
-    }
-}
-
 bool AXLayoutObject::elementAttributeValue(const QualifiedName& attributeName) const
 {
     if (!m_layoutObject)
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
index 163580e..9a41d165 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.h
@@ -202,7 +202,6 @@
 
 private:
     AXObject* treeAncestorDisallowingChild() const;
-    void ariaListboxSelectedChildren(AccessibilityChildrenVector&);
     bool nodeIsTextControl(const Node*) const;
     bool isTabItemSelected() const;
     bool isValidSelectionBound(const AXObject*) const;
@@ -222,7 +221,6 @@
     void addRemoteSVGChildren();
     void addInlineTextBoxChildren(bool force);
 
-    void ariaSelectedRows(AccessibilityChildrenVector&);
     bool elementAttributeValue(const QualifiedName&) const;
     LayoutRect computeElementRect() const;
     AXRange textControlSelection() const;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
index ff87ae1..7d8ecad 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
@@ -1192,7 +1192,7 @@
     client.postAccessibilityNotification(obj, notification);
 }
 
-void AXObjectCacheImpl::handleFocusedUIElementChanged(Node*, Node* newFocusedNode)
+void AXObjectCacheImpl::handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode)
 {
     if (!newFocusedNode)
         return;
@@ -1205,6 +1205,9 @@
     if (!focusedObject)
         return;
 
+    AXObject* oldFocusedObject = get(oldFocusedNode);
+
+    postPlatformNotification(oldFocusedObject, AXBlur);
     postPlatformNotification(focusedObject, AXFocusedUIElementChanged);
 }
 
@@ -1333,6 +1336,13 @@
     return String();
 }
 
+void AXObjectCacheImpl::onTouchAccessibilityHover(const IntPoint& location)
+{
+    AXObject* hit = root()->accessibilityHitTest(location);
+    if (hit)
+        postPlatformNotification(hit, AXHover);
+}
+
 void AXObjectCacheImpl::setCanvasObjectBounds(Element* element, const LayoutRect& rect)
 {
     AXObject* obj = getOrCreate(element);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
index 8185a2cd..14417927 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
@@ -107,6 +107,8 @@
     const AtomicString& computedRoleForNode(Node*) override;
     String computedNameForNode(Node*) override;
 
+    void onTouchAccessibilityHover(const IntPoint&) override;
+
     // Returns the root object for the entire document.
     AXObject* rootObject();
 
@@ -236,7 +238,7 @@
     HashMap<String, OwnPtr<HashSet<AXID>>> m_idToAriaOwnersMapping;
 
     Timer<AXObjectCacheImpl> m_notificationPostTimer;
-    HeapVector<pair<Member<AXObject>, AXNotification>> m_notificationsToPost;
+    HeapVector<std::pair<Member<AXObject>, AXNotification>> m_notificationsToPost;
     void notificationPostTimerFired(Timer<AXObjectCacheImpl>*);
 
     AXObject* focusedImageMapUIElement(HTMLAreaElement*);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXTable.cpp b/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
index 78a2f0d1..527eb86f 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXTable.cpp
@@ -531,8 +531,8 @@
             if (!child->isTableCell())
                 continue;
 
-            pair<unsigned, unsigned> columnRange;
-            pair<unsigned, unsigned> rowRange;
+            std::pair<unsigned, unsigned> columnRange;
+            std::pair<unsigned, unsigned> rowRange;
             AXTableCell* tableCellChild = toAXTableCell(child);
             tableCellChild->columnIndexRange(columnRange);
             tableCellChild->rowIndexRange(rowRange);
diff --git a/third_party/WebKit/Source/modules/accessibility/AXTableCell.cpp b/third_party/WebKit/Source/modules/accessibility/AXTableCell.cpp
index 8fdd961..2d55d6e 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXTableCell.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXTableCell.cpp
@@ -161,7 +161,7 @@
     return scanToDecideHeaderRole();
 }
 
-void AXTableCell::rowIndexRange(pair<unsigned, unsigned>& rowRange)
+void AXTableCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange)
 {
     if (!m_layoutObject || !m_layoutObject->isTableCell())
         return;
@@ -188,7 +188,7 @@
     rowRange.first += rowOffset;
 }
 
-void AXTableCell::columnIndexRange(pair<unsigned, unsigned>& columnRange)
+void AXTableCell::columnIndexRange(std::pair<unsigned, unsigned>& columnRange)
 {
     if (!m_layoutObject || !m_layoutObject->isTableCell())
         return;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXTableCell.h b/third_party/WebKit/Source/modules/accessibility/AXTableCell.h
index f62b0d1c..8d93b05 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXTableCell.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXTableCell.h
@@ -47,9 +47,9 @@
     bool isTableCell() const final;
 
     // fills in the start location and row span of cell
-    virtual void rowIndexRange(pair<unsigned, unsigned>& rowRange);
+    virtual void rowIndexRange(std::pair<unsigned, unsigned>& rowRange);
     // fills in the start location and column span of cell
-    virtual void columnIndexRange(pair<unsigned, unsigned>& columnRange);
+    virtual void columnIndexRange(std::pair<unsigned, unsigned>& columnRange);
     // In the case of cells that act as row or column headers.
     SortDirection sortDirection() const final;
     virtual AccessibilityRole scanToDecideHeaderRole();
diff --git a/third_party/WebKit/Source/modules/background_sync/PeriodicSyncRegistration.cpp b/third_party/WebKit/Source/modules/background_sync/PeriodicSyncRegistration.cpp
index b67ada9..da82231d 100644
--- a/third_party/WebKit/Source/modules/background_sync/PeriodicSyncRegistration.cpp
+++ b/third_party/WebKit/Source/modules/background_sync/PeriodicSyncRegistration.cpp
@@ -79,7 +79,7 @@
     WebSyncProvider* webSyncProvider = Platform::current()->backgroundSyncProvider();
     ASSERT(webSyncProvider);
 
-    webSyncProvider->unregisterBackgroundSync(WebSyncRegistration::PeriodicityPeriodic, m_id, m_tag, m_serviceWorkerRegistration->webRegistration(), new SyncUnregistrationCallbacks(resolver, m_serviceWorkerRegistration));
+    webSyncProvider->unregisterBackgroundSync(m_id, m_serviceWorkerRegistration->webRegistration(), new SyncUnregistrationCallbacks(resolver, m_serviceWorkerRegistration));
 
     return promise;
 }
diff --git a/third_party/WebKit/Source/modules/background_sync/SyncRegistration.cpp b/third_party/WebKit/Source/modules/background_sync/SyncRegistration.cpp
index 21c3758..9075288 100644
--- a/third_party/WebKit/Source/modules/background_sync/SyncRegistration.cpp
+++ b/third_party/WebKit/Source/modules/background_sync/SyncRegistration.cpp
@@ -77,7 +77,7 @@
     WebSyncProvider* webSyncProvider = Platform::current()->backgroundSyncProvider();
     ASSERT(webSyncProvider);
 
-    webSyncProvider->unregisterBackgroundSync(WebSyncRegistration::PeriodicityOneShot, m_id, m_tag, m_serviceWorkerRegistration->webRegistration(), new SyncUnregistrationCallbacks(resolver, m_serviceWorkerRegistration));
+    webSyncProvider->unregisterBackgroundSync(m_id, m_serviceWorkerRegistration->webRegistration(), new SyncUnregistrationCallbacks(resolver, m_serviceWorkerRegistration));
 
     return promise;
 }
diff --git a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
index 8bfe302..421002c 100644
--- a/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
+++ b/third_party/WebKit/Source/modules/bluetooth/Bluetooth.cpp
@@ -55,7 +55,7 @@
 {
     // 1. If the incumbent settings object is not a secure context, reject promise with a SecurityError and abort these steps.
     String errorMessage;
-    if (!scriptState->executionContext()->isPrivilegedContext(errorMessage)) {
+    if (!scriptState->executionContext()->isSecureContext(errorMessage)) {
         return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, errorMessage));
     }
 
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
index 5f74d51..62edb3d 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
@@ -33,7 +33,7 @@
         return false;
 
     String errorMessage;
-    if (!executionContext->isPrivilegedContext(errorMessage)) {
+    if (!executionContext->isSecureContext(errorMessage)) {
         exceptionState.throwSecurityError(errorMessage);
         return false;
     }
diff --git a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
index 0c18df8f..38a13495 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp
@@ -11,6 +11,7 @@
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/frame/UseCounter.h"
 #include "modules/credentialmanager/Credential.h"
 #include "modules/credentialmanager/CredentialManagerClient.h"
 #include "modules/credentialmanager/CredentialRequestOptions.h"
@@ -108,7 +109,7 @@
     }
 
     String errorMessage;
-    if (!resolver->scriptState()->executionContext()->isPrivilegedContext(errorMessage)) {
+    if (!resolver->scriptState()->executionContext()->isSecureContext(errorMessage)) {
         resolver->reject(DOMException::create(SecurityError, errorMessage));
         return false;
     }
@@ -132,6 +133,10 @@
         }
     }
 
+    UseCounter::count(scriptState->executionContext(),
+                      options.suppressUI() ? UseCounter::CredentialManagerGetWithoutUI
+                                           : UseCounter::CredentialManagerGetWithUI);
+
     CredentialManagerClient::from(scriptState->executionContext())->dispatchGet(options.suppressUI(), providers, new RequestCallbacks(resolver));
     return promise;
 }
diff --git a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.idl b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.idl
index 787fc22..44b3c7b 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.idl
+++ b/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.idl
@@ -6,8 +6,8 @@
     RuntimeEnabled=CredentialManager,
     GarbageCollected
 ] interface CredentialsContainer {
-    [CallWith=ScriptState] Promise get(optional CredentialRequestOptions options);
-    [CallWith=ScriptState, TypeChecking=Interface] Promise store(Credential credential);
-    [CallWith=ScriptState] Promise requireUserMediation();
+    [CallWith=ScriptState, MeasureAs=CredentialManagerGet] Promise get(optional CredentialRequestOptions options);
+    [CallWith=ScriptState, MeasureAs=CredentialManagerStore, TypeChecking=Interface] Promise store(Credential credential);
+    [CallWith=ScriptState, MeasureAs=CredentialManagerRequireUserMediation] Promise requireUserMediation();
 };
 
diff --git a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
index a928665..0fcae13 100644
--- a/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
+++ b/third_party/WebKit/Source/modules/credentialmanager/PasswordCredential.cpp
@@ -46,7 +46,7 @@
     FormData* fd = FormData::create();
 
     String errorMessage;
-    if (!scriptState->executionContext()->isPrivilegedContext(errorMessage))
+    if (!scriptState->executionContext()->isSecureContext(errorMessage))
         return fd;
 
     fd->append(options.idName(), id());
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
index 8ce6d339..65d84fc 100644
--- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
+++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp
@@ -56,7 +56,7 @@
 static bool canAccessWebCrypto(ScriptState* scriptState, CryptoResult* result)
 {
     String errorMessage;
-    if (!scriptState->executionContext()->isPrivilegedContext(errorMessage, ExecutionContext::WebCryptoPrivilegeCheck)) {
+    if (!scriptState->executionContext()->isSecureContext(errorMessage, ExecutionContext::WebCryptoSecureContextCheck)) {
         result->completeWithError(WebCryptoErrorTypeNotSupported, errorMessage);
         return false;
     }
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
index b748f6f..bd5a1071 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceMotionController.cpp
@@ -52,7 +52,7 @@
 
     if (document().frame()) {
         String errorMessage;
-        if (document().isPrivilegedContext(errorMessage)) {
+        if (document().isSecureContext(errorMessage)) {
             UseCounter::count(document().frame(), UseCounter::DeviceMotionSecureOrigin);
         } else {
             UseCounter::countDeprecation(document().frame(), UseCounter::DeviceMotionInsecureOrigin);
diff --git a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
index 1e9ef4f..cf71466 100644
--- a/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
+++ b/third_party/WebKit/Source/modules/device_orientation/DeviceOrientationController.cpp
@@ -59,7 +59,7 @@
 
     if (document().frame()) {
         String errorMessage;
-        if (document().isPrivilegedContext(errorMessage)) {
+        if (document().isSecureContext(errorMessage)) {
             UseCounter::count(document().frame(), UseCounter::DeviceOrientationSecureOrigin);
         } else {
             UseCounter::countDeprecation(document().frame(), UseCounter::DeviceOrientationInsecureOrigin);
diff --git a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
index 0e8aeea..eb3cf81 100644
--- a/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
+++ b/third_party/WebKit/Source/modules/encryptedmedia/NavigatorRequestMediaKeySystemAccess.cpp
@@ -184,7 +184,7 @@
     // 3-4. 'May Document use powerful features?' check.
     ExecutionContext* executionContext = scriptState->executionContext();
     String errorMessage;
-    if (executionContext->isPrivilegedContext(errorMessage)) {
+    if (executionContext->isSecureContext(errorMessage)) {
         UseCounter::count(executionContext, UseCounter::EncryptedMediaSecureOrigin);
     } else {
         UseCounter::countDeprecation(executionContext, UseCounter::EncryptedMediaInsecureOrigin);
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
index 1d3dbde..f3efdfc5 100644
--- a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
@@ -194,12 +194,14 @@
 {
     m_reader = nullptr;
     m_stream->close();
+    m_handle.clear();
 }
 
 void BodyStreamBuffer::error()
 {
     m_reader = nullptr;
     m_stream->error(DOMException::create(NetworkError, "network error"));
+    m_handle.clear();
 }
 
 void BodyStreamBuffer::processData()
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
index 37bc9934..769fc35b 100644
--- a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
@@ -34,6 +34,7 @@
     ~BodyStreamBufferTest() override {}
 
 protected:
+    ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->document().frame()); }
     ExecutionContext* executionContext() { return &m_page->document(); }
 
     OwnPtr<DummyPageHolder> m_page;
@@ -264,6 +265,46 @@
     checkpoint.Call(2);
 }
 
+// TODO(hiroshige): Merge this class into MockFetchDataConsumerHandle.
+class MockFetchDataConsumerHandleWithMockDestructor : public DataConsumerHandleTestUtil::MockFetchDataConsumerHandle {
+public:
+    static PassOwnPtr<::testing::StrictMock<MockFetchDataConsumerHandleWithMockDestructor>> create() { return adoptPtr(new ::testing::StrictMock<MockFetchDataConsumerHandleWithMockDestructor>); }
+
+    ~MockFetchDataConsumerHandleWithMockDestructor() override
+    {
+        destruct();
+    }
+
+    MOCK_METHOD0(destruct, void());
+};
+
+TEST_F(BodyStreamBufferTest, SourceHandleAndReaderShouldBeDestructedWhenCanceled)
+{
+    ScriptState::Scope scope(scriptState());
+    using MockHandle = MockFetchDataConsumerHandleWithMockDestructor;
+    using MockReader = DataConsumerHandleTestUtil::MockFetchDataConsumerReader;
+    OwnPtr<MockHandle> handle = MockHandle::create();
+    OwnPtr<MockReader> reader = MockReader::create();
+
+    Checkpoint checkpoint;
+    InSequence s;
+
+    EXPECT_CALL(*handle, obtainReaderInternal(_)).WillOnce(::testing::Return(reader.get()));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*reader, destruct());
+    EXPECT_CALL(*handle, destruct());
+    EXPECT_CALL(checkpoint, Call(2));
+
+    // |reader| is adopted by |obtainReader|.
+    ASSERT_TRUE(reader.leakPtr());
+
+    BodyStreamBuffer* buffer = new BodyStreamBuffer(handle.release());
+    checkpoint.Call(1);
+    ScriptValue reason(scriptState(), v8String(scriptState()->isolate(), "reason"));
+    buffer->cancelSource(scriptState(), reason);
+    checkpoint.Call(2);
+}
+
 } // namespace
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
index e232759..0b107f9 100644
--- a/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
+++ b/third_party/WebKit/Source/modules/geolocation/Geolocation.cpp
@@ -152,11 +152,11 @@
     Document* document = this->document();
     ASSERT(document);
 
-    // It is required by isPrivilegedContext() but isn't
+    // It is required by isSecureContext() but isn't
     // actually used. This could be used later if a warning is shown in the
     // developer console.
     String insecureOriginMsg;
-    if (document->isPrivilegedContext(insecureOriginMsg)) {
+    if (document->isSecureContext(insecureOriginMsg)) {
         UseCounter::count(document, UseCounter::GeolocationSecureOrigin);
     } else {
         UseCounter::countDeprecation(document, UseCounter::GeolocationInsecureOrigin);
@@ -199,7 +199,7 @@
 {
     if (frame()->settings()->strictPowerfulFeatureRestrictions()) {
         String errorMessage;
-        if (!executionContext()->isPrivilegedContext(errorMessage)) {
+        if (!executionContext()->isSecureContext(errorMessage)) {
             notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, errorMessage));
             return;
         }
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
index 3605b53..e376f6c2 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
+++ b/third_party/WebKit/Source/modules/indexeddb/IDBCursor.cpp
@@ -321,7 +321,9 @@
     IDBObjectStore* objectStore = effectiveObjectStore();
     const IDBObjectStoreMetadata& metadata = objectStore->metadata();
     IDBAny* value;
-    if (metadata.autoIncrement && !metadata.keyPath.isNull()) {
+    if (!m_value) {
+        value = IDBAny::createUndefined();
+    } else if (metadata.autoIncrement && !metadata.keyPath.isNull()) {
         RefPtr<IDBValue> idbValue = IDBValue::create(m_value.get(), m_primaryKey, metadata.keyPath);
 #if ENABLE(ASSERT)
         assertPrimaryKeyValidOrInjectable(scriptState, idbValue.get());
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
index 9f6bef2..6a8d2042 100644
--- a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
+++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
@@ -227,31 +227,37 @@
 
 bool MediaSource::isTypeSupported(const String& type)
 {
-    WTF_LOG(Media, "MediaSource::isTypeSupported(%s)", type.ascii().data());
-
     // Section 2.2 isTypeSupported() method steps.
     // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.html#widl-MediaSource-isTypeSupported-boolean-DOMString-type
     // 1. If type is an empty string, then return false.
-    if (type.isNull() || type.isEmpty())
+    if (type.isEmpty()) {
+        WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (empty input)", type.ascii().data());
         return false;
+    }
 
     ContentType contentType(type);
     String codecs = contentType.parameter("codecs");
 
     // 2. If type does not contain a valid MIME type string, then return false.
-    if (contentType.type().isEmpty())
+    if (contentType.type().isEmpty()) {
+        WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (invalid mime type)", type.ascii().data());
         return false;
+    }
 
     // Note: MediaSource.isTypeSupported() returning true implies that HTMLMediaElement.canPlayType() will return "maybe" or "probably"
     // since it does not make sense for a MediaSource to support a type the HTMLMediaElement knows it cannot play.
-    if (HTMLMediaElement::supportsType(contentType, String()) == WebMimeRegistry::IsNotSupported)
+    if (HTMLMediaElement::supportsType(contentType, String()) == WebMimeRegistry::IsNotSupported) {
+        WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> false (not supported by HTMLMediaElement)", type.ascii().data());
         return false;
+    }
 
     // 3. If type contains a media type or media subtype that the MediaSource does not support, then return false.
     // 4. If type contains at a codec that the MediaSource does not support, then return false.
     // 5. If the MediaSource does not support the specified combination of media type, media subtype, and codecs then return false.
     // 6. Return true.
-    return MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs);
+    bool result = MIMETypeRegistry::isSupportedMediaSourceMIMEType(contentType.type(), codecs);
+    WTF_LOG(Media, "MediaSource::isTypeSupported(%s) -> %s", type.ascii().data(), result ? "true" : "false");
+    return result;
 }
 
 const AtomicString& MediaSource::interfaceName() const
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
index 1d6b51be..48c195b1 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
@@ -106,7 +106,7 @@
     }
 
     String errorMessage;
-    if (!request->isPrivilegedContextUse(errorMessage)) {
+    if (!request->isSecureContextUse(errorMessage)) {
         return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError, errorMessage));
     }
 
diff --git a/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp b/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp
index 3b79806..8baea0e 100644
--- a/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/NavigatorMediaStream.cpp
@@ -58,7 +58,7 @@
     }
 
     String errorMessage;
-    if (!request->isPrivilegedContextUse(errorMessage)) {
+    if (!request->isSecureContextUse(errorMessage)) {
         request->failPermissionDenied(errorMessage);
         return;
     }
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
index ba8e286..49b6a29 100644
--- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.cpp
@@ -117,11 +117,11 @@
     return m_video;
 }
 
-bool UserMediaRequest::isPrivilegedContextUse(String& errorMessage)
+bool UserMediaRequest::isSecureContextUse(String& errorMessage)
 {
     Document* document = ownerDocument();
 
-    if (document->isPrivilegedContext(errorMessage)) {
+    if (document->isSecureContext(errorMessage)) {
         UseCounter::count(document->frame(), UseCounter::GetUserMediaSecureOrigin);
         OriginsUsingFeatures::countAnyWorld(*document, OriginsUsingFeatures::Feature::GetUserMediaSecureOrigin);
         return true;
diff --git a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h
index 33e2902a..c481f81 100644
--- a/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h
+++ b/third_party/WebKit/Source/modules/mediastream/UserMediaRequest.h
@@ -74,7 +74,7 @@
 
     // errorMessage is only set if requestIsPrivilegedContext() returns |false|.
     // Caller is responsible for properly setting errors and canceling request.
-    bool isPrivilegedContextUse(String& errorMessage);
+    bool isSecureContextUse(String& errorMessage);
 
     // ContextLifecycleObserver
     void contextDestroyed() override;
diff --git a/third_party/WebKit/Source/modules/notifications/Notification.cpp b/third_party/WebKit/Source/modules/notifications/Notification.cpp
index 99649be8..6f89e3d 100644
--- a/third_party/WebKit/Source/modules/notifications/Notification.cpp
+++ b/third_party/WebKit/Source/modules/notifications/Notification.cpp
@@ -80,7 +80,7 @@
     }
 
     String insecureOriginMessage;
-    UseCounter::Feature feature = context->isPrivilegedContext(insecureOriginMessage)
+    UseCounter::Feature feature = context->isSecureContext(insecureOriginMessage)
         ? UseCounter::NotificationSecureOrigin
         : UseCounter::NotificationInsecureOrigin;
 
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp
index 5dea391..a114ff48 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp
+++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.cpp
@@ -32,7 +32,7 @@
 
 PushSubscription::PushSubscription(const WebPushSubscription& subscription, ServiceWorkerRegistration* serviceWorkerRegistration)
     : m_endpoint(subscription.endpoint)
-    , m_curve25519dh(DOMArrayBuffer::create(subscription.curve25519dh.data(), subscription.curve25519dh.size()))
+    , m_p256dh(DOMArrayBuffer::create(subscription.p256dh.data(), subscription.p256dh.size()))
     , m_serviceWorkerRegistration(serviceWorkerRegistration)
 {
 }
@@ -48,8 +48,8 @@
 
 PassRefPtr<DOMArrayBuffer> PushSubscription::getKey(const AtomicString& name) const
 {
-    if (name == "curve25519dh")
-        return m_curve25519dh;
+    if (name == "p256dh")
+        return m_p256dh;
 
     return nullptr;
 }
@@ -71,7 +71,7 @@
     V8ObjectBuilder result(scriptState);
     result.addString("endpoint", endpoint());
 
-    // TODO(peter): Include |curve25519dh| in the serialized JSON blob if the intended
+    // TODO(peter): Include |p256dh| in the serialized JSON blob if the intended
     // serialization behavior gets defined in the spec.
 
     return result.scriptValue();
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h
index e05a26c1..3a2fac9 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h
+++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.h
@@ -42,7 +42,7 @@
     PushSubscription(const WebPushSubscription&, ServiceWorkerRegistration*);
 
     KURL m_endpoint;
-    RefPtr<DOMArrayBuffer> m_curve25519dh;
+    RefPtr<DOMArrayBuffer> m_p256dh;
 
     Member<ServiceWorkerRegistration> m_serviceWorkerRegistration;
 };
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl
index a1ed1a2..775d63b 100644
--- a/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl
+++ b/third_party/WebKit/Source/modules/push_messaging/PushSubscription.idl
@@ -5,7 +5,7 @@
 // https://w3c.github.io/push-api/#pushsubscription-interface
 
 enum PushEncryptionKeyName {
-    "curve25519dh"
+    "p256dh"
 };
 
 [
diff --git a/third_party/WebKit/Source/modules/quota/StorageManager.cpp b/third_party/WebKit/Source/modules/quota/StorageManager.cpp
index ab2734a..051927d 100644
--- a/third_party/WebKit/Source/modules/quota/StorageManager.cpp
+++ b/third_party/WebKit/Source/modules/quota/StorageManager.cpp
@@ -79,14 +79,14 @@
     ExecutionContext* executionContext = scriptState->executionContext();
     SecurityOrigin* securityOrigin = executionContext->securityOrigin();
     // TODO(dgrogan): Is the isUnique() check covered by the later
-    // isPrivilegedContext() check? If so, maybe remove it. Write a test if it
+    // isSecureContext() check? If so, maybe remove it. Write a test if it
     // stays.
     if (securityOrigin->isUnique()) {
         resolver->reject(DOMException::create(NotSupportedError));
         return promise;
     }
     String errorMessage;
-    if (!executionContext->isPrivilegedContext(errorMessage)) {
+    if (!executionContext->isSecureContext(errorMessage)) {
         resolver->reject(DOMException::create(SecurityError, errorMessage));
         return promise;
     }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
index 764ecded..905e9287 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
@@ -208,7 +208,7 @@
     RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin();
     String errorMessage;
     // Restrict to secure origins: https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-privileged
-    if (!executionContext->isPrivilegedContext(errorMessage)) {
+    if (!executionContext->isSecureContext(errorMessage)) {
         resolver->reject(DOMException::create(NotSupportedError, errorMessage));
         return promise;
     }
@@ -276,7 +276,7 @@
 
     RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin();
     String errorMessage;
-    if (!executionContext->isPrivilegedContext(errorMessage)) {
+    if (!executionContext->isSecureContext(errorMessage)) {
         resolver->reject(DOMException::create(NotSupportedError, errorMessage));
         return promise;
     }
@@ -312,7 +312,7 @@
     ExecutionContext* executionContext = scriptState->executionContext();
     RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin();
     String errorMessage;
-    if (!executionContext->isPrivilegedContext(errorMessage)) {
+    if (!executionContext->isSecureContext(errorMessage)) {
         resolver->reject(DOMException::create(NotSupportedError, errorMessage));
         return promise;
     }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
index c2e8e9b..11215d43 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.cpp
@@ -59,6 +59,7 @@
     , m_playbackRate(playbackRate)
     , m_detune(detune)
     , m_isLooping(false)
+    , m_didSetLooping(false)
     , m_loopStart(0)
     , m_loopEnd(0)
     , m_virtualReadIndex(0)
@@ -579,7 +580,11 @@
     // been called but is never connected to the destination (directly or indirectly).  By stopping
     // the node, the node can be collected.  Otherwise, the node will never get collected, leaking
     // memory.
-    if (!loop() && buffer() && isPlayingOrScheduled() && m_minPlaybackRate > 0) {
+    //
+    // If looping was ever done (m_didSetLooping = true), give up.  We can't easily determine how
+    // long we looped so we don't know the actual duration thus far, so don't try to do anything
+    // fancy.
+    if (!m_didSetLooping && buffer() && isPlayingOrScheduled() && m_minPlaybackRate > 0) {
         // Adjust the duration to include the playback rate. Only need to account for rate < 1
         // which makes the sound last longer.  For rate >= 1, the source stops sooner, but that's
         // ok.
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h
index bcfc07fd..d1c085e 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioBufferSourceNode.h
@@ -67,7 +67,11 @@
     // and with how it's described in the specification, the proper attribute name is .loop
     // The old attribute is kept for backwards compatibility.
     bool loop() const { return m_isLooping; }
-    void setLoop(bool looping) { m_isLooping = looping; }
+    void setLoop(bool looping)
+    {
+        m_isLooping = looping;
+        m_didSetLooping = m_didSetLooping || looping;
+    }
 
     // Loop times in seconds.
     double loopStart() const { return m_loopStart; }
@@ -116,6 +120,9 @@
     // If true, it will wrap around to the start of the buffer each time it reaches the end.
     bool m_isLooping;
 
+    // True if the source .loop attribute was ever set.
+    bool m_didSetLooping;
+
     double m_loopStart;
     double m_loopEnd;
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
index acf5741..8fdaddf8 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
@@ -86,7 +86,7 @@
 String AudioParamTimeline::eventToString(const ParamEvent& event)
 {
     // The default arguments for most automation methods is the value and the time.
-    String args = String::number(event.value()) + ", " + String::number(event.time());
+    String args = String::number(event.value()) + ", " + String::number(event.time(), 16);
 
     // Get a nice printable name for the event and update the args if necessary.
     String s;
@@ -103,12 +103,12 @@
     case ParamEvent::SetTarget:
         s = "setTargetAtTime";
         // This has an extra time constant arg
-        args = args + ", " + String::number(event.timeConstant());
+        args = args + ", " + String::number(event.timeConstant(), 16);
         break;
     case ParamEvent::SetValueCurve:
         s = "setValueCurveAtTime";
         // Replace the default arg, using "..." to denote the curve argument.
-        args = "..., " + String::number(event.time()) + ", " + String::number(event.duration());
+        args = "..., " + String::number(event.time(), 16) + ", " + String::number(event.duration(), 16);
         break;
     case ParamEvent::LastType:
         ASSERT_NOT_REACHED();
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
index 6cb2dda..ec206d0 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.cpp
@@ -164,6 +164,7 @@
     ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     ScriptPromise promise = resolver->promise();
     m_device->open(new CallbackPromiseAdapter<void, USBError>(resolver));
+    setContext(scriptState->executionContext());
     return promise;
 }
 
@@ -172,6 +173,7 @@
     ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     ScriptPromise promise = resolver->promise();
     m_device->close(new CallbackPromiseAdapter<void, USBError>(resolver));
+    setContext(nullptr);
     return promise;
 }
 
@@ -289,4 +291,14 @@
     return promise;
 }
 
+void USBDevice::contextDestroyed()
+{
+    m_device->close(new WebUSBDeviceCloseCallbacks());
+}
+
+DEFINE_TRACE(USBDevice)
+{
+    ContextLifecycleObserver::trace(visitor);
+}
+
 } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webusb/USBDevice.h b/third_party/WebKit/Source/modules/webusb/USBDevice.h
index 5bdbcbe..b3fa5065 100644
--- a/third_party/WebKit/Source/modules/webusb/USBDevice.h
+++ b/third_party/WebKit/Source/modules/webusb/USBDevice.h
@@ -8,6 +8,7 @@
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/modules/v8/UnionTypesModules.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/modules/webusb/WebUSBDevice.h"
 #include "public/platform/modules/webusb/WebUSBDeviceInfo.h"
@@ -21,7 +22,9 @@
 
 class USBDevice
     : public GarbageCollectedFinalized<USBDevice>
+    , public ContextLifecycleObserver
     , public ScriptWrappable {
+    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(USBDevice);
     DEFINE_WRAPPERTYPEINFO();
 public:
     using WebType = OwnPtr<WebUSBDevice>;
@@ -37,7 +40,8 @@
     }
 
     explicit USBDevice(PassOwnPtr<WebUSBDevice> device)
-        : m_device(device)
+        : ContextLifecycleObserver(nullptr)
+        , m_device(device)
     {
     }
 
@@ -77,7 +81,9 @@
     ScriptPromise transferOut(ScriptState*, uint8_t endpointNumber, const ArrayBufferOrArrayBufferView& data);
     ScriptPromise reset(ScriptState*);
 
-    DEFINE_INLINE_TRACE() { }
+    void contextDestroyed() override;
+
+    DECLARE_TRACE();
 
 private:
     OwnPtr<WebUSBDevice> m_device;
diff --git a/third_party/WebKit/Source/platform/PlatformGestureEvent.h b/third_party/WebKit/Source/platform/PlatformGestureEvent.h
index 53453a1..52fd1f3f 100644
--- a/third_party/WebKit/Source/platform/PlatformGestureEvent.h
+++ b/third_party/WebKit/Source/platform/PlatformGestureEvent.h
@@ -135,8 +135,11 @@
 
     bool preventPropagation() const
     {
+        // TODO(tdresser) Once we've decided if we're getting rid of scroll
+        // chaining, we should remove all scroll chaining related logic. See
+        // crbug.com/526462 for details.
         ASSERT(m_type == PlatformEvent::GestureScrollUpdate);
-        return m_data.m_scroll.m_preventPropagation;
+        return true;
     }
 
     float scale() const
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
index 967c303..aa3def6 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -136,7 +136,7 @@
 PushMessagingData status=test
 QuotaPromise status=experimental
 ReducedReferrerGranularity
-RequestIdleCallback status=experimental
+RequestIdleCallback status=stable
 RequestAutocomplete status=test
 RestrictIFramePermissions
 SandboxBlocksModals status=stable
@@ -157,7 +157,8 @@
 SlimmingPaintV2
 SlimmingPaintOffsetCaching implied_by=SlimmingPaintV2
 SlimmingPaintStrictCullRectClipping
-SlimmingPaintSubsequenceCaching implied_by=SlimmingPaintV2, status=stable
+SlimmingPaintSubsequenceCaching implied_by=SlimmingPaintV2
+SlimmingPaintSynchronizedPainting implied_by=SlimmingPaintV2
 SlimmingPaintUnderInvalidationChecking
 StackedCSSPropertyAnimations status=experimental
 StyleSharing status=stable
diff --git a/third_party/WebKit/Source/platform/Timer.cpp b/third_party/WebKit/Source/platform/Timer.cpp
index c2913c3..ad619a3c 100644
--- a/third_party/WebKit/Source/platform/Timer.cpp
+++ b/third_party/WebKit/Source/platform/Timer.cpp
@@ -110,12 +110,8 @@
             // TODO(skyostil): Move timer alignment into the scheduler.
             m_webScheduler->postTimerTaskAt(m_location, m_cancellableTimerTask, m_nextFireTime);
         } else {
-            // Round the delay up to the nearest millisecond to be consistant with the
-            // previous behavior of BlinkPlatformImpl::setSharedTimerFireInterval.
-            long long delayMs = static_cast<long long>(ceil((newTime - now) * 1000.0));
-            if (delayMs < 0)
-                delayMs = 0;
-            timerTaskRunner()->postDelayedTask(m_location, m_cancellableTimerTask, delayMs);
+            double delayMs = 1000.0 * (newTime - now);
+            m_webScheduler->timerTaskRunner()->postDelayedTask(m_location, m_cancellableTimerTask, delayMs);
         }
     }
 }
@@ -131,10 +127,15 @@
     TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkInternal");
 
     m_nextFireTime = 0;
-    // Note: repeating timers drift, but this is preserving the functionality of the old timer heap.
-    // See crbug.com/328700.
-    if (m_repeatInterval)
-        setNextFireTime(monotonicallyIncreasingTime(), m_repeatInterval);
+    if (m_repeatInterval) {
+        double now = monotonicallyIncreasingTime();
+        // This computation should be drift free, and it will cope if we miss a beat,
+        // which can easily happen if the thread is busy.  It will also cope if we get
+        // called slightly before m_unalignedNextFireTime, which can happen due to lack
+        // of timer precision.
+        double intervalToNextFireTime = m_repeatInterval - fmod(now - m_unalignedNextFireTime, m_repeatInterval);
+        setNextFireTime(monotonicallyIncreasingTime(), intervalToNextFireTime);
+    }
     fired();
     TRACE_EVENT_SET_SAMPLING_STATE("blink", "Sleeping");
 }
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp
index 1deae7a..9a0900c8 100644
--- a/third_party/WebKit/Source/platform/TimerTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -41,14 +41,14 @@
 
 class DelayedTask {
 public:
-    DelayedTask(WebTaskRunner::Task* task, long long delayMs)
+    DelayedTask(WebTaskRunner::Task* task, double delaySeconds)
         : m_task(adoptRef(new RefCountedTaskContainer(task)))
-        , m_runTimeSecs(monotonicallyIncreasingTime() + 0.001 * static_cast<double>(delayMs))
-        , m_delayMs(delayMs) { }
+        , m_runTimeSeconds(monotonicallyIncreasingTime() + delaySeconds)
+        , m_delaySeconds(delaySeconds) { }
 
     bool operator<(const DelayedTask& other) const
     {
-        return m_runTimeSecs > other.m_runTimeSecs;
+        return m_runTimeSeconds > other.m_runTimeSeconds;
     }
 
     void run() const
@@ -56,20 +56,20 @@
         m_task->run();
     }
 
-    double runTimeSecs() const
+    double runTimeSeconds() const
     {
-        return m_runTimeSecs;
+        return m_runTimeSeconds;
     }
 
-    long long delayMs() const
+    double delaySeconds() const
     {
-        return m_delayMs;
+        return m_delaySeconds;
     }
 
 private:
     RefPtr<RefCountedTaskContainer> m_task;
-    double m_runTimeSecs;
-    long long m_delayMs;
+    double m_runTimeSeconds;
+    double m_delaySeconds;
 };
 
 class MockWebTaskRunner : public WebTaskRunner {
@@ -82,9 +82,9 @@
         m_timerTasks->push(DelayedTask(task, 0));
     }
 
-    void postDelayedTask(const WebTraceLocation&, Task* task, long long delayMs) override
+    void postDelayedTask(const WebTraceLocation&, Task* task, double delayMs) override
     {
-        m_timerTasks->push(DelayedTask(task, delayMs));
+        m_timerTasks->push(DelayedTask(task, delayMs * 0.001));
     }
 
     std::priority_queue<DelayedTask>* m_timerTasks; // NOT OWNED
@@ -136,7 +136,7 @@
     void runUntilIdle()
     {
         while (!m_timerTasks.empty()) {
-            gCurrentTimeSecs = m_timerTasks.top().runTimeSecs();
+            gCurrentTimeSecs = m_timerTasks.top().runTimeSeconds();
             m_timerTasks.top().run();
             m_timerTasks.pop();
         }
@@ -145,11 +145,19 @@
     void runUntilIdleOrDeadlinePassed(double deadline)
     {
         while (!m_timerTasks.empty()) {
-            if (m_timerTasks.top().runTimeSecs() > deadline) {
+            if (m_timerTasks.top().runTimeSeconds() > deadline) {
                 gCurrentTimeSecs = deadline;
                 break;
             }
-            gCurrentTimeSecs = m_timerTasks.top().runTimeSecs();
+            gCurrentTimeSecs = m_timerTasks.top().runTimeSeconds();
+            m_timerTasks.top().run();
+            m_timerTasks.pop();
+        }
+    }
+
+    void runPendingTasks()
+    {
+        while (!m_timerTasks.empty() && m_timerTasks.top().runTimeSeconds() <= gCurrentTimeSecs) {
             m_timerTasks.top().run();
             m_timerTasks.pop();
         }
@@ -160,10 +168,10 @@
         return m_timerTasks.size() == 1;
     }
 
-    long nextTimerTaskDelayMillis() const
+    double nextTimerTaskDelaySecs() const
     {
         ASSERT(hasOneTimerTask());
-        return m_timerTasks.top().delayMs();
+        return m_timerTasks.top().delaySeconds();
     }
 
 private:
@@ -240,6 +248,11 @@
         mockScheduler()->runUntilIdle();
     }
 
+    void runPendingTasks()
+    {
+        mockScheduler()->runPendingTasks();
+    }
+
     void runUntilIdleOrDeadlinePassed(double deadline)
     {
         mockScheduler()->runUntilIdleOrDeadlinePassed(deadline);
@@ -250,9 +263,9 @@
         return mockScheduler()->hasOneTimerTask();
     }
 
-    long nextTimerTaskDelayMillis() const
+    double nextTimerTaskDelaySecs() const
     {
-        return mockScheduler()->nextTimerTaskDelayMillis();
+        return mockScheduler()->nextTimerTaskDelaySecs();
     }
 
 private:
@@ -288,6 +301,11 @@
         m_runTimes.push_back(monotonicallyIncreasingTime());
     }
 
+    void recordNextFireTimeTask(Timer<TimerTest>* timer)
+    {
+        m_nextFireTimes.push_back(monotonicallyIncreasingTime() + timer->nextFireInterval());
+    }
+
     void advanceTimeBy(double timeSecs)
     {
         gCurrentTimeSecs += timeSecs;
@@ -298,6 +316,11 @@
         m_platform->runUntilIdle();
     }
 
+    void runPendingTasks()
+    {
+        m_platform->runPendingTasks();
+    }
+
     void runUntilIdleOrDeadlinePassed(double deadline)
     {
         m_platform->runUntilIdleOrDeadlinePassed(deadline);
@@ -308,14 +331,16 @@
         return m_platform->hasOneTimerTask();
     }
 
-    long nextTimerTaskDelayMillis() const
+    double nextTimerTaskDelaySecs() const
     {
-        return m_platform->nextTimerTaskDelayMillis();
+        return m_platform->nextTimerTaskDelaySecs();
     }
 
 protected:
     double m_startTime;
+    // TODO(alexclarke): Migrate to WTF::Vector and add gmock matcher support.
     std::vector<double> m_runTimes;
+    std::vector<double> m_nextFireTimes;
 
 private:
     OwnPtr<TimerTestPlatform> m_platform;
@@ -328,7 +353,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime));
@@ -340,7 +365,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     timer.stop();
 
@@ -354,7 +379,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     timer.stop();
 
@@ -364,7 +389,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime));
@@ -376,7 +401,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime));
@@ -384,7 +409,7 @@
     timer.startOneShot(0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(0ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(0.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime, m_startTime));
@@ -396,7 +421,7 @@
     timer.startOneShot(10.0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 10.0));
@@ -408,7 +433,7 @@
     timer.startOneShot(10, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     timer.stop();
 
@@ -422,7 +447,7 @@
     timer.startOneShot(10, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     timer.stop();
 
@@ -433,7 +458,7 @@
     timer.startOneShot(10, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(secondPostTime + 10.0));
@@ -445,7 +470,7 @@
     timer.startOneShot(10, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 10.0));
@@ -453,7 +478,7 @@
     timer.startOneShot(20, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(20000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(20.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 10.0, m_startTime + 30.0));
@@ -466,7 +491,7 @@
     timer.startOneShot(10, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(10000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(10.0, nextTimerTaskDelaySecs());
 
     runUntilIdle();
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 10.0));
@@ -498,7 +523,7 @@
     timer.startRepeating(1.0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(1000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(1.0, nextTimerTaskDelaySecs());
 
     runUntilIdleOrDeadlinePassed(m_startTime + 5.5);
     EXPECT_THAT(m_runTimes, ElementsAre(
@@ -511,7 +536,7 @@
     timer.startRepeating(1.0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(1000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(1.0, nextTimerTaskDelaySecs());
 
     runUntilIdleOrDeadlinePassed(m_startTime + 2.5);
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 1.0, m_startTime + 2.0));
@@ -528,7 +553,7 @@
     timer.startRepeating(1.0, FROM_HERE);
 
     ASSERT(hasOneTimerTask());
-    EXPECT_EQ(1000ll, nextTimerTaskDelayMillis());
+    EXPECT_FLOAT_EQ(1.0, nextTimerTaskDelaySecs());
 
     runUntilIdleOrDeadlinePassed(m_startTime + 2.5);
     EXPECT_THAT(m_runTimes, ElementsAre(m_startTime + 1.0, m_startTime + 2.0));
@@ -752,6 +777,47 @@
     EXPECT_FLOAT_EQ(m_startTime, timer.lastFireTime());
 }
 
+TEST_F(TimerTest, RepeatingTimerDoesNotDrift)
+{
+    Timer<TimerTest> timer(this, &TimerTest::recordNextFireTimeTask);
+    timer.startRepeating(2.0, FROM_HERE);
+
+    ASSERT(hasOneTimerTask());
+    recordNextFireTimeTask(&timer); // Next scheduled task to run at m_startTime + 2.0
+
+    // Simulate timer firing early. Next scheduled task to run at m_startTime + 4.0
+    advanceTimeBy(1.9);
+    runUntilIdleOrDeadlinePassed(gCurrentTimeSecs + 0.2);
+
+    advanceTimeBy(2.0);
+    runPendingTasks(); // Next scheduled task to run at m_startTime + 6.0
+
+    advanceTimeBy(2.1);
+    runPendingTasks(); // Next scheduled task to run at m_startTime + 8.0
+
+    advanceTimeBy(2.9);
+    runPendingTasks(); // Next scheduled task to run at m_startTime + 10.0
+
+    advanceTimeBy(3.1);
+    runPendingTasks(); // Next scheduled task to run at m_startTime + 14.0 (skips a beat)
+
+    advanceTimeBy(4.0);
+    runPendingTasks(); // Next scheduled task to run at m_startTime + 18.0 (skips a beat)
+
+    advanceTimeBy(10.0); // Next scheduled task to run at m_startTime + 28.0 (skips 5 beats)
+    runPendingTasks();
+
+    runUntilIdleOrDeadlinePassed(m_startTime + 5.5);
+    EXPECT_THAT(m_nextFireTimes, ElementsAre(
+        m_startTime + 2.0,
+        m_startTime + 4.0,
+        m_startTime + 6.0,
+        m_startTime + 8.0,
+        m_startTime + 10.0,
+        m_startTime + 14.0,
+        m_startTime + 18.0,
+        m_startTime + 28.0));
+}
 
 } // namespace
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/blink_platform_tests.gyp b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
index 8eb4eac..849b2f3 100644
--- a/third_party/WebKit/Source/platform/blink_platform_tests.gyp
+++ b/third_party/WebKit/Source/platform/blink_platform_tests.gyp
@@ -164,10 +164,6 @@
                 '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/natives_blob.bin',
                 '<(PRODUCT_DIR)/blink_heap_unittests_apk/assets/snapshot_blob.bin',
               ],
-              'inputs': [
-                '<(PRODUCT_DIR)/natives_blob.bin',
-                '<(PRODUCT_DIR)/snapshot_blob.bin',
-              ],
             }],
           ],
         },
diff --git a/third_party/WebKit/Source/platform/fonts/Font.h b/third_party/WebKit/Source/platform/fonts/Font.h
index 8885e6470..3054f03 100644
--- a/third_party/WebKit/Source/platform/fonts/Font.h
+++ b/third_party/WebKit/Source/platform/fonts/Font.h
@@ -86,7 +86,11 @@
     FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1, bool accountForGlyphBounds = false) const;
 
     // Metrics that we query the FontFallbackList for.
-    const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); }
+    const FontMetrics& fontMetrics() const
+    {
+        RELEASE_ASSERT(primaryFont());
+        return primaryFont()->fontMetrics();
+    }
     float spaceWidth() const { return primaryFont()->spaceWidth() + fontDescription().letterSpacing(); }
     float tabWidth(const SimpleFontData&, const TabSize&, float position) const;
     float tabWidth(const TabSize& tabSize, float position) const { return tabWidth(*primaryFont(), tabSize, position); }
diff --git a/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp b/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
index 1c5592c..1bcb7abe3 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDataCache.cpp
@@ -60,7 +60,7 @@
 
     Cache::iterator result = m_cache.find(*platformData);
     if (result == m_cache.end()) {
-        pair<RefPtr<SimpleFontData>, unsigned> newValue(SimpleFontData::create(*platformData), shouldRetain == Retain ? 1 : 0);
+        std::pair<RefPtr<SimpleFontData>, unsigned> newValue(SimpleFontData::create(*platformData), shouldRetain == Retain ? 1 : 0);
         m_cache.set(*platformData, newValue);
         if (shouldRetain == DoNotRetain)
             m_inactiveFontData.add(newValue.first);
diff --git a/third_party/WebKit/Source/platform/fonts/FontDataCache.h b/third_party/WebKit/Source/platform/fonts/FontDataCache.h
index 11707a5..f76351c 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDataCache.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDataCache.h
@@ -88,7 +88,7 @@
 private:
     bool purgeLeastRecentlyUsed(int count);
 
-    typedef HashMap<FontPlatformData, pair<RefPtr<SimpleFontData>, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> Cache;
+    typedef HashMap<FontPlatformData, std::pair<RefPtr<SimpleFontData>, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> Cache;
     Cache m_cache;
     ListHashSet<RefPtr<SimpleFontData>> m_inactiveFontData;
 };
diff --git a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
index 85ae04a..7919c8b 100644
--- a/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContentLayerDelegate.cpp
@@ -84,7 +84,7 @@
     // TODO(pdr): Remove when slimming paint v2 is further along. This is only
     // here so the browser is usable during development and does not crash due
     // to committing the new display items twice.
-    if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+    if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
         m_painter->displayItemList()->appendToWebDisplayItemList(webDisplayItemList);
         return;
     }
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index 5e255919..f7081603 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -99,6 +99,7 @@
     , m_isRootForIsolatedGroup(false)
     , m_hasScrollParent(false)
     , m_hasClipParent(false)
+    , m_needsDisplay(true)
     , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
     , m_parent(0)
     , m_maskLayer(0)
@@ -962,32 +963,68 @@
     }
 }
 
+void GraphicsLayer::setNeedsDisplayWithoutInvalidateForTesting()
+{
+    ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled());
+    if (!drawsContent())
+        return;
+
+    if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
+        m_needsDisplay = true;
+}
+
 void GraphicsLayer::setNeedsDisplay()
 {
-    if (drawsContent()) {
-        m_layer->layer()->invalidate();
-        if (isTrackingPaintInvalidations())
-            trackPaintInvalidationRect(FloatRect(FloatPoint(), m_size));
-        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
-            m_linkHighlights[i]->invalidate();
+    if (!drawsContent())
+        return;
 
-        displayItemList()->invalidateAll();
-        if (isTrackingPaintInvalidations())
-            trackPaintInvalidationObject("##ALL##");
+    // TODO(chrishtr): stop invalidating the rects once FrameView::paintRecursively does so.
+    if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
+        m_needsDisplay = true;
+
+    m_layer->layer()->invalidate();
+    if (isTrackingPaintInvalidations())
+        trackPaintInvalidationRect(FloatRect(FloatPoint(), m_size));
+    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
+        m_linkHighlights[i]->invalidate();
+
+    displayItemList()->invalidateAll();
+    if (isTrackingPaintInvalidations())
+        trackPaintInvalidationObject("##ALL##");
+}
+
+bool GraphicsLayer::needsDisplay() const
+{
+    ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled());
+    return m_needsDisplay;
+}
+
+bool GraphicsLayer::commitIfNeeded(DisplayListDiff& displayListDiff)
+{
+    ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled());
+    if (m_needsDisplay) {
+        displayItemList()->commitNewDisplayItems(&displayListDiff);
+        m_needsDisplay = false;
+        return true;
     }
+    return false;
 }
 
 void GraphicsLayer::setNeedsDisplayInRect(const IntRect& rect, PaintInvalidationReason invalidationReason)
 {
-    if (drawsContent()) {
-        m_layer->layer()->invalidateRect(rect);
-        if (firstPaintInvalidationTrackingEnabled())
-            m_debugInfo.appendAnnotatedInvalidateRect(rect, invalidationReason);
-        if (isTrackingPaintInvalidations())
-            trackPaintInvalidationRect(rect);
-        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
-            m_linkHighlights[i]->invalidate();
-    }
+    if (!drawsContent())
+        return;
+
+    if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled())
+        m_needsDisplay = true;
+
+    m_layer->layer()->invalidateRect(rect);
+    if (firstPaintInvalidationTrackingEnabled())
+        m_debugInfo.appendAnnotatedInvalidateRect(rect, invalidationReason);
+    if (isTrackingPaintInvalidations())
+        trackPaintInvalidationRect(rect);
+    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
+        m_linkHighlights[i]->invalidate();
 }
 
 void GraphicsLayer::invalidateDisplayItemClient(const DisplayItemClientWrapper& displayItemClient)
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index 88cbd41..51f5ea7 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -39,6 +39,7 @@
 #include "platform/graphics/PaintInvalidationReason.h"
 #include "platform/graphics/filters/FilterOperations.h"
 #include "platform/graphics/paint/DisplayItemClient.h"
+#include "platform/graphics/paint/DisplayItemList.h"
 #include "platform/transforms/TransformationMatrix.h"
 #include "public/platform/WebCompositorAnimationDelegate.h"
 #include "public/platform/WebContentLayer.h"
@@ -189,6 +190,10 @@
 
     void setContentsNeedsDisplay();
 
+    bool needsDisplay() const;
+    // Commites new display items only if m_needsDisplay is true.
+    bool commitIfNeeded(DisplayListDiff&);
+
     void invalidateDisplayItemClient(const DisplayItemClientWrapper&);
 
     // Set that the position/size of the contents (image or video).
@@ -274,6 +279,11 @@
     // Callback from the underlying graphics system to draw layer contents.
     void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip);
 
+    // Sets m_needsDisplay, but without invalidating the DisplayItemList. This allows us to test
+    // scenarios where paint needs to be re-calculated, but no DisplayItemClients were invalidated
+    // (such as re-paints due to change of interest rect).
+    void setNeedsDisplayWithoutInvalidateForTesting();
+
     // Adds a child without calling updateChildList(), so that adding children
     // can be batched before updating.
     void addChildInternal(GraphicsLayer*);
@@ -327,6 +337,8 @@
     bool m_hasScrollParent : 1;
     bool m_hasClipParent : 1;
 
+    bool m_needsDisplay : 1;
+
     GraphicsLayerPaintingPhase m_paintingPhase;
 
     Vector<GraphicsLayer*> m_children;
@@ -335,8 +347,9 @@
     GraphicsLayer* m_maskLayer; // Reference to mask layer. We don't own this.
     GraphicsLayer* m_contentsClippingMaskLayer; // Reference to clipping mask layer. We don't own this.
 
-    GraphicsLayer* m_replicaLayer; // A layer that replicates this layer. We only allow one, for now.
-                                   // The replica is not parented; this is the primary reference to it.
+    // A layer that replicates this layer. We only allow one, for now.
+    // The replica is not parented; this is the primary reference to it.
+    GraphicsLayer* m_replicaLayer; 
     GraphicsLayer* m_replicatedLayer; // For a replica layer, a reference to the original layer.
     FloatPoint m_replicatedLayerPosition; // For a replica layer, the position of the replica.
 
@@ -362,6 +375,8 @@
     int m_3dRenderingContext;
 
     OwnPtr<DisplayItemList> m_displayItemList;
+
+    friend class DisplayItemListPaintTestForSlimmingPaintV2;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
index d211082..8cf1c048 100644
--- a/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/RecordingImageBufferSurfaceTest.cpp
@@ -266,7 +266,7 @@
             m_task = task;
         }
 
-        void postDelayedTask(const WebTraceLocation&, Task*, long long delayMs) override { ASSERT_NOT_REACHED(); };
+        void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) override { ASSERT_NOT_REACHED(); };
 
         Task* m_task;
     };
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp b/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
index ba5df1f..8a3ce41 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -44,8 +44,6 @@
     , m_preserveAlpha(preserveAlpha)
     , m_kernelMatrix(kernelMatrix)
 {
-    ASSERT(m_kernelSize.width() > 0);
-    ASSERT(m_kernelSize.height() > 0);
 }
 
 PassRefPtrWillBeRawPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntSize& kernelSize,
@@ -59,53 +57,21 @@
 FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward)
 {
     FloatRect result = rect;
-
-    result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize);
-    result.expand(m_kernelSize);
+    if (parametersValid()) {
+        result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize);
+        result.expand(m_kernelSize);
+    }
     return result;
 }
 
-IntSize FEConvolveMatrix::kernelSize() const
-{
-    return m_kernelSize;
-}
-
-void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize)
-{
-    ASSERT(kernelSize.width() > 0);
-    ASSERT(kernelSize.height() > 0);
-    m_kernelSize = kernelSize;
-}
-
-const Vector<float>& FEConvolveMatrix::kernel() const
-{
-    return m_kernelMatrix;
-}
-
-void FEConvolveMatrix::setKernel(const Vector<float>& kernel)
-{
-    m_kernelMatrix = kernel;
-}
-
-float FEConvolveMatrix::divisor() const
-{
-    return m_divisor;
-}
-
 bool FEConvolveMatrix::setDivisor(float divisor)
 {
-    ASSERT(divisor);
     if (m_divisor == divisor)
         return false;
     m_divisor = divisor;
     return true;
 }
 
-float FEConvolveMatrix::bias() const
-{
-    return m_bias;
-}
-
 bool FEConvolveMatrix::setBias(float bias)
 {
     if (m_bias == bias)
@@ -114,11 +80,6 @@
     return true;
 }
 
-IntPoint FEConvolveMatrix::targetOffset() const
-{
-    return m_targetOffset;
-}
-
 bool FEConvolveMatrix::setTargetOffset(const IntPoint& targetOffset)
 {
     if (m_targetOffset == targetOffset)
@@ -127,11 +88,6 @@
     return true;
 }
 
-EdgeModeType FEConvolveMatrix::edgeMode() const
-{
-    return m_edgeMode;
-}
-
 bool FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode)
 {
     if (m_edgeMode == edgeMode)
@@ -140,11 +96,6 @@
     return true;
 }
 
-bool FEConvolveMatrix::preserveAlpha() const
-{
-    return m_preserveAlpha;
-}
-
 bool FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha)
 {
     if (m_preserveAlpha == preserveAlpha)
@@ -167,12 +118,33 @@
     }
 }
 
+bool FEConvolveMatrix::parametersValid() const
+{
+    if (m_kernelSize.isEmpty())
+        return false;
+    uint64_t kernelArea = m_kernelSize.area();
+    if (!WTF::isInBounds<int>(kernelArea))
+        return false;
+    if (safeCast<size_t>(kernelArea) != m_kernelMatrix.size())
+        return false;
+    if (m_targetOffset.x() < 0 || m_targetOffset.x() >= m_kernelSize.width())
+        return false;
+    if (m_targetOffset.y() < 0 || m_targetOffset.y() >= m_kernelSize.height())
+        return false;
+    if (!m_divisor)
+        return false;
+    return true;
+}
+
 PassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
 {
-    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
+    if (!parametersValid())
+        return createTransparentBlack(builder);
 
+    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
     SkISize kernelSize(SkISize::Make(m_kernelSize.width(), m_kernelSize.height()));
-    int numElements = kernelSize.width() * kernelSize.height();
+    // parametersValid() above checks that the kernel area fits in int.
+    int numElements = safeCast<int>(m_kernelSize.area());
     SkScalar gain = SkFloatToScalar(1.0f / m_divisor);
     SkScalar bias = SkFloatToScalar(m_bias * 255);
     SkIPoint target = SkIPoint::Make(m_targetOffset.x(), m_targetOffset.y());
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h b/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
index 07be8dab..a80099a 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
+++ b/third_party/WebKit/Source/platform/graphics/filters/FEConvolveMatrix.h
@@ -44,25 +44,10 @@
     static PassRefPtrWillBeRawPtr<FEConvolveMatrix> create(Filter*, const IntSize&,
         float, float, const IntPoint&, EdgeModeType, bool, const Vector<float>&);
 
-    IntSize kernelSize() const;
-    void setKernelSize(const IntSize&);
-
-    const Vector<float>& kernel() const;
-    void setKernel(const Vector<float>&);
-
-    float divisor() const;
     bool setDivisor(float);
-
-    float bias() const;
     bool setBias(float);
-
-    IntPoint targetOffset() const;
     bool setTargetOffset(const IntPoint&);
-
-    EdgeModeType edgeMode() const;
     bool setEdgeMode(EdgeModeType);
-
-    bool preserveAlpha() const;
     bool setPreserveAlpha(bool);
 
     PassRefPtr<SkImageFilter> createImageFilter(SkiaImageFilterBuilder*) override;
@@ -75,6 +60,8 @@
     FEConvolveMatrix(Filter*, const IntSize&, float, float,
         const IntPoint&, EdgeModeType, bool, const Vector<float>&);
 
+    bool parametersValid() const;
+
     IntSize m_kernelSize;
     float m_divisor;
     float m_bias;
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp b/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
index 16977f23..9f5cda4 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
+++ b/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.cpp
@@ -22,10 +22,13 @@
  */
 
 #include "config.h"
-
 #include "platform/graphics/filters/FilterEffect.h"
 
 #include "platform/graphics/filters/Filter.h"
+#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
+#include "third_party/skia/include/core/SkColorFilter.h"
+#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
+#include "third_party/skia/include/effects/SkPictureImageFilter.h"
 
 namespace blink {
 
@@ -190,6 +193,13 @@
     return createImageFilter(builder);
 }
 
+PassRefPtr<SkImageFilter> FilterEffect::createTransparentBlack(SkiaImageFilterBuilder* builder) const
+{
+    SkAutoTUnref<SkColorFilter> filter(SkColorFilter::CreateModeFilter(0, SkXfermode::kClear_Mode));
+    SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
+    return adoptRef(SkColorFilterImageFilter::Create(filter, nullptr, &rect));
+}
+
 bool FilterEffect::hasConnectedInput() const
 {
     for (unsigned i = 0; i < m_inputEffects.size(); i++) {
diff --git a/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h b/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
index 00b3aaf..d1056bc 100644
--- a/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
+++ b/third_party/WebKit/Source/platform/graphics/filters/FilterEffect.h
@@ -149,6 +149,8 @@
 protected:
     FilterEffect(Filter*);
 
+    PassRefPtr<SkImageFilter> createTransparentBlack(SkiaImageFilterBuilder*) const;
+
     Color adaptColorToOperatingColorSpace(const Color& deviceColor);
 
     SkImageFilter::CropRect getCropRect(const FloatSize& cropOffset) const;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
index 59fd0fe..8db534a 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -154,6 +154,15 @@
     }
 }
 
+static String subsequenceTypeAsDebugString(DisplayItem::Type type)
+{
+    switch (type) {
+        DEBUG_STRING_CASE(SubsequenceNegativeZOrder);
+        DEBUG_STRING_CASE(SubsequenceNormalFlowAndPositiveZOrder);
+        DEFAULT_CASE;
+    }
+}
+
 WTF::String DisplayItem::typeAsDebugString(Type type)
 {
     if (isDrawingType(type))
@@ -181,6 +190,13 @@
     if (isEndTransform3DType(type))
         return "End" + transform3DTypeAsDebugString(endTransform3DTypeToTransform3DType(type));
 
+    if (isSubsequenceType(type))
+        return subsequenceTypeAsDebugString(type);
+    if (isEndSubsequenceType(type))
+        return "End" + subsequenceTypeAsDebugString(endSubsequenceTypeToSubsequenceType(type));
+    if (isCachedSubsequenceType(type))
+        return "Cached" + subsequenceTypeAsDebugString(cachedSubsequenceTypeToSubsequenceType(type));
+
     switch (type) {
         DEBUG_STRING_CASE(BeginFilter);
         DEBUG_STRING_CASE(EndFilter);
@@ -194,9 +210,6 @@
         DEBUG_STRING_CASE(EndFixedPosition);
         DEBUG_STRING_CASE(BeginFixedPositionContainer);
         DEBUG_STRING_CASE(EndFixedPositionContainer);
-        DEBUG_STRING_CASE(BeginSubsequence);
-        DEBUG_STRING_CASE(EndSubsequence);
-        DEBUG_STRING_CASE(CachedSubsequence);
         DEBUG_STRING_CASE(UninitializedType);
         DEFAULT_CASE;
     }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
index 1615455..2ede618 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -165,9 +165,14 @@
         BeginFixedPositionContainer,
         EndFixedPositionContainer,
 
-        BeginSubsequence,
-        EndSubsequence,
-        CachedSubsequence,
+        SubsequenceFirst,
+        SubsequenceNegativeZOrder = SubsequenceFirst,
+        SubsequenceNormalFlowAndPositiveZOrder,
+        SubsequenceLast = SubsequenceNormalFlowAndPositiveZOrder,
+        EndSubsequenceFirst,
+        EndSubsequenceLast = EndSubsequenceFirst + SubsequenceLast - SubsequenceFirst,
+        CachedSubsequenceFirst,
+        CachedSubsequenceLast = CachedSubsequenceFirst + SubsequenceLast - SubsequenceFirst,
 
         UninitializedType,
         TypeLast = UninitializedType
@@ -228,8 +233,8 @@
     {
         if (isCachedDrawingType(type))
             return cachedDrawingTypeToDrawingType(type);
-        if (type == CachedSubsequence)
-            return BeginSubsequence;
+        if (isCachedSubsequenceType(type))
+            return cachedSubsequenceTypeToSubsequenceType(type);
         return type;
     }
 
@@ -307,11 +312,15 @@
     DEFINE_PAIRED_CATEGORY_METHODS(Scroll, scroll)
     DEFINE_PAINT_PHASE_CONVERSION_METHOD(Scroll)
 
-    DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D);
+    DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D)
 
-    static bool isCachedType(Type type) { return isCachedDrawingType(type) || type == CachedSubsequence; }
+    DEFINE_PAIRED_CATEGORY_METHODS(Subsequence, subsequence)
+    DEFINE_CATEGORY_METHODS(CachedSubsequence)
+    DEFINE_CONVERSION_METHODS(Subsequence, subsequence, CachedSubsequence, cachedSubsequence)
+
+    static bool isCachedType(Type type) { return isCachedDrawingType(type) || isCachedSubsequenceType(type); }
     bool isCached() const { return isCachedType(m_type); }
-    static bool isCacheableType(Type type) { return isDrawingType(type) || type == BeginSubsequence; }
+    static bool isCacheableType(Type type) { return isDrawingType(type) || isSubsequenceType(type); }
     bool isCacheable() const { return !skippedCache() && isCacheableType(m_type); }
 
     virtual bool isBegin() const { return false; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
index 7b329e4..344b432 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -61,7 +61,7 @@
     // Verify noop begin/end pairs have been removed.
     if (m_newDisplayItems.size() >= 2 && displayItem.isEnd()) {
         const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size() - 2];
-        if (beginDisplayItem.isBegin() && beginDisplayItem.type() != DisplayItem::BeginSubsequence && !beginDisplayItem.drawsContent())
+        if (beginDisplayItem.isBegin() && !beginDisplayItem.isSubsequence() && !beginDisplayItem.drawsContent())
             ASSERT(!displayItem.isEndAndPairedWith(beginDisplayItem.type()));
     }
 #endif
@@ -228,9 +228,9 @@
 
 void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems& updatedList)
 {
-    ASSERT(currentIt->type() == DisplayItem::BeginSubsequence);
+    ASSERT(currentIt->isSubsequence());
     ASSERT(!currentIt->scope());
-    DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubsequence, 0);
+    DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::subsequenceTypeToEndSubsequenceType(currentIt->type()), 0);
     do {
         // We should always find the EndSubsequence display item.
         ASSERT(currentIt != m_currentDisplayItems.end());
@@ -242,14 +242,14 @@
 
 // Update the existing display items by removing invalidated entries, updating
 // repainted ones, and appending new items.
-// - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
-// - For SubsequenceCachedDisplayItem, copy the cached display items between the
-//   corresponding BeginSubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
+// - For cached drawing display item, copy the corresponding cached DrawingDisplayItem;
+// - For cached subsequence display item, copy the cached display items between the
+//   corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
 // - Otherwise, copy the new display item.
 //
 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|).
-// Coefficients are related to the ratio of out-of-order [Subsequence]CachedDisplayItems
-// and the average number of (Drawing|BeginSubsequence)DisplayItems per client.
+// Coefficients are related to the ratio of out-of-order CachedDisplayItems
+// and the average number of (Drawing|Subsequence)DisplayItems per client.
 //
 // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2.
 void DisplayItemList::commitNewDisplayItems(DisplayListDiff*)
@@ -325,9 +325,9 @@
                 updatedList.appendByMoving(*currentIt);
                 ++currentIt;
             } else {
-                ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence);
+                ASSERT(newDisplayItem.isCachedSubsequence());
                 copyCachedSubsequence(currentIt, updatedList);
-                ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence);
+                ASSERT(updatedList.last().isEndSubsequence());
             }
         } else {
             ASSERT(!newDisplayItem.isDrawing()
@@ -433,7 +433,7 @@
         return;
     }
 
-    ASSERT(newIt->type() == DisplayItem::BeginSubsequence);
+    ASSERT(newIt->isSubsequence());
 
 #ifndef NDEBUG
     CString messagePrefix = String::format("(In CachedSubsequence of %s)", newIt->clientDebugString().utf8().data()).utf8();
@@ -441,7 +441,7 @@
     CString messagePrefix = "(In CachedSubsequence)";
 #endif
 
-    DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::EndSubsequence, 0);
+    DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::subsequenceTypeToEndSubsequenceType(newIt->type()), 0);
     while (true) {
         ASSERT(newIt != m_newDisplayItems.end());
         if (newIt->isCached())
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp
index 76a00fa..e9f98e1 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemListTest.cpp
@@ -39,6 +39,9 @@
 const DisplayItem::Type foregroundDrawingType = static_cast<DisplayItem::Type>(DisplayItem::DrawingPaintPhaseFirst + 4);
 const DisplayItem::Type backgroundDrawingType = DisplayItem::DrawingPaintPhaseFirst;
 const DisplayItem::Type clipType = DisplayItem::ClipFirst;
+const DisplayItem::Type subsequenceType = DisplayItem::SubsequenceNormalFlowAndPositiveZOrder;
+const DisplayItem::Type endSubsequenceType = DisplayItem::subsequenceTypeToEndSubsequenceType(subsequenceType);
+const DisplayItem::Type cachedSubsequenceType = DisplayItem::subsequenceTypeToCachedSubsequenceType(subsequenceType);
 
 class TestDisplayItemClient {
 public:
@@ -457,14 +460,14 @@
     GraphicsContext context(&displayItemList());
 
     {
-        SubsequenceRecorder r(context, container1);
+        SubsequenceRecorder r(context, container1, subsequenceType);
         drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100, 100));
         drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 200));
         drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 200));
         drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     }
     {
-        SubsequenceRecorder r(context, container2);
+        SubsequenceRecorder r(context, container2, subsequenceType);
         drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100, 100));
         drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 200));
         drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 200));
@@ -473,44 +476,44 @@
     displayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 12,
-        TestDisplayItem(container1, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container1, subsequenceType),
         TestDisplayItem(container1, backgroundDrawingType),
         TestDisplayItem(content1, backgroundDrawingType),
         TestDisplayItem(content1, foregroundDrawingType),
         TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence),
+        TestDisplayItem(container1, endSubsequenceType),
 
-        TestDisplayItem(container2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container2, subsequenceType),
         TestDisplayItem(container2, backgroundDrawingType),
         TestDisplayItem(content2, backgroundDrawingType),
         TestDisplayItem(content2, foregroundDrawingType),
         TestDisplayItem(container2, foregroundDrawingType),
-        TestDisplayItem(container2, DisplayItem::EndSubsequence));
+        TestDisplayItem(container2, endSubsequenceType));
 
     // Simulate the situation when container1 e.g. gets a z-index that is now greater than container2.
-    EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2));
-    EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1));
+    EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2, subsequenceType));
+    EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1, subsequenceType));
 
     EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 2,
-        TestDisplayItem(container2, DisplayItem::CachedSubsequence),
-        TestDisplayItem(container1, DisplayItem::CachedSubsequence));
+        TestDisplayItem(container2, cachedSubsequenceType),
+        TestDisplayItem(container1, cachedSubsequenceType));
 
     displayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 12,
-        TestDisplayItem(container2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container2, subsequenceType),
         TestDisplayItem(container2, backgroundDrawingType),
         TestDisplayItem(content2, backgroundDrawingType),
         TestDisplayItem(content2, foregroundDrawingType),
         TestDisplayItem(container2, foregroundDrawingType),
-        TestDisplayItem(container2, DisplayItem::EndSubsequence),
+        TestDisplayItem(container2, endSubsequenceType),
 
-        TestDisplayItem(container1, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container1, subsequenceType),
         TestDisplayItem(container1, backgroundDrawingType),
         TestDisplayItem(content1, backgroundDrawingType),
         TestDisplayItem(content1, foregroundDrawingType),
         TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence));
+        TestDisplayItem(container1, endSubsequenceType));
 }
 
 TEST_F(DisplayItemListTest, OutOfOrderNoCrash)
@@ -549,41 +552,41 @@
     GraphicsContext context(&displayItemList());
 
     {
-        SubsequenceRecorder r(context, container1);
+        SubsequenceRecorder r(context, container1, subsequenceType);
         drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100, 100));
         {
-            SubsequenceRecorder r(context, content1);
+            SubsequenceRecorder r(context, content1, subsequenceType);
             drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 200));
             drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 200));
         }
         drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     }
     {
-        SubsequenceRecorder r(context, container2);
+        SubsequenceRecorder r(context, container2, subsequenceType);
         drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100, 100));
         {
-            SubsequenceRecorder r(context, content2);
+            SubsequenceRecorder r(context, content2, subsequenceType);
             drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 200));
         }
     }
     displayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 14,
-        TestDisplayItem(container1, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container1, subsequenceType),
         TestDisplayItem(container1, backgroundDrawingType),
-        TestDisplayItem(content1, DisplayItem::BeginSubsequence),
+        TestDisplayItem(content1, subsequenceType),
         TestDisplayItem(content1, backgroundDrawingType),
         TestDisplayItem(content1, foregroundDrawingType),
-        TestDisplayItem(content1, DisplayItem::EndSubsequence),
+        TestDisplayItem(content1, endSubsequenceType),
         TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence),
+        TestDisplayItem(container1, endSubsequenceType),
 
-        TestDisplayItem(container2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container2, subsequenceType),
         TestDisplayItem(container2, backgroundDrawingType),
-        TestDisplayItem(content2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(content2, subsequenceType),
         TestDisplayItem(content2, backgroundDrawingType),
-        TestDisplayItem(content2, DisplayItem::EndSubsequence),
-        TestDisplayItem(container2, DisplayItem::EndSubsequence));
+        TestDisplayItem(content2, endSubsequenceType),
+        TestDisplayItem(container2, endSubsequenceType));
 
     // Invalidate container1 but not content1.
     displayItemList().invalidate(container1);
@@ -592,44 +595,44 @@
     // and chooses not to output subsequence info.
     displayItemList().invalidate(container2);
     displayItemList().invalidate(content2);
-    EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2));
-    EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content2));
+    EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2, subsequenceType));
+    EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content2, subsequenceType));
     // Content2 now outputs foreground only.
     {
-        SubsequenceRecorder r(context, content2);
+        SubsequenceRecorder r(context, content2, subsequenceType);
         drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 200));
     }
     // Repaint container1 with foreground only.
     {
-        EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1));
-        SubsequenceRecorder r(context, container1);
+        EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1, subsequenceType));
+        SubsequenceRecorder r(context, container1, subsequenceType);
         // Use cached subsequence of content1.
-        EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content1));
+        EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content1, subsequenceType));
         drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100));
     }
     EXPECT_DISPLAY_LIST(displayItemList().newDisplayItems(), 7,
-        TestDisplayItem(content2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(content2, subsequenceType),
         TestDisplayItem(content2, foregroundDrawingType),
-        TestDisplayItem(content2, DisplayItem::EndSubsequence),
-        TestDisplayItem(container1, DisplayItem::BeginSubsequence),
-        TestDisplayItem(content1, DisplayItem::CachedSubsequence),
+        TestDisplayItem(content2, endSubsequenceType),
+        TestDisplayItem(container1, subsequenceType),
+        TestDisplayItem(content1, cachedSubsequenceType),
         TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence));
+        TestDisplayItem(container1, endSubsequenceType));
 
     displayItemList().commitNewDisplayItems();
 
     EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 10,
-        TestDisplayItem(content2, DisplayItem::BeginSubsequence),
+        TestDisplayItem(content2, subsequenceType),
         TestDisplayItem(content2, foregroundDrawingType),
-        TestDisplayItem(content2, DisplayItem::EndSubsequence),
+        TestDisplayItem(content2, endSubsequenceType),
 
-        TestDisplayItem(container1, DisplayItem::BeginSubsequence),
-        TestDisplayItem(content1, DisplayItem::BeginSubsequence),
+        TestDisplayItem(container1, subsequenceType),
+        TestDisplayItem(content1, subsequenceType),
         TestDisplayItem(content1, backgroundDrawingType),
         TestDisplayItem(content1, foregroundDrawingType),
-        TestDisplayItem(content1, DisplayItem::EndSubsequence),
+        TestDisplayItem(content1, endSubsequenceType),
         TestDisplayItem(container1, foregroundDrawingType),
-        TestDisplayItem(container1, DisplayItem::EndSubsequence));
+        TestDisplayItem(container1, endSubsequenceType));
 }
 
 TEST_F(DisplayItemListTest, Scope)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceDisplayItem.h
index fda7a832..dc7f451 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceDisplayItem.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceDisplayItem.h
@@ -13,19 +13,26 @@
 
 class BeginSubsequenceDisplayItem final : public PairedBeginDisplayItem {
 public:
-    BeginSubsequenceDisplayItem(const DisplayItemClientWrapper& client)
-        : PairedBeginDisplayItem(client, BeginSubsequence, sizeof(*this))
-    { }
+    BeginSubsequenceDisplayItem(const DisplayItemClientWrapper& client, DisplayItem::Type type)
+        : PairedBeginDisplayItem(client, type, sizeof(*this))
+    {
+        ASSERT(DisplayItem::isSubsequenceType(type));
+    }
 };
 
 class EndSubsequenceDisplayItem final : public PairedEndDisplayItem {
 public:
-    EndSubsequenceDisplayItem(const DisplayItemClientWrapper& client)
-        : PairedEndDisplayItem(client, EndSubsequence, sizeof(*this))
-    { }
+    EndSubsequenceDisplayItem(const DisplayItemClientWrapper& client, DisplayItem::Type type)
+        : PairedEndDisplayItem(client, type, sizeof(*this))
+    {
+        ASSERT(DisplayItem::isEndSubsequenceType(type));
+    }
 
 #if ENABLE(ASSERT)
-    bool isEndAndPairedWith(DisplayItem::Type otherType) const final { return otherType == BeginSubsequence; }
+    bool isEndAndPairedWith(DisplayItem::Type otherType) const final
+    {
+        return otherType == DisplayItem::endSubsequenceTypeToSubsequenceType(type());
+    }
 #endif
 };
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
index 146a035..74976819 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
@@ -13,7 +13,7 @@
 
 namespace blink {
 
-bool SubsequenceRecorder::useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClientWrapper& client)
+bool SubsequenceRecorder::useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClientWrapper& client, DisplayItem::Type type)
 {
     if (!RuntimeEnabledFeatures::slimmingPaintSubsequenceCachingEnabled())
         return false;
@@ -26,7 +26,7 @@
     if (!context.displayItemList()->clientCacheIsValid(client.displayItemClient()))
         return false;
 
-    context.displayItemList()->createAndAppend<CachedDisplayItem>(client, DisplayItem::CachedSubsequence);
+    context.displayItemList()->createAndAppend<CachedDisplayItem>(client, DisplayItem::subsequenceTypeToCachedSubsequenceType(type));
 
 #if ENABLE(ASSERT)
     // When under-invalidation checking is enabled, we output CachedSubsequence display item
@@ -38,10 +38,11 @@
     return true;
 }
 
-SubsequenceRecorder::SubsequenceRecorder(GraphicsContext& context, const DisplayItemClientWrapper& client)
+SubsequenceRecorder::SubsequenceRecorder(GraphicsContext& context, const DisplayItemClientWrapper& client, DisplayItem::Type type)
     : m_displayItemList(context.displayItemList())
     , m_client(client)
     , m_beginSubsequenceIndex(0)
+    , m_type(type)
 {
     if (!RuntimeEnabledFeatures::slimmingPaintSubsequenceCachingEnabled())
         return;
@@ -51,7 +52,7 @@
         return;
 
     m_beginSubsequenceIndex = m_displayItemList->newDisplayItems().size();
-    m_displayItemList->createAndAppend<BeginSubsequenceDisplayItem>(m_client);
+    m_displayItemList->createAndAppend<BeginSubsequenceDisplayItem>(m_client, type);
 }
 
 SubsequenceRecorder::~SubsequenceRecorder()
@@ -72,7 +73,7 @@
         }
     }
 
-    m_displayItemList->createAndAppend<EndSubsequenceDisplayItem>(m_client);
+    m_displayItemList->createAndAppend<EndSubsequenceDisplayItem>(m_client, DisplayItem::subsequenceTypeToEndSubsequenceType(m_type));
 }
 
 void SubsequenceRecorder::setUncacheable()
@@ -83,7 +84,7 @@
     if (m_displayItemList->displayItemConstructionIsDisabled())
         return;
 
-    ASSERT(m_displayItemList->newDisplayItems()[m_beginSubsequenceIndex].type() == DisplayItem::BeginSubsequence);
+    ASSERT(m_displayItemList->newDisplayItems()[m_beginSubsequenceIndex].isSubsequence());
     m_displayItemList->newDisplayItems()[m_beginSubsequenceIndex].setSkippedCache();
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
index 2cc1330..03c70e3 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
@@ -5,7 +5,7 @@
 #ifndef SubsequenceRecorder_h
 #define SubsequenceRecorder_h
 
-#include "platform/graphics/paint/DisplayItemClient.h"
+#include "platform/graphics/paint/DisplayItem.h"
 
 namespace blink {
 
@@ -22,9 +22,9 @@
 //
 class PLATFORM_EXPORT SubsequenceRecorder {
 public:
-    static bool useCachedSubsequenceIfPossible(GraphicsContext&, const DisplayItemClientWrapper&);
+    static bool useCachedSubsequenceIfPossible(GraphicsContext&, const DisplayItemClientWrapper&, DisplayItem::Type);
 
-    SubsequenceRecorder(GraphicsContext&, const DisplayItemClientWrapper&);
+    SubsequenceRecorder(GraphicsContext&, const DisplayItemClientWrapper&, DisplayItem::Type);
     ~SubsequenceRecorder();
 
     void setUncacheable();
@@ -33,6 +33,7 @@
     DisplayItemList* m_displayItemList;
     DisplayItemClientWrapper m_client;
     size_t m_beginSubsequenceIndex;
+    DisplayItem::Type m_type;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/network/HTTPHeaderMap.cpp b/third_party/WebKit/Source/platform/network/HTTPHeaderMap.cpp
index fa60bec..75ebe1d 100644
--- a/third_party/WebKit/Source/platform/network/HTTPHeaderMap.cpp
+++ b/third_party/WebKit/Source/platform/network/HTTPHeaderMap.cpp
@@ -58,7 +58,7 @@
     clear();
     size_t dataSize = data->size();
     for (size_t index = 0; index < dataSize; ++index) {
-        pair<String, String>& header = (*data)[index];
+        std::pair<String, String>& header = (*data)[index];
         set(AtomicString(header.first), AtomicString(header.second));
     }
 }
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
index 156fffb1..9ac24844 100644
--- a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
+++ b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
@@ -779,7 +779,7 @@
     return str.substring(0, str.find(isCacheHeaderSeparator));
 }
 
-static void parseCacheHeader(const String& header, Vector<pair<String, String>>& result)
+static void parseCacheHeader(const String& header, Vector<std::pair<String, String>>& result)
 {
     const String safeHeader = header.removeCharacters(isControlCharacter);
     unsigned max = safeHeader.length();
@@ -797,7 +797,7 @@
                 size_t nextDoubleQuotePosition = value.find('"', 1);
                 if (nextDoubleQuotePosition != kNotFound) {
                     // Store the value as a quoted string without quotes
-                    result.append(pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
+                    result.append(std::pair<String, String>(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
                     pos += (safeHeader.find('"', pos) - pos) + nextDoubleQuotePosition + 1;
                     // Move past next comma, if there is one
                     size_t nextCommaPosition2 = safeHeader.find(',', pos);
@@ -807,7 +807,7 @@
                         return; // Parse error if there is anything left with no comma
                 } else {
                     // Parse error; just use the rest as the value
-                    result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
+                    result.append(std::pair<String, String>(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
                     return;
                 }
             } else {
@@ -815,21 +815,21 @@
                 size_t nextCommaPosition2 = value.find(',');
                 if (nextCommaPosition2 != kNotFound) {
                     // The value is delimited by the next comma
-                    result.append(pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
+                    result.append(std::pair<String, String>(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
                     pos += (safeHeader.find(',', pos) - pos) + 1;
                 } else {
                     // The rest is the value; no change to value needed
-                    result.append(pair<String, String>(directive, trimToNextSeparator(value)));
+                    result.append(std::pair<String, String>(directive, trimToNextSeparator(value)));
                     return;
                 }
             }
         } else if (nextCommaPosition != kNotFound && (nextCommaPosition < nextEqualSignPosition || nextEqualSignPosition == kNotFound)) {
             // Add directive to map with empty string as value
-            result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
+            result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), ""));
             pos += nextCommaPosition - pos + 1;
         } else {
             // Add last directive to map with empty string as value
-            result.append(pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
+            result.append(std::pair<String, String>(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), ""));
             return;
         }
     }
@@ -849,7 +849,7 @@
     DEFINE_STATIC_LOCAL(const AtomicString, staleWhileRevalidateDirective, ("stale-while-revalidate", AtomicString::ConstructFromLiteral));
 
     if (!cacheControlValue.isEmpty()) {
-        Vector<pair<String, String>> directives;
+        Vector<std::pair<String, String>> directives;
         parseCacheHeader(cacheControlValue, directives);
 
         size_t directivesSize = directives.size();
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeNonMacCommon.cpp b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeNonMacCommon.cpp
index 0e53c35..cf7fa79 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeNonMacCommon.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeNonMacCommon.cpp
@@ -72,16 +72,15 @@
 
 IntRect ScrollbarThemeNonMacCommon::trackRect(ScrollbarThemeClient* scrollbar, bool)
 {
+    // The track occupies all space between the two buttons.
     IntSize bs = buttonSize(scrollbar);
     int thickness = scrollbarThickness(scrollbar->controlSize());
     if (scrollbar->orientation() == HorizontalScrollbar) {
-        // Once the scrollbar becomes smaller than the size of the
-        // two buttons with a 1 pixel gap, the track disappears.
-        if (scrollbar->width() <= 2 * bs.width() + 1)
+        if (scrollbar->width() <= 2 * bs.width())
             return IntRect();
         return IntRect(scrollbar->x() + bs.width(), scrollbar->y(), scrollbar->width() - 2 * bs.width(), thickness);
     }
-    if (scrollbar->height() <= 2 * bs.height() + 1)
+    if (scrollbar->height() <= 2 * bs.height())
         return IntRect();
     return IntRect(scrollbar->x(), scrollbar->y() + bs.height(), thickness, scrollbar->height() - 2 * bs.height());
 }
diff --git a/third_party/WebKit/Source/platform/text/TextBreakIteratorICU.cpp b/third_party/WebKit/Source/platform/text/TextBreakIteratorICU.cpp
index 06e6907..94aa2ae 100644
--- a/third_party/WebKit/Source/platform/text/TextBreakIteratorICU.cpp
+++ b/third_party/WebKit/Source/platform/text/TextBreakIteratorICU.cpp
@@ -99,7 +99,7 @@
 
     static const size_t capacity = 4;
 
-    typedef pair<AtomicString, icu::BreakIterator*> Entry;
+    typedef std::pair<AtomicString, icu::BreakIterator*> Entry;
     typedef Vector<Entry, capacity> Pool;
     Pool m_pool;
     HashMap<icu::BreakIterator*, AtomicString> m_vendedIterators;
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index 65f492c..259083b 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -159,6 +159,7 @@
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventChildrenChanged, AXObjectCache::AXChildrenChanged);
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventFocus, AXObjectCache::AXFocusedUIElementChanged);
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventHide, AXObjectCache::AXHide);
+STATIC_ASSERT_MATCHING_ENUM(WebAXEventHover, AXObjectCache::AXHover);
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventInvalidStatusChanged, AXObjectCache::AXInvalidStatusChanged);
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventLayoutComplete, AXObjectCache::AXLayoutComplete);
 STATIC_ASSERT_MATCHING_ENUM(WebAXEventLiveRegionChanged, AXObjectCache::AXLiveRegionChanged);
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
index 7230e961..affe69a 100644
--- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
+++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp
@@ -561,6 +561,14 @@
     return static_cast<NavigationPolicy>(webPolicy);
 }
 
+bool FrameLoaderClientImpl::hasPendingNavigation()
+{
+    if (!m_webFrame->client())
+        return false;
+
+    return m_webFrame->client()->hasPendingNavigation(m_webFrame);
+}
+
 void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form)
 {
     if (m_webFrame->client())
diff --git a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
index 26c496e..c468e0e 100644
--- a/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
+++ b/third_party/WebKit/Source/web/FrameLoaderClientImpl.h
@@ -101,6 +101,7 @@
 
     void dispatchDidChangeThemeColor() override;
     NavigationPolicy decidePolicyForNavigation(const ResourceRequest&, DocumentLoader*, NavigationPolicy) override;
+    bool hasPendingNavigation() override;
     void dispatchWillSendSubmitEvent(HTMLFormElement*) override;
     void dispatchWillSubmitForm(HTMLFormElement*) override;
     void didStartLoading(LoadStartType) override;
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.cpp b/third_party/WebKit/Source/web/InspectorOverlay.cpp
index 357987e..a44c0153c 100644
--- a/third_party/WebKit/Source/web/InspectorOverlay.cpp
+++ b/third_party/WebKit/Source/web/InspectorOverlay.cpp
@@ -337,6 +337,18 @@
     }
 }
 
+void InspectorOverlay::setInspectedNode(Node* node)
+{
+    if (m_inspectMode != InspectorDOMAgent::ShowLayoutEditor || (m_layoutEditor && m_layoutEditor->element() == node))
+        return;
+
+    if (m_layoutEditor) {
+        m_layoutEditor->commitChanges();
+        m_layoutEditor.clear();
+    }
+    initializeLayoutEditorIfNeeded(node);
+}
+
 void InspectorOverlay::highlightQuad(PassOwnPtr<FloatQuad> quad, const InspectorHighlightConfig& highlightConfig)
 {
     m_quadHighlightConfig = highlightConfig;
@@ -725,10 +737,16 @@
     if (m_domAgent)
         m_domAgent->inspect(node);
 
+    initializeLayoutEditorIfNeeded(node);
+    if (m_layoutEditor)
+        hideHighlight();
+}
+
+void InspectorOverlay::initializeLayoutEditorIfNeeded(Node* node)
+{
     if (node && node->isElementNode() && m_inspectMode == InspectorDOMAgent::ShowLayoutEditor && !m_layoutEditor) {
         m_layoutEditor = LayoutEditor::create(toElement(node), m_cssAgent, m_domAgent, &overlayMainFrame()->script());
         toChromeClientImpl(m_webViewImpl->page()->chromeClient()).setCursorOverridden(true);
-        hideHighlight();
     }
 }
 
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.h b/third_party/WebKit/Source/web/InspectorOverlay.h
index 64e5b90..389be4b 100644
--- a/third_party/WebKit/Source/web/InspectorOverlay.h
+++ b/third_party/WebKit/Source/web/InspectorOverlay.h
@@ -114,6 +114,7 @@
     void highlightNode(Node*, const InspectorHighlightConfig&, bool omitTooltip) override;
     void highlightQuad(PassOwnPtr<FloatQuad>, const InspectorHighlightConfig&) override;
     void setInspectMode(InspectorDOMAgent::SearchMode, PassOwnPtr<InspectorHighlightConfig>) override;
+    void setInspectedNode(Node*) override;
 
     void highlightNode(Node*, Node* eventTarget, const InspectorHighlightConfig&, bool omitTooltip);
     bool isEmpty();
@@ -138,6 +139,7 @@
     bool handleMouseMove(const PlatformMouseEvent&);
     bool shouldSearchForNode();
     void inspect(Node*);
+    void initializeLayoutEditorIfNeeded(Node*);
 
     WebViewImpl* m_webViewImpl;
     String m_pausedInDebuggerMessage;
diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp
index 060d446c..38a96b17 100644
--- a/third_party/WebKit/Source/web/TextFinder.cpp
+++ b/third_party/WebKit/Source/web/TextFinder.cpp
@@ -278,8 +278,8 @@
     }
 
     WebLocalFrameImpl* mainFrameImpl = ownerFrame().viewImpl()->mainFrameImpl();
-    PositionAlgorithm<Strategy> searchStart = PositionAlgorithm<Strategy>::firstPositionInNode(ownerFrame().frame()->document());
-    PositionAlgorithm<Strategy> searchEnd = PositionAlgorithm<Strategy>::lastPositionInNode(ownerFrame().frame()->document());
+    PositionTemplate<Strategy> searchStart = PositionTemplate<Strategy>::firstPositionInNode(ownerFrame().frame()->document());
+    PositionTemplate<Strategy> searchEnd = PositionTemplate<Strategy>::lastPositionInNode(ownerFrame().frame()->document());
     ASSERT(searchStart.document() == searchEnd.document());
 
     if (m_resumeScopingFromRange) {
diff --git a/third_party/WebKit/Source/web/WebAXObject.cpp b/third_party/WebKit/Source/web/WebAXObject.cpp
index bdc91c3..b9dc9120 100644
--- a/third_party/WebKit/Source/web/WebAXObject.cpp
+++ b/third_party/WebKit/Source/web/WebAXObject.cpp
@@ -1442,7 +1442,7 @@
     if (!m_private->isTableCell())
         return 0;
 
-    pair<unsigned, unsigned> columnRange;
+    std::pair<unsigned, unsigned> columnRange;
     toAXTableCell(m_private.get())->columnIndexRange(columnRange);
     return columnRange.first;
 }
@@ -1455,7 +1455,7 @@
     if (!m_private->isTableCell())
         return 0;
 
-    pair<unsigned, unsigned> columnRange;
+    std::pair<unsigned, unsigned> columnRange;
     toAXTableCell(m_private.get())->columnIndexRange(columnRange);
     return columnRange.second;
 }
@@ -1468,7 +1468,7 @@
     if (!m_private->isTableCell())
         return 0;
 
-    pair<unsigned, unsigned> rowRange;
+    std::pair<unsigned, unsigned> rowRange;
     toAXTableCell(m_private.get())->rowIndexRange(rowRange);
     return rowRange.first;
 }
@@ -1481,7 +1481,7 @@
     if (!m_private->isTableCell())
         return 0;
 
-    pair<unsigned, unsigned> rowRange;
+    std::pair<unsigned, unsigned> rowRange;
     toAXTableCell(m_private.get())->rowIndexRange(rowRange);
     return rowRange.second;
 }
diff --git a/third_party/WebKit/Source/web/WebDOMCustomEvent.cpp b/third_party/WebKit/Source/web/WebDOMCustomEvent.cpp
index 45963330..4de4858 100644
--- a/third_party/WebKit/Source/web/WebDOMCustomEvent.cpp
+++ b/third_party/WebKit/Source/web/WebDOMCustomEvent.cpp
@@ -34,16 +34,13 @@
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "core/events/CustomEvent.h"
 #include "public/platform/WebString.h"
-#include "public/web/WebSerializedScriptValue.h"
 
 namespace blink {
 
-void WebDOMCustomEvent::initCustomEvent(const WebString& type, bool canBubble, bool cancelable, const WebSerializedScriptValue& webSerializedScriptValue)
+WebDOMCustomEvent::WebDOMCustomEvent(const WebString& type)
+    : WebDOMEvent(CustomEvent::create())
 {
-    ASSERT(m_private.get());
-    RefPtr<SerializedScriptValue> serializedScriptValue;
-    serializedScriptValue = webSerializedScriptValue;
-    unwrap<CustomEvent>()->initCustomEvent(type, canBubble, cancelable, serializedScriptValue.get());
+    unwrap<CustomEvent>()->initCustomEvent(type, false, false, nullptr);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp b/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp
index 7c35d4e..e45cafe 100644
--- a/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp
+++ b/third_party/WebKit/Source/web/WebDOMMessageEvent.cpp
@@ -44,23 +44,23 @@
 
 namespace blink {
 
-void WebDOMMessageEvent::initMessageEvent(const WebString& type, bool canBubble, bool cancelable, const WebSerializedScriptValue& messageData, const WebString& origin, const WebFrame* sourceFrame, const WebDocument& targetDocument, const WebString& lastEventId, const WebMessagePortChannelArray& webChannels)
+WebDOMMessageEvent::WebDOMMessageEvent(const WebSerializedScriptValue& messageData, const WebString& origin, const WebFrame* sourceFrame, const WebDocument& targetDocument, const WebMessagePortChannelArray& channels)
+    : WebDOMMessageEvent(MessageEvent::create())
 {
-    ASSERT(m_private.get());
-    ASSERT(isMessageEvent());
     DOMWindow* window = nullptr;
     if (sourceFrame)
         window = toCoreFrame(sourceFrame)->domWindow();
     MessagePortArray* ports = nullptr;
     if (!targetDocument.isNull()) {
         RefPtrWillBeRawPtr<Document> coreDocument = PassRefPtrWillBeRawPtr<Document>(targetDocument);
-        ports = MessagePort::toMessagePortArray(coreDocument.get(), webChannels);
+        ports = MessagePort::toMessagePortArray(coreDocument.get(), channels);
     }
     // Use an empty array for |ports| when it is null because this function
     // is used to implement postMessage().
     if (!ports)
         ports = new MessagePortArray;
-    unwrap<MessageEvent>()->initMessageEvent(type, canBubble, cancelable, messageData, origin, lastEventId, window, ports);
+    // TODO(esprehn): Chromium always passes empty string for lastEventId, is that right?
+    unwrap<MessageEvent>()->initMessageEvent("message", false, false, messageData, origin, ""/*lastEventId*/, window, ports);
 }
 
 WebSerializedScriptValue WebDOMMessageEvent::data() const
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
index 49662c05..39c0b386 100644
--- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
+++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
@@ -38,7 +38,6 @@
 #include "core/frame/FrameConsole.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
-#include "core/inspector/AsyncCallTracker.h"
 #include "core/inspector/IdentifiersFactory.h"
 #include "core/inspector/InjectedScriptHost.h"
 #include "core/inspector/InjectedScriptManager.h"
@@ -140,7 +139,7 @@
     {
         // Release render thread if necessary.
         if (s_instance && s_instance->m_running)
-            MainThreadDebugger::instance()->debugger()->continueProgram();
+            s_instance->quitNow();
     }
 
 private:
@@ -410,7 +409,6 @@
     visitor->trace(m_resourceContentLoader);
     visitor->trace(m_state);
     visitor->trace(m_overlay);
-    visitor->trace(m_asyncCallTracker);
     visitor->trace(m_inspectorAgent);
     visitor->trace(m_domAgent);
     visitor->trace(m_pageAgent);
@@ -464,7 +462,6 @@
     OwnPtrWillBeRawPtr<InspectorDebuggerAgent> debuggerAgentPtr(PageDebuggerAgent::create(MainThreadDebugger::instance(), m_pageAgent, injectedScriptManager));
     InspectorDebuggerAgent* debuggerAgent = debuggerAgentPtr.get();
     m_agents.append(debuggerAgentPtr.release());
-    m_asyncCallTracker = adoptPtrWillBeNoop(new AsyncCallTracker(debuggerAgent->v8DebuggerAgent(), m_instrumentingAgents.get()));
 
     m_agents.append(InspectorDOMDebuggerAgent::create(injectedScriptManager, m_domAgent, debuggerAgent->v8DebuggerAgent()));
 
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
index d90da8e..03bf4be 100644
--- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
+++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
@@ -155,7 +155,6 @@
     RefPtrWillBeMember<InspectorBackendDispatcher> m_inspectorBackendDispatcher;
     OwnPtr<InspectorFrontend> m_inspectorFrontend;
     InspectorAgentRegistry m_agents;
-    OwnPtrWillBeMember<AsyncCallTracker> m_asyncCallTracker;
     bool m_deferredAgentsInitialized;
 
     typedef Vector<RefPtr<JSONObject>> NotificationQueue;
diff --git a/third_party/WebKit/Source/web/WebDocument.cpp b/third_party/WebKit/Source/web/WebDocument.cpp
index 9ef8eba2..e10b756 100644
--- a/third_party/WebKit/Source/web/WebDocument.cpp
+++ b/third_party/WebKit/Source/web/WebDocument.cpp
@@ -82,13 +82,13 @@
     return WebSecurityOrigin(constUnwrap<Document>()->securityOrigin());
 }
 
-bool WebDocument::isPrivilegedContext(WebString& errorMessage) const
+bool WebDocument::isSecureContext(WebString& errorMessage) const
 {
     const Document* document = constUnwrap<Document>();
     if (!document)
         return false;
     String message;
-    bool result = document->isPrivilegedContext(message);
+    bool result = document->isSecureContext(message);
     errorMessage = message;
     return result;
 }
@@ -248,15 +248,6 @@
     return WebElement(fullScreenElement);
 }
 
-WebDOMEvent WebDocument::createEvent(const WebString& eventType)
-{
-    TrackExceptionState exceptionState;
-    WebDOMEvent event(unwrap<Document>()->createEvent(eventType, exceptionState));
-    if (exceptionState.hadException())
-        return WebDOMEvent();
-    return event;
-}
-
 WebReferrerPolicy WebDocument::referrerPolicy() const
 {
     return static_cast<WebReferrerPolicy>(constUnwrap<Document>()->referrerPolicy());
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index 4463798..6bb3cee 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -530,6 +530,11 @@
     return view()->textInputInfo();
 }
 
+WebTextInputType WebFrameWidgetImpl::textInputType()
+{
+    return view()->textInputType();
+}
+
 WebColor WebFrameWidgetImpl::backgroundColor() const
 {
     if (isTransparent())
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
index fb819fb..e8e8725 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -102,6 +102,7 @@
     bool confirmComposition(const WebString& text) override;
     bool compositionRange(size_t* location, size_t* length) override;
     WebTextInputInfo textInputInfo() override;
+    WebTextInputType textInputType() override;
     WebColor backgroundColor() const override;
     bool selectionBounds(WebRect& anchor, WebRect& focus) const override;
     bool selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const override;
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index d86713f4..70009483 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -32,6 +32,7 @@
 #include "web/WebPagePopupImpl.h"
 
 #include "core/dom/ContextFeatures.h"
+#include "core/events/MessageEvent.h"
 #include "core/frame/FrameHost.h"
 #include "core/frame/FrameView.h"
 #include "core/frame/LocalFrame.h"
diff --git a/third_party/WebKit/Source/web/WebPageSerializer.cpp b/third_party/WebKit/Source/web/WebPageSerializer.cpp
index a436d085b..f995480e 100644
--- a/third_party/WebKit/Source/web/WebPageSerializer.cpp
+++ b/third_party/WebKit/Source/web/WebPageSerializer.cpp
@@ -213,14 +213,13 @@
 }
 
 bool WebPageSerializer::serialize(WebLocalFrame* frame,
-                                  bool recursive,
                                   WebPageSerializerClient* client,
                                   const WebVector<WebURL>& links,
                                   const WebVector<WebString>& localPaths,
                                   const WebString& localDirectoryName)
 {
     WebPageSerializerImpl serializerImpl(
-        frame, recursive, client, links, localPaths, localDirectoryName);
+        frame, client, links, localPaths, localDirectoryName);
     return serializerImpl.serialize();
 }
 
diff --git a/third_party/WebKit/Source/web/WebPageSerializerImpl.cpp b/third_party/WebKit/Source/web/WebPageSerializerImpl.cpp
index 6d2dfa1..34bc016 100644
--- a/third_party/WebKit/Source/web/WebPageSerializerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPageSerializerImpl.cpp
@@ -425,14 +425,11 @@
 }
 
 WebPageSerializerImpl::WebPageSerializerImpl(WebFrame* frame,
-                                             bool recursiveSerialization,
                                              WebPageSerializerClient* client,
                                              const WebVector<WebURL>& links,
                                              const WebVector<WebString>& localPaths,
                                              const WebString& localDirectoryName)
     : m_client(client)
-    , m_recursiveSerialization(recursiveSerialization)
-    , m_framesCollected(false)
     , m_localDirectoryName(localDirectoryName)
     , m_htmlEntities(false)
     , m_xmlEntities(true)
@@ -453,51 +450,16 @@
     ASSERT(m_dataBuffer.isEmpty());
 }
 
-void WebPageSerializerImpl::collectTargetFrames()
-{
-    ASSERT(!m_framesCollected);
-    m_framesCollected = true;
-
-    // First, process main frame.
-    m_frames.append(m_specifiedWebLocalFrameImpl);
-    // Return now if user only needs to serialize specified frame, not including
-    // all sub-frames.
-    if (!m_recursiveSerialization)
-        return;
-    // Collect all frames inside the specified frame.
-    for (WebLocalFrameImpl* frame : m_frames) {
-        // Get current using document.
-        Document* currentDoc = frame->frame()->document();
-        // Go through sub-frames.
-        RefPtrWillBeRawPtr<HTMLAllCollection> all = currentDoc->all();
-
-        for (unsigned i = 0; Element* element = all->item(i); ++i) {
-            if (!element->isHTMLElement())
-                continue;
-            WebLocalFrameImpl* webFrame =
-                WebLocalFrameImpl::fromFrameOwnerElement(element);
-            if (webFrame)
-                m_frames.append(webFrame);
-        }
-    }
-}
-
 bool WebPageSerializerImpl::serialize()
 {
-    if (!m_framesCollected)
-        collectTargetFrames();
-
     bool didSerialization = false;
     KURL mainURL = m_specifiedWebLocalFrameImpl->frame()->document()->url();
 
-    for (unsigned i = 0; i < m_frames.size(); ++i) {
-        WebLocalFrameImpl* webFrame = m_frames[i];
-        Document* document = webFrame->frame()->document();
-        const KURL& url = document->url();
+    WebLocalFrameImpl* webFrame = m_specifiedWebLocalFrameImpl;
+    Document* document = webFrame->frame()->document();
+    const KURL& url = document->url();
 
-        if (!url.isValid() || !m_localLinks.contains(url.string()))
-            continue;
-
+    if (url.isValid() && m_localLinks.contains(url.string())) {
         didSerialization = true;
 
         const WTF::TextEncoding& textEncoding = document->encoding().isValid() ? document->encoding() : UTF8Encoding();
diff --git a/third_party/WebKit/Source/web/WebPageSerializerImpl.h b/third_party/WebKit/Source/web/WebPageSerializerImpl.h
index e1816d3..5c72406 100644
--- a/third_party/WebKit/Source/web/WebPageSerializerImpl.h
+++ b/third_party/WebKit/Source/web/WebPageSerializerImpl.h
@@ -55,24 +55,22 @@
 class Node;
 class WebLocalFrameImpl;
 
-// Get html data by serializing all frames of current page with lists
-// which contain all resource links that have local copy.
-// contain all saved auxiliary files included all sub frames and resources.
-// This function will find out all frames and serialize them to HTML data.
-// We have a data buffer to temporary saving generated html data. We will
-// sequentially call WebViewDelegate::SendSerializedHtmlData once the data
-// buffer is full. See comments of WebViewDelegate::SendSerializedHtmlData
-// for getting more information.
+// Responsible for serializing the specified frame into html
+// (replacing links with paths to local files).
 class WebPageSerializerImpl {
     STACK_ALLOCATED();
 public:
-    // Do serialization action. Return false means no available frame has been
-    // serialized, otherwise return true.
+    // Do serialization action.
+    //
+    // Returns false to indicate that no data has been serialized (i.e. because
+    // the target frame didn't have a valid url).
+    //
+    // Synchronously calls WebPageSerializerClient methods to report
+    // serialization results.  See WebPageSerializerClient comments for more
+    // details.
     bool serialize();
 
     // The parameter specifies which frame need to be serialized.
-    // The parameter recursive_serialization specifies whether we need to
-    // serialize all sub frames of the specified frame or not.
     // The parameter delegate specifies the pointer of interface
     // DomSerializerDelegate provide sink interface which can receive the
     // individual chunks of data to be saved.
@@ -82,7 +80,6 @@
     // The parameter local_directory_name is relative path of directory which
     // contain all saved auxiliary files included all sub frames and resources.
     WebPageSerializerImpl(WebFrame* frame,
-                          bool recursive,
                           WebPageSerializerClient* client,
                           const WebVector<WebURL>& links,
                           const WebVector<WebString>& localPaths,
@@ -101,17 +98,8 @@
     LinkLocalPathMap m_localLinks;
     // Data buffer for saving result of serialized DOM data.
     StringBuilder m_dataBuffer;
-    // Passing true to recursive_serialization_ indicates we will serialize not
-    // only the specified frame but also all sub-frames in the specific frame.
-    // Otherwise we only serialize the specified frame excluded all sub-frames.
-    bool m_recursiveSerialization;
-    // Flag indicates whether we have collected all frames which need to be
-    // serialized or not;
-    bool m_framesCollected;
     // Local directory name of all local resource files.
     WTF::String m_localDirectoryName;
-    // Vector for saving all frames which need to be serialized.
-    WillBeHeapVector<RawPtrWillBeMember<WebLocalFrameImpl>> m_frames;
 
     // Web entities conversion maps.
     WebEntities m_htmlEntities;
@@ -142,8 +130,6 @@
         bool haveAddedContentsBeforeEnd;
     };
 
-    // Collect all target frames which need to be serialized.
-    void collectTargetFrames();
     // Before we begin serializing open tag of a element, we give the target
     // element a chance to do some work prior to add some additional data.
     WTF::String preActionBeforeSerializeOpenTag(const Element*,
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
index f0d8b845..30de52e 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
@@ -181,6 +181,11 @@
     return m_webView->textInputInfo();
 }
 
+WebTextInputType WebViewFrameWidget::textInputType()
+{
+    return m_webView->textInputType();
+}
+
 bool WebViewFrameWidget::selectionBounds(WebRect& anchor, WebRect& focus) const
 {
     return m_webView->selectionBounds(anchor, focus);
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.h b/third_party/WebKit/Source/web/WebViewFrameWidget.h
index 9e31b78..32b7f18 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.h
+++ b/third_party/WebKit/Source/web/WebViewFrameWidget.h
@@ -75,6 +75,7 @@
     bool confirmComposition(const WebString& text) override;
     bool compositionRange(size_t* location, size_t* length) override;
     WebTextInputInfo textInputInfo() override;
+    WebTextInputType textInputType() override;
     bool selectionBounds(WebRect& anchor, WebRect& focus) const override;
     bool selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const override;
     bool isSelectionAnchorFirst() const override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index a20c4c51..eda1089 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -2086,6 +2086,29 @@
             return true;
     }
 
+    if (inputEvent.modifiers & WebInputEvent::IsTouchAccessibility
+        && WebInputEvent::isMouseEventType(inputEvent.type)) {
+        PlatformMouseEventBuilder pme(mainFrameImpl()->frameView(), static_cast<const WebMouseEvent&>(inputEvent));
+
+        // Find the right target frame. See issue 1186900.
+        HitTestResult result = hitTestResultForRootFramePos(pme.position());
+        Frame* targetFrame;
+        if (result.innerNodeOrImageMapImage())
+            targetFrame = result.innerNodeOrImageMapImage()->document().frame();
+        else
+            targetFrame = m_page->focusController().focusedOrMainFrame();
+
+        if (targetFrame->isLocalFrame()) {
+            LocalFrame* targetLocalFrame = toLocalFrame(targetFrame);
+            Document* document = targetLocalFrame->document();
+            if (document) {
+                AXObjectCache* cache = document->existingAXObjectCache();
+                if (cache)
+                    cache->onTouchAccessibilityHover(pme.position());
+            }
+        }
+    }
+
     // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
     if (m_ignoreInputEvents)
         return false;
@@ -2389,7 +2412,21 @@
 
 WebTextInputType WebViewImpl::textInputType()
 {
-    Element* element = focusedElement();
+    Frame* focusedFrame = m_page->focusController().focusedFrame();
+    if (!focusedFrame || !focusedFrame->isLocalFrame())
+        return WebTextInputTypeNone;
+
+    // It's important to preserve the equivalence of textInputInfo().type and textInputType(),
+    // so perform the same rootEditableElement() existence check here for consistency.
+    LocalFrame* focused = toLocalFrame(focusedFrame);
+    if (!focused || !focused->selection().selection().rootEditableElement())
+        return WebTextInputTypeNone;
+
+    Document* document = focused->document();
+    if (!document)
+        return WebTextInputTypeNone;
+
+    Element* element = document->focusedElement();
     if (!element)
         return WebTextInputTypeNone;
 
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 0cf600a4..28072ba 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -142,6 +142,7 @@
     bool confirmComposition(const WebString& text) override;
     bool compositionRange(size_t* location, size_t* length) override;
     WebTextInputInfo textInputInfo() override;
+    WebTextInputType textInputType() override;
     WebColor backgroundColor() const override;
     WebPagePopup* pagePopup() const override;
     bool selectionBounds(WebRect& anchor, WebRect& focus) const override;
@@ -552,7 +553,6 @@
     explicit WebViewImpl(WebViewClient*);
     ~WebViewImpl() override;
 
-    WebTextInputType textInputType();
     int textInputFlags();
 
     WebString inputModeOfFocusedElement();
diff --git a/third_party/WebKit/Source/web/tests/CustomEventTest.cpp b/third_party/WebKit/Source/web/tests/CustomEventTest.cpp
deleted file mode 100644
index 38809ea..0000000
--- a/third_party/WebKit/Source/web/tests/CustomEventTest.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#include "config.h"
-
-#include "bindings/core/v8/ExceptionStatePlaceholder.h"
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/SerializedScriptValue.h"
-#include "bindings/core/v8/V8AbstractEventListener.h"
-#include "bindings/core/v8/V8BindingForTesting.h"
-#include "bindings/core/v8/V8Event.h"
-#include "platform/testing/URLTestHelpers.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebUnitTestSupport.h"
-#include "public/web/WebDOMCustomEvent.h"
-#include "public/web/WebFrame.h"
-#include "public/web/WebView.h"
-#include "v8.h"
-#include "web/WebLocalFrameImpl.h"
-#include "web/WebViewImpl.h"
-#include "web/tests/FrameTestHelpers.h"
-#include <gtest/gtest.h>
-
-namespace blink {
-
-class TestListener final : public V8AbstractEventListener {
-public:
-    bool operator==(const EventListener&) override
-    {
-        return true;
-    }
-
-    void handleEvent(ScriptState* scriptState, Event* event) override
-    {
-        EXPECT_EQ(event->type(), "blah");
-
-        ScriptState::Scope scope(scriptState);
-        v8::Local<v8::Context> context = scriptState->context();
-        v8::Local<v8::Value> jsEvent = toV8(event, context->Global(), isolate());
-
-        EXPECT_EQ(jsEvent->ToObject(context).ToLocalChecked()->Get(context, v8AtomicString(isolate(), "detail")).ToLocalChecked(), v8::Boolean::New(isolate(), true));
-    }
-
-    static PassRefPtrWillBeRawPtr<TestListener> create(ScriptState* scriptState)
-    {
-        return adoptRefWillBeNoop(new TestListener(scriptState));
-    }
-
-private:
-    explicit TestListener(ScriptState* scriptState)
-        : V8AbstractEventListener(false, scriptState->world(), scriptState->isolate())
-    {
-    }
-
-    v8::Local<v8::Value> callListenerFunction(ScriptState*, v8::Local<v8::Value>, Event*) override
-    {
-        ASSERT_NOT_REACHED();
-        return v8::Local<v8::Value>();
-    }
-};
-
-// Tests that a CustomEvent can be initialized with a 'detail' value that is a
-// SerializedScriptValue, and that this value can be retrieved and read in an
-// event listener. Initialization of a CustomEvent with a SerializedScriptValue
-// is an internal API, so it cannot be tested with a LayoutTest.
-//
-// Triggers crash in GC. http://crbug.com/317669
-TEST(CustomEventTest, InitWithSerializedScriptValue)
-{
-    const std::string baseURL = "http://www.test.com";
-    const std::string path = "visible_iframe.html";
-
-    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(baseURL.c_str()), WebString::fromUTF8(path.c_str()));
-    FrameTestHelpers::WebViewHelper webViewHelper;
-    WebLocalFrameImpl* frame = toWebLocalFrameImpl(webViewHelper.initializeAndLoad(baseURL + path)->mainFrame());
-    WebDOMEvent event = frame->frame()->document()->createEvent("CustomEvent", IGNORE_EXCEPTION);
-    WebDOMCustomEvent customEvent = event.to<WebDOMCustomEvent>();
-
-    v8::Isolate* isolate = toIsolate(frame->frame());
-    V8TestingScope scope(isolate);
-    customEvent.initCustomEvent("blah", false, false, WebSerializedScriptValue::serialize(v8::Boolean::New(isolate, true)));
-    RefPtrWillBeRawPtr<EventListener> listener = TestListener::create(scope.scriptState());
-    frame->frame()->document()->addEventListener("blah", listener, false);
-    frame->frame()->document()->dispatchEvent(event);
-
-    Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 228996e..de33e96 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -820,10 +820,8 @@
     // Send a message with the correct origin.
     WebSecurityOrigin correctOrigin(WebSecurityOrigin::create(toKURL(m_baseURL)));
     WebDocument document = webViewHelper.webView()->mainFrame()->document();
-    WebDOMEvent event = document.createEvent("MessageEvent");
-    WebDOMMessageEvent message = event.to<WebDOMMessageEvent>();
     WebSerializedScriptValue data(WebSerializedScriptValue::fromString("foo"));
-    message.initMessageEvent("message", false, false, data, "http://origin.com", 0, document, "");
+    WebDOMMessageEvent message(data, "http://origin.com");
     webViewHelper.webView()->mainFrame()->dispatchMessageEventWithOriginCheck(correctOrigin, message);
 
     // Send another message with incorrect origin.
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index 6ffabd3..c951a5f4 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -803,8 +803,14 @@
 {
     URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8(htmlFile.c_str()));
     WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + htmlFile);
+    EXPECT_EQ(WebTextInputTypeNone, webView->textInputType());
+    EXPECT_EQ(WebTextInputTypeNone, webView->textInputInfo().type);
     webView->setInitialFocus(false);
+    EXPECT_EQ(expectedType, webView->textInputType());
     EXPECT_EQ(expectedType, webView->textInputInfo().type);
+    webView->clearFocusedElement();
+    EXPECT_EQ(WebTextInputTypeNone, webView->textInputType());
+    EXPECT_EQ(WebTextInputTypeNone, webView->textInputInfo().type);
 }
 
 TEST_F(WebViewTest, TextInputType)
diff --git a/third_party/WebKit/Source/web/web.gypi b/third_party/WebKit/Source/web/web.gypi
index 9dc7762..42ef62e 100644
--- a/third_party/WebKit/Source/web/web.gypi
+++ b/third_party/WebKit/Source/web/web.gypi
@@ -266,7 +266,6 @@
       # crbug.com/353585
       'tests/ActivityLoggerTest.cpp',
       'tests/ChromeClientImplTest.cpp',
-      'tests/CustomEventTest.cpp',
       'tests/DocumentLoaderTest.cpp',
       'tests/DocumentLoadingRenderingTest.cpp',
       'tests/FakeWebPlugin.cpp',
diff --git a/third_party/WebKit/Source/web/web_tests.gyp b/third_party/WebKit/Source/web/web_tests.gyp
index 87d19c38..b4277c8 100644
--- a/third_party/WebKit/Source/web/web_tests.gyp
+++ b/third_party/WebKit/Source/web/web_tests.gyp
@@ -164,10 +164,6 @@
                           '<(PRODUCT_DIR)/content_shell/assets/natives_blob.bin',
                           '<(PRODUCT_DIR)/content_shell/assets/snapshot_blob.bin',
                         ],
-                        'inputs': [
-                          '<(PRODUCT_DIR)/natives_blob.bin',
-                          '<(PRODUCT_DIR)/snapshot_blob.bin',
-                        ],
                       }],
                     ],
                 },
diff --git a/third_party/WebKit/Source/wtf/Alignment.h b/third_party/WebKit/Source/wtf/Alignment.h
index df48a96f..6b92b81 100644
--- a/third_party/WebKit/Source/wtf/Alignment.h
+++ b/third_party/WebKit/Source/wtf/Alignment.h
@@ -25,46 +25,46 @@
 #include <stdint.h>
 #include <utility>
 
-
 namespace WTF {
 
 #if COMPILER(GCC)
-    #define WTF_ALIGN_OF(type) __alignof__(type)
-    #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
+#define WTF_ALIGN_OF(type) __alignof__(type)
+#define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
 #elif COMPILER(MSVC)
-    #define WTF_ALIGN_OF(type) __alignof(type)
-    #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
+#define WTF_ALIGN_OF(type) __alignof(type)
+#define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
 #else
-    #error WTF_ALIGN macros need alignment control.
+#error WTF_ALIGN macros need alignment control.
 #endif
 
 #if COMPILER(GCC)
-    typedef char __attribute__((__may_alias__)) AlignedBufferChar;
+typedef char __attribute__((__may_alias__)) AlignedBufferChar;
 #else
-    typedef char AlignedBufferChar;
+typedef char AlignedBufferChar;
 #endif
 
-    template<size_t size, size_t alignment> struct AlignedBuffer;
-    template<size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
-    template<size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2);  };
-    template<size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4);  };
-    template<size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8);  };
-    template<size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
-    template<size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
-    template<size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
+template <size_t size, size_t alignment> struct AlignedBuffer;
+template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
+template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); };
+template <size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); };
+template <size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); };
+template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
+template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
+template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
 
-    template <size_t size, size_t alignment>
-    void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
-    {
-        for (size_t i = 0; i < size; ++i)
-            std::swap(a.buffer[i], b.buffer[i]);
-    }
-
-    template <uintptr_t mask>
-    inline bool isAlignedTo(const void* pointer)
-    {
-        return !(reinterpret_cast<uintptr_t>(pointer) & mask);
-    }
+template <size_t size, size_t alignment>
+void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
+{
+    for (size_t i = 0; i < size; ++i)
+        std::swap(a.buffer[i], b.buffer[i]);
 }
 
+template <uintptr_t mask>
+inline bool isAlignedTo(const void* pointer)
+{
+    return !(reinterpret_cast<uintptr_t>(pointer) & mask);
+}
+
+} // namespace WTF
+
 #endif // WTF_Alignment_h
diff --git a/third_party/WebKit/Source/wtf/ArrayBufferView.cpp b/third_party/WebKit/Source/wtf/ArrayBufferView.cpp
index d126e130..38d0a5f4 100644
--- a/third_party/WebKit/Source/wtf/ArrayBufferView.cpp
+++ b/third_party/WebKit/Source/wtf/ArrayBufferView.cpp
@@ -30,15 +30,14 @@
 
 namespace WTF {
 
-ArrayBufferView::ArrayBufferView(PassRefPtr<ArrayBuffer> buffer,
-                       unsigned byteOffset)
-        : m_byteOffset(byteOffset)
-        , m_isNeuterable(true)
-        , m_buffer(buffer)
-        , m_prevView(0)
-        , m_nextView(0)
+ArrayBufferView::ArrayBufferView(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset)
+    : m_byteOffset(byteOffset)
+    , m_isNeuterable(true)
+    , m_buffer(buffer)
+    , m_prevView(nullptr)
+    , m_nextView(nullptr)
 {
-    m_baseAddress = m_buffer ? (static_cast<char*>(m_buffer->data()) + m_byteOffset) : 0;
+    m_baseAddress = m_buffer ? (static_cast<char*>(m_buffer->data()) + m_byteOffset) : nullptr;
     if (m_buffer)
         m_buffer->addView(this);
 }
diff --git a/third_party/WebKit/Source/wtf/ArrayBufferView.h b/third_party/WebKit/Source/wtf/ArrayBufferView.h
index e9bbe49..af64f26 100644
--- a/third_party/WebKit/Source/wtf/ArrayBufferView.h
+++ b/third_party/WebKit/Source/wtf/ArrayBufferView.h
@@ -37,7 +37,7 @@
 namespace WTF {
 
 class WTF_EXPORT ArrayBufferView : public RefCounted<ArrayBufferView> {
-  public:
+public:
     enum ViewType {
         TypeInt8,
         TypeUint8,
@@ -76,7 +76,7 @@
 
     virtual ~ArrayBufferView();
 
-  protected:
+protected:
     ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
 
     inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
@@ -84,9 +84,7 @@
     // Helper to verify that a given sub-range of an ArrayBuffer is
     // within range.
     template <typename T>
-    static bool verifySubRange(PassRefPtr<ArrayBuffer> buffer,
-                               unsigned byteOffset,
-                               unsigned numElements)
+    static bool verifySubRange(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned numElements)
     {
         if (!buffer)
             return false;
@@ -108,7 +106,7 @@
     unsigned m_byteOffset : 31;
     bool m_isNeuterable : 1;
 
-  private:
+private:
     friend class ArrayBuffer;
     RefPtr<ArrayBuffer> m_buffer;
     ArrayBufferView* m_prevView;
diff --git a/third_party/WebKit/Source/wtf/Assertions.cpp b/third_party/WebKit/Source/wtf/Assertions.cpp
index cc5e4de..b2d869a8 100644
--- a/third_party/WebKit/Source/wtf/Assertions.cpp
+++ b/third_party/WebKit/Source/wtf/Assertions.cpp
@@ -32,14 +32,13 @@
 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
 
 #include "config.h"
-#include "Assertions.h"
+#include "wtf/Assertions.h"
 
-#include "Compiler.h"
-#include "OwnPtr.h"
-#include "PassOwnPtr.h"
-
-#include <stdio.h>
+#include "wtf/Compiler.h"
+#include "wtf/OwnPtr.h"
+#include "wtf/PassOwnPtr.h"
 #include <stdarg.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -76,13 +75,13 @@
 {
 #if USE(CF) && !OS(WIN)
     if (strstr(format, "%@")) {
-        CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
+        CFStringRef cfFormat = CFStringCreateWithCString(nullptr, format, kCFStringEncodingUTF8);
 
 #if COMPILER(CLANG)
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wformat-nonliteral"
 #endif
-        CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args);
+        CFStringRef str = CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfFormat, args);
 #if COMPILER(CLANG)
 #pragma clang diagnostic pop
 #endif
@@ -119,8 +118,7 @@
 
         do {
             char* buffer = (char*)malloc(size);
-
-            if (buffer == NULL)
+            if (!buffer)
                 break;
 
             if (_vsnprintf(buffer, size, format, args) != -1) {
@@ -186,7 +184,7 @@
 static void printCallSite(const char* file, int line, const char* function)
 {
 #if OS(WIN) && defined(_DEBUG)
-    _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
+    _CrtDbgReport(_CRT_WARN, file, line, nullptr, "%s\n", function);
 #else
     // By using this format, which matches the format used by MSVC for compiler errors, developers
     // using Visual Studio can double-click the file/line number in the Output Window to have the
diff --git a/third_party/WebKit/Source/wtf/Assertions.h b/third_party/WebKit/Source/wtf/Assertions.h
index edd2aa6..2cfccfc 100644
--- a/third_party/WebKit/Source/wtf/Assertions.h
+++ b/third_party/WebKit/Source/wtf/Assertions.h
@@ -147,9 +147,7 @@
 #define CRASH() (__debugbreak(), IMMEDIATE_CRASH())
 #else
 #define CRASH() \
-    (WTFReportBacktrace(), \
-     (*(int*)0xfbadbeef = 0), \
-     IMMEDIATE_CRASH())
+    (WTFReportBacktrace(), (*(int*)0xfbadbeef = 0), IMMEDIATE_CRASH())
 #endif
 #endif
 
@@ -171,7 +169,7 @@
 
 #define BACKTRACE() do { \
     WTFReportBacktrace(); \
-} while(false)
+} while (false)
 
 #endif
 
@@ -190,13 +188,12 @@
 #define ASSERT(assertion) \
     (!(assertion) ? \
         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
-         CRASH()) : \
+            CRASH()) : \
         (void)0)
 
 #define ASSERT_AT(assertion, file, line, function) \
     (!(assertion) ? \
-        (WTFReportAssertionFailure(file, line, function, #assertion), \
-         CRASH()) :                                                   \
+        (WTFReportAssertionFailure(file, line, function, #assertion), CRASH()) : \
         (void)0)
 
 #define ASSERT_NOT_REACHED() do { \
@@ -232,7 +229,7 @@
 #define ASSERT_WITH_SECURITY_IMPLICATION(assertion) \
     (!(assertion) ? \
         (WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion), \
-         CRASH()) : \
+            CRASH()) : \
         (void)0)
 
 #define RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(assertion) ASSERT_WITH_SECURITY_IMPLICATION(assertion)
diff --git a/third_party/WebKit/Source/wtf/BitArray.h b/third_party/WebKit/Source/wtf/BitArray.h
index 54b84b4..2a39c71f 100644
--- a/third_party/WebKit/Source/wtf/BitArray.h
+++ b/third_party/WebKit/Source/wtf/BitArray.h
@@ -26,8 +26,8 @@
 #ifndef BitArray_h
 #define BitArray_h
 
-#include <string.h>
 #include "wtf/Assertions.h"
+#include <string.h>
 
 namespace WTF {
 
diff --git a/third_party/WebKit/Source/wtf/BitVector.cpp b/third_party/WebKit/Source/wtf/BitVector.cpp
index 8db54a3e..79a33228 100644
--- a/third_party/WebKit/Source/wtf/BitVector.cpp
+++ b/third_party/WebKit/Source/wtf/BitVector.cpp
@@ -24,7 +24,7 @@
  */
 
 #include "config.h"
-#include "BitVector.h"
+#include "wtf/BitVector.h"
 
 #include "wtf/LeakAnnotations.h"
 #include "wtf/PartitionAlloc.h"
@@ -38,9 +38,9 @@
 void BitVector::setSlow(const BitVector& other)
 {
     uintptr_t newBitsOrPointer;
-    if (other.isInline())
+    if (other.isInline()) {
         newBitsOrPointer = other.m_bitsOrPointer;
-    else {
+    } else {
         OutOfLineBits* newOutOfLineBits = OutOfLineBits::create(other.size());
         memcpy(newOutOfLineBits->bits(), other.bits(), byteCount(other.size()));
         newBitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits) >> 1;
@@ -104,8 +104,9 @@
             size_t oldNumWords = outOfLineBits()->numWords();
             memcpy(newOutOfLineBits->bits(), outOfLineBits()->bits(), oldNumWords * sizeof(void*));
             memset(newOutOfLineBits->bits() + oldNumWords, 0, (newNumWords - oldNumWords) * sizeof(void*));
-        } else
+        } else {
             memcpy(newOutOfLineBits->bits(), outOfLineBits()->bits(), newOutOfLineBits->numWords() * sizeof(void*));
+        }
         OutOfLineBits::destroy(outOfLineBits());
     }
     m_bitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits) >> 1;
diff --git a/third_party/WebKit/Source/wtf/CheckedArithmetic.h b/third_party/WebKit/Source/wtf/CheckedArithmetic.h
index 7fe15a7..4ae1bbe 100644
--- a/third_party/WebKit/Source/wtf/CheckedArithmetic.h
+++ b/third_party/WebKit/Source/wtf/CheckedArithmetic.h
@@ -66,8 +66,7 @@
 
 namespace WTF {
 
-enum class CheckedState
-{
+enum class CheckedState {
     DidOverflow,
     DidNotOverflow
 };
diff --git a/third_party/WebKit/Source/wtf/CryptographicallyRandomNumber.h b/third_party/WebKit/Source/wtf/CryptographicallyRandomNumber.h
index 00a8717b..a420198 100644
--- a/third_party/WebKit/Source/wtf/CryptographicallyRandomNumber.h
+++ b/third_party/WebKit/Source/wtf/CryptographicallyRandomNumber.h
@@ -26,9 +26,8 @@
 #ifndef WTF_CryptographicallyRandomNumber_h
 #define WTF_CryptographicallyRandomNumber_h
 
-#include <stdint.h>
-
 #include "wtf/WTFExport.h"
+#include <stdint.h>
 
 namespace WTF {
 
diff --git a/third_party/WebKit/Source/wtf/DateMath.cpp b/third_party/WebKit/Source/wtf/DateMath.cpp
index 0192f93..6732cea 100644
--- a/third_party/WebKit/Source/wtf/DateMath.cpp
+++ b/third_party/WebKit/Source/wtf/DateMath.cpp
@@ -70,22 +70,21 @@
  */
 
 #include "config.h"
-#include "DateMath.h"
+#include "wtf/DateMath.h"
 
-#include "Assertions.h"
-#include "ASCIICType.h"
-#include "CurrentTime.h"
-#include "MathExtras.h"
-#include "StdLibExtras.h"
-#include "StringExtras.h"
-
+#include "wtf/ASCIICType.h"
+#include "wtf/Assertions.h"
+#include "wtf/CurrentTime.h"
+#include "wtf/MathExtras.h"
+#include "wtf/StdLibExtras.h"
+#include "wtf/StringExtras.h"
+#include "wtf/text/StringBuilder.h"
 #include <algorithm>
 #include <limits.h>
 #include <limits>
 #include <math.h>
 #include <stdlib.h>
 #include <time.h>
-#include "wtf/text/StringBuilder.h"
 
 #if OS(WIN)
 #include <windows.h>
@@ -93,8 +92,6 @@
 #include <sys/time.h>
 #endif
 
-using namespace WTF;
-
 namespace WTF {
 
 /* Constants */
@@ -302,7 +299,7 @@
     // greater than the max year minus 27 (2010), we want to use the max year
     // minus 27 instead, to ensure there is a range of 28 years that all years
     // can map to.
-    return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27) ;
+    return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27);
 }
 
 /*
@@ -528,8 +525,9 @@
                 month = findMonth(wordStart);
             skipSpacesAndComments(dateString);
             wordStart = dateString;
-        } else
-           dateString++;
+        } else {
+            dateString++;
+        }
     }
 
     // Missing delimiter between month and day (like "January29")?
@@ -587,7 +585,7 @@
             dateString++;
         if (!*dateString)
             return std::numeric_limits<double>::quiet_NaN();
-     } else {
+    } else {
         if (*dateString == '-')
             dateString++;
 
@@ -627,9 +625,9 @@
     long hour = 0;
     long minute = 0;
     long second = 0;
-    if (!*newPosStr)
+    if (!*newPosStr) {
         dateString = newPosStr;
-    else {
+    } else {
         // ' 23:12:40 GMT'
         if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
             if (*newPosStr != ':')
diff --git a/third_party/WebKit/Source/wtf/DateMath.h b/third_party/WebKit/Source/wtf/DateMath.h
index b23e992..c7946a9 100644
--- a/third_party/WebKit/Source/wtf/DateMath.h
+++ b/third_party/WebKit/Source/wtf/DateMath.h
@@ -43,10 +43,10 @@
 #ifndef DateMath_h
 #define DateMath_h
 
+#include "wtf/WTFExport.h"
+#include "wtf/text/WTFString.h"
 #include <stdint.h>
 #include <string.h>
-#include "wtf/text/WTFString.h"
-#include "wtf/WTFExport.h"
 
 namespace WTF {
 
diff --git a/third_party/WebKit/Source/wtf/Deque.h b/third_party/WebKit/Source/wtf/Deque.h
index 89d4edc..45ecd0d 100644
--- a/third_party/WebKit/Source/wtf/Deque.h
+++ b/third_party/WebKit/Source/wtf/Deque.h
@@ -38,537 +38,542 @@
 #include <iterator>
 
 namespace WTF {
-    template<typename T, size_t inlineCapacity, typename Allocator> class DequeIteratorBase;
-    template<typename T, size_t inlineCapacity, typename Allocator> class DequeIterator;
-    template<typename T, size_t inlineCapacity, typename Allocator> class DequeConstIterator;
 
-    template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
-    class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> {
-        WTF_USE_ALLOCATOR(Deque, Allocator);
-    public:
-        typedef DequeIterator<T, inlineCapacity, Allocator> iterator;
-        typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator;
-        typedef std::reverse_iterator<iterator> reverse_iterator;
-        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-        typedef PassTraits<T> Pass;
-        typedef typename PassTraits<T>::PassType PassType;
+template <typename T, size_t inlineCapacity, typename Allocator> class DequeIteratorBase;
+template <typename T, size_t inlineCapacity, typename Allocator> class DequeIterator;
+template <typename T, size_t inlineCapacity, typename Allocator> class DequeConstIterator;
 
-        Deque();
-        Deque(const Deque<T, inlineCapacity, Allocator>&);
-        // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572
-        Deque<T, 0, Allocator>& operator=(const Deque&);
+template <typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
+class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> {
+    WTF_USE_ALLOCATOR(Deque, Allocator);
+public:
+    typedef DequeIterator<T, inlineCapacity, Allocator> iterator;
+    typedef DequeConstIterator<T, inlineCapacity, Allocator> const_iterator;
+    typedef std::reverse_iterator<iterator> reverse_iterator;
+    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+    typedef PassTraits<T> Pass;
+    typedef typename PassTraits<T>::PassType PassType;
 
-        void finalize();
-        void finalizeGarbageCollectedObject() { finalize(); }
-
-        // We hard wire the inlineCapacity to zero here, due to crbug.com/360572
-        void swap(Deque<T, 0, Allocator>&);
-
-        size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; }
-        bool isEmpty() const { return m_start == m_end; }
-
-        iterator begin() { return iterator(this, m_start); }
-        iterator end() { return iterator(this, m_end); }
-        const_iterator begin() const { return const_iterator(this, m_start); }
-        const_iterator end() const { return const_iterator(this, m_end); }
-        reverse_iterator rbegin() { return reverse_iterator(end()); }
-        reverse_iterator rend() { return reverse_iterator(begin()); }
-        const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
-        const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
-
-        T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
-        const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
-        PassType takeFirst();
-
-        T& last() { ASSERT(m_start != m_end); return *(--end()); }
-        const T& last() const { ASSERT(m_start != m_end); return *(--end()); }
-        PassType takeLast();
-
-        T& at(size_t i)
-        {
-            RELEASE_ASSERT(i < size());
-            size_t right = m_buffer.capacity() - m_start;
-            return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - right];
-        }
-        const T& at(size_t i) const
-        {
-            RELEASE_ASSERT(i < size());
-            size_t right = m_buffer.capacity() - m_start;
-            return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - right];
-        }
-
-        T& operator[](size_t i) { return at(i); }
-        const T& operator[](size_t i) const { return at(i); }
-
-        template<typename U> void append(const U&);
-        template<typename U> void prepend(const U&);
-        void removeFirst();
-        void removeLast();
-        void remove(iterator&);
-        void remove(const_iterator&);
-
-        void clear();
-
-        template<typename Predicate>
-        iterator findIf(Predicate&);
-
-        template<typename VisitorDispatcher> void trace(VisitorDispatcher);
-
-    private:
-        friend class DequeIteratorBase<T, inlineCapacity, Allocator>;
-
-        typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Buffer;
-        typedef VectorTypeOperations<T> TypeOperations;
-        typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase;
-
-        void remove(size_t position);
-        void destroyAll();
-        void expandCapacityIfNeeded();
-        void expandCapacity();
-
-        Buffer m_buffer;
-        unsigned m_start;
-        unsigned m_end;
-    };
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    class DequeIteratorBase {
-    protected:
-        DequeIteratorBase();
-        DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t);
-        DequeIteratorBase(const DequeIteratorBase&);
-        DequeIteratorBase<T, 0, Allocator>& operator=(const DequeIteratorBase<T, 0, Allocator>&);
-        ~DequeIteratorBase();
-
-        void assign(const DequeIteratorBase& other) { *this = other; }
-
-        void increment();
-        void decrement();
-
-        T* before() const;
-        T* after() const;
-
-        bool isEqual(const DequeIteratorBase&) const;
-
-    private:
-        Deque<T, inlineCapacity, Allocator>* m_deque;
-        unsigned m_index;
-
-        friend class Deque<T, inlineCapacity, Allocator>;
-    };
-
-    template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
-    class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
-        typedef DequeIterator<T, inlineCapacity, Allocator> Iterator;
-
-    public:
-        typedef ptrdiff_t difference_type;
-        typedef T value_type;
-        typedef T* pointer;
-        typedef T& reference;
-        typedef std::bidirectional_iterator_tag iterator_category;
-
-        DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) { }
-
-        DequeIterator(const Iterator& other) : Base(other) { }
-        DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
-
-        T& operator*() const { return *Base::after(); }
-        T* operator->() const { return Base::after(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::increment(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::decrement(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-    template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
-    class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
-        typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator;
-        typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator;
-
-    public:
-        typedef ptrdiff_t difference_type;
-        typedef T value_type;
-        typedef const T* pointer;
-        typedef const T& reference;
-        typedef std::bidirectional_iterator_tag iterator_category;
-
-        DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) { }
-
-        DequeConstIterator(const Iterator& other) : Base(other) { }
-        DequeConstIterator(const NonConstIterator& other) : Base(other) { }
-        DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
-        DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
-
-        const T& operator*() const { return *Base::after(); }
-        const T* operator->() const { return Base::after(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::increment(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::decrement(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline Deque<T, inlineCapacity, Allocator>::Deque()
-        : m_start(0)
-        , m_end(0)
-    {
-        static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
-#if ENABLE(OILPAN)
-        static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Deque");
-#endif
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapacity, Allocator>& other)
-        : m_buffer(other.m_buffer.capacity())
-        , m_start(other.m_start)
-        , m_end(other.m_end)
-    {
-        const T* otherBuffer = other.m_buffer.buffer();
-        if (m_start <= m_end)
-            TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start);
-        else {
-            TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer());
-            TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start);
-        }
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator=(const Deque& other)
-    {
-        Deque<T> copy(other);
-        swap(copy);
-        return *this;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::destroyAll()
-    {
-        if (m_start <= m_end) {
-            TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
-            m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
-        } else {
-            TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end);
-            m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_end);
-            TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
-            m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
-        }
-    }
-
-    // Off-GC-heap deques: Destructor should be called.
-    // On-GC-heap deques: Destructor should be called for inline buffers
-    // (if any) but destructor shouldn't be called for vector backing since
-    // it is managed by the traced GC heap.
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::finalize()
-    {
-        if (!INLINE_CAPACITY && !m_buffer.buffer())
-            return;
-        if (!isEmpty() && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBuffer()))
-            destroyAll();
-
-        m_buffer.destruct();
-    }
-
+    Deque();
+    Deque(const Deque<T, inlineCapacity, Allocator>&);
     // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, 0, Allocator>& other)
+    Deque<T, 0, Allocator>& operator=(const Deque&);
+
+    void finalize();
+    void finalizeGarbageCollectedObject() { finalize(); }
+
+    // We hard wire the inlineCapacity to zero here, due to crbug.com/360572
+    void swap(Deque<T, 0, Allocator>&);
+
+    size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; }
+    bool isEmpty() const { return m_start == m_end; }
+
+    iterator begin() { return iterator(this, m_start); }
+    iterator end() { return iterator(this, m_end); }
+    const_iterator begin() const { return const_iterator(this, m_start); }
+    const_iterator end() const { return const_iterator(this, m_end); }
+    reverse_iterator rbegin() { return reverse_iterator(end()); }
+    reverse_iterator rend() { return reverse_iterator(begin()); }
+    const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+    const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+    T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
+    const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
+    PassType takeFirst();
+
+    T& last() { ASSERT(m_start != m_end); return *(--end()); }
+    const T& last() const { ASSERT(m_start != m_end); return *(--end()); }
+    PassType takeLast();
+
+    T& at(size_t i)
     {
-        std::swap(m_start, other.m_start);
-        std::swap(m_end, other.m_end);
-        m_buffer.swapVectorBuffer(other.m_buffer);
+        RELEASE_ASSERT(i < size());
+        size_t right = m_buffer.capacity() - m_start;
+        return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - right];
+    }
+    const T& at(size_t i) const
+    {
+        RELEASE_ASSERT(i < size());
+        size_t right = m_buffer.capacity() - m_start;
+        return i < right ? m_buffer.buffer()[m_start + i] : m_buffer.buffer()[i - right];
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::clear()
-    {
+    T& operator[](size_t i) { return at(i); }
+    const T& operator[](size_t i) const { return at(i); }
+
+    template <typename U> void append(const U&);
+    template <typename U> void prepend(const U&);
+    void removeFirst();
+    void removeLast();
+    void remove(iterator&);
+    void remove(const_iterator&);
+
+    void clear();
+
+    template <typename Predicate>
+    iterator findIf(Predicate&);
+
+    template <typename VisitorDispatcher> void trace(VisitorDispatcher);
+
+private:
+    friend class DequeIteratorBase<T, inlineCapacity, Allocator>;
+
+    typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Buffer;
+    typedef VectorTypeOperations<T> TypeOperations;
+    typedef DequeIteratorBase<T, inlineCapacity, Allocator> IteratorBase;
+
+    void remove(size_t position);
+    void destroyAll();
+    void expandCapacityIfNeeded();
+    void expandCapacity();
+
+    Buffer m_buffer;
+    unsigned m_start;
+    unsigned m_end;
+};
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+class DequeIteratorBase {
+protected:
+    DequeIteratorBase();
+    DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>*, size_t);
+    DequeIteratorBase(const DequeIteratorBase&);
+    DequeIteratorBase<T, 0, Allocator>& operator=(const DequeIteratorBase<T, 0, Allocator>&);
+    ~DequeIteratorBase();
+
+    void assign(const DequeIteratorBase& other) { *this = other; }
+
+    void increment();
+    void decrement();
+
+    T* before() const;
+    T* after() const;
+
+    bool isEqual(const DequeIteratorBase&) const;
+
+private:
+    Deque<T, inlineCapacity, Allocator>* m_deque;
+    unsigned m_index;
+
+    friend class Deque<T, inlineCapacity, Allocator>;
+};
+
+template <typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
+class DequeIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
+private:
+    typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
+    typedef DequeIterator<T, inlineCapacity, Allocator> Iterator;
+
+public:
+    typedef ptrdiff_t difference_type;
+    typedef T value_type;
+    typedef T* pointer;
+    typedef T& reference;
+    typedef std::bidirectional_iterator_tag iterator_category;
+
+    DequeIterator(Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) {}
+
+    DequeIterator(const Iterator& other) : Base(other) {}
+    DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+
+    T& operator*() const { return *Base::after(); }
+    T* operator->() const { return Base::after(); }
+
+    bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+    bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+
+    Iterator& operator++() { Base::increment(); return *this; }
+    // postfix ++ intentionally omitted
+    Iterator& operator--() { Base::decrement(); return *this; }
+    // postfix -- intentionally omitted
+};
+
+template <typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
+class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity, Allocator> {
+private:
+    typedef DequeIteratorBase<T, inlineCapacity, Allocator> Base;
+    typedef DequeConstIterator<T, inlineCapacity, Allocator> Iterator;
+    typedef DequeIterator<T, inlineCapacity, Allocator> NonConstIterator;
+
+public:
+    typedef ptrdiff_t difference_type;
+    typedef T value_type;
+    typedef const T* pointer;
+    typedef const T& reference;
+    typedef std::bidirectional_iterator_tag iterator_category;
+
+    DequeConstIterator(const Deque<T, inlineCapacity, Allocator>* deque, size_t index) : Base(deque, index) {}
+
+    DequeConstIterator(const Iterator& other) : Base(other) {}
+    DequeConstIterator(const NonConstIterator& other) : Base(other) {}
+    DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
+    DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
+
+    const T& operator*() const { return *Base::after(); }
+    const T* operator->() const { return Base::after(); }
+
+    bool operator==(const Iterator& other) const { return Base::isEqual(other); }
+    bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
+    
+    Iterator& operator++() { Base::increment(); return *this; }
+    // postfix ++ intentionally omitted
+    Iterator& operator--() { Base::decrement(); return *this; }
+    // postfix -- intentionally omitted
+};
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline Deque<T, inlineCapacity, Allocator>::Deque()
+    : m_start(0)
+    , m_end(0)
+{
+    static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
+#if ENABLE(OILPAN)
+    static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Deque");
+#endif
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline Deque<T, inlineCapacity, Allocator>::Deque(const Deque<T, inlineCapacity, Allocator>& other)
+    : m_buffer(other.m_buffer.capacity())
+    , m_start(other.m_start)
+    , m_end(other.m_end)
+{
+    const T* otherBuffer = other.m_buffer.buffer();
+    if (m_start <= m_end) {
+        TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start);
+    } else {
+        TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer());
+        TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start);
+    }
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline Deque<T, 0, Allocator>& Deque<T, inlineCapacity, Allocator>::operator=(const Deque& other)
+{
+    Deque<T> copy(other);
+    swap(copy);
+    return *this;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::destroyAll()
+{
+    if (m_start <= m_end) {
+        TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
+        m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
+    } else {
+        TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end);
+        m_buffer.clearUnusedSlots(m_buffer.buffer(), m_buffer.buffer() + m_end);
+        TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
+        m_buffer.clearUnusedSlots(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
+    }
+}
+
+// Off-GC-heap deques: Destructor should be called.
+// On-GC-heap deques: Destructor should be called for inline buffers (if any)
+// but destructor shouldn't be called for vector backing since it is managed by
+// the traced GC heap.
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::finalize()
+{
+    if (!INLINE_CAPACITY && !m_buffer.buffer())
+        return;
+    if (!isEmpty() && !(Allocator::isGarbageCollected && m_buffer.hasOutOfLineBuffer()))
         destroyAll();
-        m_start = 0;
-        m_end = 0;
-        m_buffer.deallocateBuffer(m_buffer.buffer());
-        m_buffer.resetBufferPointer();
-    }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename Predicate>
-    inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allocator>::findIf(Predicate& predicate)
-    {
-        iterator end_iterator = end();
-        for (iterator it = begin(); it != end_iterator; ++it) {
-            if (predicate(*it))
-                return it;
-        }
-        return end_iterator;
-    }
+    m_buffer.destruct();
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded()
-    {
-        if (m_start) {
-            if (m_end + 1 != m_start)
-                return;
-        } else if (m_end) {
-            if (m_end != m_buffer.capacity() - 1)
-                return;
-        } else if (m_buffer.capacity())
+// FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::swap(Deque<T, 0, Allocator>& other)
+{
+    std::swap(m_start, other.m_start);
+    std::swap(m_end, other.m_end);
+    m_buffer.swapVectorBuffer(other.m_buffer);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::clear()
+{
+    destroyAll();
+    m_start = 0;
+    m_end = 0;
+    m_buffer.deallocateBuffer(m_buffer.buffer());
+    m_buffer.resetBufferPointer();
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename Predicate>
+inline DequeIterator<T, inlineCapacity, Allocator> Deque<T, inlineCapacity, Allocator>::findIf(Predicate& predicate)
+{
+    iterator endIterator = end();
+    for (iterator it = begin(); it != endIterator; ++it) {
+        if (predicate(*it))
+            return it;
+    }
+    return endIterator;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::expandCapacityIfNeeded()
+{
+    if (m_start) {
+        if (m_end + 1 != m_start)
             return;
-
-        expandCapacity();
+    } else if (m_end) {
+        if (m_end != m_buffer.capacity() - 1)
+            return;
+    } else if (m_buffer.capacity()) {
+        return;
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Deque<T, inlineCapacity, Allocator>::expandCapacity()
-    {
-        size_t oldCapacity = m_buffer.capacity();
-        T* oldBuffer = m_buffer.buffer();
-        size_t newCapacity = std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1);
-        if (m_buffer.expandBuffer(newCapacity)) {
-            if (m_start <= m_end) {
-                // No adjustments to be done.
-            } else {
-                size_t newStart = m_buffer.capacity() - (oldCapacity - m_start);
-                TypeOperations::moveOverlapping(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
-                m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + std::min(oldCapacity, newStart));
-                m_start = newStart;
-            }
-            return;
-        }
-        m_buffer.allocateBuffer(newCapacity);
+    expandCapacity();
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Deque<T, inlineCapacity, Allocator>::expandCapacity()
+{
+    size_t oldCapacity = m_buffer.capacity();
+    T* oldBuffer = m_buffer.buffer();
+    size_t newCapacity = std::max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1);
+    if (m_buffer.expandBuffer(newCapacity)) {
         if (m_start <= m_end) {
-            TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start);
-            m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + m_end);
+            // No adjustments to be done.
         } else {
-            TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer());
-            m_buffer.clearUnusedSlots(oldBuffer, oldBuffer + m_end);
             size_t newStart = m_buffer.capacity() - (oldCapacity - m_start);
-            TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
-            m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + oldCapacity);
+            TypeOperations::moveOverlapping(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
+            m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + std::min(oldCapacity, newStart));
             m_start = newStart;
         }
-        m_buffer.deallocateBuffer(oldBuffer);
+        return;
     }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeFirst()
-    {
-        T oldFirst = Pass::transfer(first());
-        removeFirst();
-        return Pass::transfer(oldFirst);
+    m_buffer.allocateBuffer(newCapacity);
+    if (m_start <= m_end) {
+        TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start);
+        m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + m_end);
+    } else {
+        TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer());
+        m_buffer.clearUnusedSlots(oldBuffer, oldBuffer + m_end);
+        size_t newStart = m_buffer.capacity() - (oldCapacity - m_start);
+        TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
+        m_buffer.clearUnusedSlots(oldBuffer + m_start, oldBuffer + oldCapacity);
+        m_start = newStart;
     }
+    m_buffer.deallocateBuffer(oldBuffer);
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeLast()
-    {
-        T oldLast = Pass::transfer(last());
-        removeLast();
-        return Pass::transfer(oldLast);
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeFirst()
+{
+    T oldFirst = Pass::transfer(first());
+    removeFirst();
+    return Pass::transfer(oldFirst);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline typename Deque<T, inlineCapacity, Allocator>::PassType Deque<T, inlineCapacity, Allocator>::takeLast()
+{
+    T oldLast = Pass::transfer(last());
+    removeLast();
+    return Pass::transfer(oldLast);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+inline void Deque<T, inlineCapacity, Allocator>::append(const U& value)
+{
+    expandCapacityIfNeeded();
+    new (NotNull, &m_buffer.buffer()[m_end]) T(value);
+    if (m_end == m_buffer.capacity() - 1)
+        m_end = 0;
+    else
+        ++m_end;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value)
+{
+    expandCapacityIfNeeded();
+    if (!m_start)
+        m_start = m_buffer.capacity() - 1;
+    else
+        --m_start;
+    new (NotNull, &m_buffer.buffer()[m_start]) T(value);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::removeFirst()
+{
+    ASSERT(!isEmpty());
+    TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
+    m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
+    if (m_start == m_buffer.capacity() - 1)
+        m_start = 0;
+    else
+        ++m_start;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::removeLast()
+{
+    ASSERT(!isEmpty());
+    if (!m_end)
+        m_end = m_buffer.capacity() - 1;
+    else
+        --m_end;
+    TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]);
+    m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it)
+{
+    remove(it.m_index);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it)
+{
+    remove(it.m_index);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position)
+{
+    if (position == m_end)
+        return;
+
+    T* buffer = m_buffer.buffer();
+    TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
+
+    // Find which segment of the circular buffer contained the remove element,
+    // and only move elements in that part.
+    if (position >= m_start) {
+        TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1);
+        m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1);
+        m_start = (m_start + 1) % m_buffer.capacity();
+    } else {
+        TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position);
+        m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end);
+        m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
     }
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    inline void Deque<T, inlineCapacity, Allocator>::append(const U& value)
-    {
-        expandCapacityIfNeeded();
-        new (NotNull, &m_buffer.buffer()[m_end]) T(value);
-        if (m_end == m_buffer.capacity() - 1)
-            m_end = 0;
-        else
-            ++m_end;
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase()
+    : m_deque(0)
+{
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    inline void Deque<T, inlineCapacity, Allocator>::prepend(const U& value)
-    {
-        expandCapacityIfNeeded();
-        if (!m_start)
-            m_start = m_buffer.capacity() - 1;
-        else
-            --m_start;
-        new (NotNull, &m_buffer.buffer()[m_start]) T(value);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>* deque, size_t index)
+    : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque))
+    , m_index(index)
+{
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::removeFirst()
-    {
-        ASSERT(!isEmpty());
-        TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
-        m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
-        if (m_start == m_buffer.capacity() - 1)
-            m_start = 0;
-        else
-            ++m_start;
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const DequeIteratorBase& other)
+    : m_deque(other.m_deque)
+    , m_index(other.m_index)
+{
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::removeLast()
-    {
-        ASSERT(!isEmpty());
-        if (!m_end)
-            m_end = m_buffer.capacity() - 1;
-        else
-            --m_end;
-        TypeOperations::destruct(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]);
-        m_buffer.clearUnusedSlots(&m_buffer.buffer()[m_end], &m_buffer.buffer()[m_end + 1]);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline DequeIteratorBase<T, 0, Allocator>& DequeIteratorBase<T, inlineCapacity, Allocator>::operator=(const DequeIteratorBase<T, 0, Allocator>& other)
+{
+    m_deque = other.m_deque;
+    m_index = other.m_index;
+    return *this;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::remove(iterator& it)
-    {
-        remove(it.m_index);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase()
+{
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::remove(const_iterator& it)
-    {
-        remove(it.m_index);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const DequeIteratorBase& other) const
+{
+    return m_index == other.m_index;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Deque<T, inlineCapacity, Allocator>::remove(size_t position)
-    {
-        if (position == m_end)
-            return;
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment()
+{
+    ASSERT(m_index != m_deque->m_end);
+    ASSERT(m_deque->m_buffer.capacity());
+    if (m_index == m_deque->m_buffer.capacity() - 1)
+        m_index = 0;
+    else
+        ++m_index;
+}
 
-        T* buffer = m_buffer.buffer();
-        TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement()
+{
+    ASSERT(m_index != m_deque->m_start);
+    ASSERT(m_deque->m_buffer.capacity());
+    if (!m_index)
+        m_index = m_deque->m_buffer.capacity() - 1;
+    else
+        --m_index;
+}
 
-        // Find which segment of the circular buffer contained the remove element, and only move elements in that part.
-        if (position >= m_start) {
-            TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1);
-            m_buffer.clearUnusedSlots(buffer + m_start, buffer + m_start + 1);
-            m_start = (m_start + 1) % m_buffer.capacity();
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const
+{
+    ASSERT(m_index != m_deque->m_end);
+    return &m_deque->m_buffer.buffer()[m_index];
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const
+{
+    ASSERT(m_index != m_deque->m_start);
+    if (!m_index)
+        return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1];
+    return &m_deque->m_buffer.buffer()[m_index - 1];
+}
+
+// This is only called if the allocator is a HeapAllocator. It is used when
+// visiting during a tracing GC.
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename VisitorDispatcher>
+void Deque<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor)
+{
+    ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled.
+    const T* bufferBegin = m_buffer.buffer();
+    const T* end = bufferBegin + m_end;
+    if (ShouldBeTraced<VectorTraits<T>>::value) {
+        if (m_start <= m_end) {
+            for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != end; bufferEntry++)
+                Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
         } else {
-            TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position);
-            m_buffer.clearUnusedSlots(buffer + m_end - 1, buffer + m_end);
-            m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
+            for (const T* bufferEntry = bufferBegin; bufferEntry != end; bufferEntry++)
+                Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
+            const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity();
+            for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != bufferEnd; bufferEntry++)
+                Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
         }
     }
+    if (m_buffer.hasOutOfLineBuffer())
+        Allocator::markNoTracing(visitor, m_buffer.buffer());
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase()
-        : m_deque(0)
-    {
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const Deque<T, inlineCapacity, Allocator>* deque, size_t index)
-        : m_deque(const_cast<Deque<T, inlineCapacity, Allocator>*>(deque))
-        , m_index(index)
-    {
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(const DequeIteratorBase& other)
-        : m_deque(other.m_deque)
-        , m_index(other.m_index)
-    {
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline DequeIteratorBase<T, 0, Allocator>& DequeIteratorBase<T, inlineCapacity, Allocator>::operator=(const DequeIteratorBase<T, 0, Allocator>& other)
-    {
-        m_deque = other.m_deque;
-        m_index = other.m_index;
-        return *this;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline DequeIteratorBase<T, inlineCapacity, Allocator>::~DequeIteratorBase()
-    {
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline bool DequeIteratorBase<T, inlineCapacity, Allocator>::isEqual(const DequeIteratorBase& other) const
-    {
-        return m_index == other.m_index;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void DequeIteratorBase<T, inlineCapacity, Allocator>::increment()
-    {
-        ASSERT(m_index != m_deque->m_end);
-        ASSERT(m_deque->m_buffer.capacity());
-        if (m_index == m_deque->m_buffer.capacity() - 1)
-            m_index = 0;
-        else
-            ++m_index;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void DequeIteratorBase<T, inlineCapacity, Allocator>::decrement()
-    {
-        ASSERT(m_index != m_deque->m_start);
-        ASSERT(m_deque->m_buffer.capacity());
-        if (!m_index)
-            m_index = m_deque->m_buffer.capacity() - 1;
-        else
-            --m_index;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::after() const
-    {
-        ASSERT(m_index != m_deque->m_end);
-        return &m_deque->m_buffer.buffer()[m_index];
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline T* DequeIteratorBase<T, inlineCapacity, Allocator>::before() const
-    {
-        ASSERT(m_index != m_deque->m_start);
-        if (!m_index)
-            return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1];
-        return &m_deque->m_buffer.buffer()[m_index - 1];
-    }
-
-    // This is only called if the allocator is a HeapAllocator. It is used when
-    // visiting during a tracing GC.
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename VisitorDispatcher>
-    void Deque<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor)
-    {
-        ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled.
-        const T* bufferBegin = m_buffer.buffer();
-        const T* end = bufferBegin + m_end;
-        if (ShouldBeTraced<VectorTraits<T>>::value) {
-            if (m_start <= m_end) {
-                for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != end; bufferEntry++)
-                    Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
-            } else {
-                for (const T* bufferEntry = bufferBegin; bufferEntry != end; bufferEntry++)
-                    Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
-                const T* bufferEnd = m_buffer.buffer() + m_buffer.capacity();
-                for (const T* bufferEntry = bufferBegin + m_start; bufferEntry != bufferEnd; bufferEntry++)
-                    Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
-            }
-        }
-        if (m_buffer.hasOutOfLineBuffer())
-            Allocator::markNoTracing(visitor, m_buffer.buffer());
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void swap(Deque<T, inlineCapacity, Allocator>& a, Deque<T, inlineCapacity, Allocator>& b)
-    {
-        a.swap(b);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void swap(Deque<T, inlineCapacity, Allocator>& a, Deque<T, inlineCapacity, Allocator>& b)
+{
+    a.swap(b);
+}
 
 #if !ENABLE(OILPAN)
-    template<typename T, size_t N>
-    struct NeedsTracing<Deque<T, N>> {
-        static const bool value = false;
-    };
+template <typename T, size_t N>
+struct NeedsTracing<Deque<T, N>> {
+    static const bool value = false;
+};
 #endif
 
 } // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/FastAllocBase.h b/third_party/WebKit/Source/wtf/FastAllocBase.h
index 540e3f5..8c40270 100644
--- a/third_party/WebKit/Source/wtf/FastAllocBase.h
+++ b/third_party/WebKit/Source/wtf/FastAllocBase.h
@@ -73,7 +73,7 @@
     \
     void operator delete[](void* p) \
     { \
-         ::WTF::fastFree(p); \
+        ::WTF::fastFree(p); \
     } \
     void* operator new(size_t, NotNullTag, void* location) \
     { \
diff --git a/third_party/WebKit/Source/wtf/FilePrintStream.h b/third_party/WebKit/Source/wtf/FilePrintStream.h
index 7e20d24d..6f4eccdf6 100644
--- a/third_party/WebKit/Source/wtf/FilePrintStream.h
+++ b/third_party/WebKit/Source/wtf/FilePrintStream.h
@@ -26,9 +26,9 @@
 #ifndef FilePrintStream_h
 #define FilePrintStream_h
 
-#include <stdio.h>
 #include "wtf/PassOwnPtr.h"
 #include "wtf/PrintStream.h"
+#include <stdio.h>
 
 namespace WTF {
 
diff --git a/third_party/WebKit/Source/wtf/Float32Array.h b/third_party/WebKit/Source/wtf/Float32Array.h
index 710cf26..25bec054 100644
--- a/third_party/WebKit/Source/wtf/Float32Array.h
+++ b/third_party/WebKit/Source/wtf/Float32Array.h
@@ -27,8 +27,8 @@
 #ifndef Float32Array_h
 #define Float32Array_h
 
-#include "wtf/TypedArrayBase.h"
 #include "wtf/MathExtras.h"
+#include "wtf/TypedArrayBase.h"
 
 namespace WTF {
 
@@ -55,9 +55,7 @@
     }
 
 private:
-    inline Float32Array(PassRefPtr<ArrayBuffer>,
-                    unsigned byteOffset,
-                    unsigned length);
+    inline Float32Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<float>;
 };
diff --git a/third_party/WebKit/Source/wtf/Float64Array.h b/third_party/WebKit/Source/wtf/Float64Array.h
index a56389f..14be7a28 100644
--- a/third_party/WebKit/Source/wtf/Float64Array.h
+++ b/third_party/WebKit/Source/wtf/Float64Array.h
@@ -27,8 +27,8 @@
 #ifndef Float64Array_h
 #define Float64Array_h
 
-#include "wtf/TypedArrayBase.h"
 #include "wtf/MathExtras.h"
+#include "wtf/TypedArrayBase.h"
 
 namespace WTF {
 
@@ -57,9 +57,7 @@
     }
 
 private:
-    inline Float64Array(PassRefPtr<ArrayBuffer>,
-                 unsigned byteOffset,
-                 unsigned length);
+    inline Float64Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<double>;
 };
diff --git a/third_party/WebKit/Source/wtf/Forward.h b/third_party/WebKit/Source/wtf/Forward.h
index 8fe791b..ea652511 100644
--- a/third_party/WebKit/Source/wtf/Forward.h
+++ b/third_party/WebKit/Source/wtf/Forward.h
@@ -24,34 +24,35 @@
 #include <stddef.h>
 
 namespace WTF {
-    template<typename T> class Function;
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnPtr;
-    template<typename T> class PassRefPtr;
-    template<typename T> class RefPtr;
-    template<typename T, size_t inlineCapacity, typename Allocator> class Vector;
-    template<typename T> class WeakPtr;
 
-    class ArrayBuffer;
-    class ArrayBufferView;
-    class ArrayPiece;
-    class AtomicString;
-    class CString;
-    class Float32Array;
-    class Float64Array;
-    class Int8Array;
-    class Int16Array;
-    class Int32Array;
-    template<size_t size>
-    class SizeSpecificPartitionAllocator;
-    class String;
-    template <typename T> class StringBuffer;
-    class StringBuilder;
-    class StringImpl;
-    class Uint8Array;
-    class Uint8ClampedArray;
-    class Uint16Array;
-    class Uint32Array;
+template <typename T> class Function;
+template <typename T> class OwnPtr;
+template <typename T> class PassOwnPtr;
+template <typename T> class PassRefPtr;
+template <typename T> class RefPtr;
+template <size_t size> class SizeSpecificPartitionAllocator;
+template <typename T> class StringBuffer;
+template <typename T, size_t inlineCapacity, typename Allocator> class Vector;
+template <typename T> class WeakPtr;
+
+class ArrayBuffer;
+class ArrayBufferView;
+class ArrayPiece;
+class AtomicString;
+class CString;
+class Float32Array;
+class Float64Array;
+class Int8Array;
+class Int16Array;
+class Int32Array;
+class String;
+class StringBuilder;
+class StringImpl;
+class Uint8Array;
+class Uint8ClampedArray;
+class Uint16Array;
+class Uint32Array;
+
 }
 
 using WTF::Function;
diff --git a/third_party/WebKit/Source/wtf/GetPtr.h b/third_party/WebKit/Source/wtf/GetPtr.h
index a0f7c62..f88fb80 100644
--- a/third_party/WebKit/Source/wtf/GetPtr.h
+++ b/third_party/WebKit/Source/wtf/GetPtr.h
@@ -23,15 +23,15 @@
 
 namespace WTF {
 
-    template <typename T> inline T* getPtr(T* p)
-    {
-        return p;
-    }
+template <typename T> inline T* getPtr(T* p)
+{
+    return p;
+}
 
-    template <typename T> inline T* getPtr(T& p)
-    {
-        return &p;
-    }
+template <typename T> inline T* getPtr(T& p)
+{
+    return &p;
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/HashCountedSet.h b/third_party/WebKit/Source/wtf/HashCountedSet.h
index 2606012..11b27772 100644
--- a/third_party/WebKit/Source/wtf/HashCountedSet.h
+++ b/third_party/WebKit/Source/wtf/HashCountedSet.h
@@ -27,136 +27,138 @@
 
 namespace WTF {
 
-    // An unordered hash set that keeps track of how many times you added an
-    // item to the set. The iterators have fields ->key and ->value that return
-    // the set members and their counts, respectively.
-    template<
-        typename Value,
-        typename HashFunctions = typename DefaultHash<Value>::Hash,
-        typename Traits = HashTraits<Value>,
-        typename Allocator = DefaultAllocator > class HashCountedSet {
-        WTF_USE_ALLOCATOR(HashCountedSet, Allocator);
-    private:
-        typedef HashMap<Value, unsigned, HashFunctions, Traits, HashTraits<unsigned>, Allocator> ImplType;
-    public:
-        typedef Value ValueType;
-        typedef typename ImplType::iterator iterator;
-        typedef typename ImplType::const_iterator const_iterator;
-        typedef typename ImplType::AddResult AddResult;
+// An unordered hash set that keeps track of how many times you added an item to
+// the set. The iterators have fields ->key and ->value that return the set
+// members and their counts, respectively.
+template <
+    typename Value,
+    typename HashFunctions = typename DefaultHash<Value>::Hash,
+    typename Traits = HashTraits<Value>,
+    typename Allocator = DefaultAllocator>
+class HashCountedSet {
+    WTF_USE_ALLOCATOR(HashCountedSet, Allocator);
+private:
+    typedef HashMap<Value, unsigned, HashFunctions, Traits, HashTraits<unsigned>, Allocator> ImplType;
+public:
+    typedef Value ValueType;
+    typedef typename ImplType::iterator iterator;
+    typedef typename ImplType::const_iterator const_iterator;
+    typedef typename ImplType::AddResult AddResult;
 
-        HashCountedSet() {}
+    HashCountedSet() {}
 
-        void swap(HashCountedSet& other) { m_impl.swap(other.m_impl); }
+    void swap(HashCountedSet& other) { m_impl.swap(other.m_impl); }
 
-        unsigned size() const { return m_impl.size(); }
-        unsigned capacity() const { return m_impl.capacity(); }
-        bool isEmpty() const { return m_impl.isEmpty(); }
+    unsigned size() const { return m_impl.size(); }
+    unsigned capacity() const { return m_impl.capacity(); }
+    bool isEmpty() const { return m_impl.isEmpty(); }
 
-        // Iterators iterate over pairs of values (called key) and counts (called value).
-        iterator begin() { return m_impl.begin(); }
-        iterator end() { return m_impl.end(); }
-        const_iterator begin() const { return m_impl.begin(); }
-        const_iterator end() const { return m_impl.end(); }
+    // Iterators iterate over pairs of values (called key) and counts (called
+    // value).
+    iterator begin() { return m_impl.begin(); }
+    iterator end() { return m_impl.end(); }
+    const_iterator begin() const { return m_impl.begin(); }
+    const_iterator end() const { return m_impl.end(); }
 
-        iterator find(const ValueType& value) { return m_impl.find(value); }
-        const_iterator find(const ValueType& value) const { return m_impl.find(value); }
-        bool contains(const ValueType& value ) const { return m_impl.contains(value); }
-        unsigned count(const ValueType& value ) const { return m_impl.get(value); }
+    iterator find(const ValueType& value) { return m_impl.find(value); }
+    const_iterator find(const ValueType& value) const { return m_impl.find(value); }
+    bool contains(const ValueType& value ) const { return m_impl.contains(value); }
+    unsigned count(const ValueType& value ) const { return m_impl.get(value); }
 
-        // Increases the count if an equal value is already present
-        // the return value is a pair of an iterator to the new value's
-        // location, and a bool that is true if an new entry was added.
-        AddResult add(const ValueType&);
+    // Increases the count if an equal value is already present the return value
+    // is a pair of an iterator to the new value's location, and a bool that is
+    // true if an new entry was added.
+    AddResult add(const ValueType&);
 
-        // Reduces the count of the value, and removes it if count
-        // goes down to zero, returns true if the value is removed.
-        bool remove(const ValueType& value) { return remove(find(value)); }
-        bool remove(iterator);
+    // Reduces the count of the value, and removes it if count goes down to
+    // zero, returns true if the value is removed.
+    bool remove(const ValueType& value) { return remove(find(value)); }
+    bool remove(iterator);
 
-        // Removes the value, regardless of its count.
-        void removeAll(const ValueType& value) { removeAll(find(value)); }
-        void removeAll(iterator);
+    // Removes the value, regardless of its count.
+    void removeAll(const ValueType& value) { removeAll(find(value)); }
+    void removeAll(iterator);
 
-        // Clears the whole set.
-        void clear() { m_impl.clear(); }
+    // Clears the whole set.
+    void clear() { m_impl.clear(); }
 
-        template<typename VisitorDispatcher>
-        void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
+    template <typename VisitorDispatcher>
+    void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
 
-    private:
-        ImplType m_impl;
-    };
+private:
+    ImplType m_impl;
+};
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashCountedSet<T, U, V, W>::AddResult HashCountedSet<T, U, V, W>::add(const ValueType& value)
-    {
-        AddResult result = m_impl.add(value, 0);
-        ++result.storedValue->value;
-        return result;
+template <typename T, typename U, typename V, typename W>
+inline typename HashCountedSet<T, U, V, W>::AddResult HashCountedSet<T, U, V, W>::add(const ValueType& value)
+{
+    AddResult result = m_impl.add(value, 0);
+    ++result.storedValue->value;
+    return result;
+}
+
+template <typename T, typename U, typename V, typename W>
+inline bool HashCountedSet<T, U, V, W>::remove(iterator it)
+{
+    if (it == end())
+        return false;
+
+    unsigned oldVal = it->value;
+    ASSERT(oldVal);
+    unsigned newVal = oldVal - 1;
+    if (newVal) {
+        it->value = newVal;
+        return false;
     }
 
-    template<typename T, typename U, typename V, typename W>
-    inline bool HashCountedSet<T, U, V, W>::remove(iterator it)
-    {
-        if (it == end())
-            return false;
+    m_impl.remove(it);
+    return true;
+}
 
-        unsigned oldVal = it->value;
-        ASSERT(oldVal);
-        unsigned newVal = oldVal - 1;
-        if (newVal) {
-            it->value = newVal;
-            return false;
-        }
+template <typename T, typename U, typename V, typename W>
+inline void HashCountedSet<T, U, V, W>::removeAll(iterator it)
+{
+    if (it == end())
+        return;
 
-        m_impl.remove(it);
-        return true;
-    }
+    m_impl.remove(it);
+}
 
-    template<typename T, typename U, typename V, typename W>
-    inline void HashCountedSet<T, U, V, W>::removeAll(iterator it)
-    {
-        if (it == end())
-            return;
+template <typename T, typename U, typename V, typename W, typename VectorType>
+inline void copyToVector(const HashCountedSet<T, U, V, W>& collection, VectorType& vector)
+{
+    typedef typename HashCountedSet<T, U, V, W>::const_iterator iterator;
 
-        m_impl.remove(it);
-    }
+    vector.resize(collection.size());
 
-    template<typename T, typename U, typename V, typename W, typename VectorType>
-    inline void copyToVector(const HashCountedSet<T, U, V, W>& collection, VectorType& vector)
-    {
-        typedef typename HashCountedSet<T, U, V, W>::const_iterator iterator;
+    iterator it = collection.begin();
+    iterator end = collection.end();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        vector[i] = *it;
+}
 
-        vector.resize(collection.size());
+template <typename Value, typename HashFunctions, typename Traits, typename Allocator, size_t inlineCapacity, typename VectorAllocator>
+inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits, Allocator>& collection, Vector<Value, inlineCapacity, VectorAllocator>& vector)
+{
+    typedef typename HashCountedSet<Value, HashFunctions, Traits, Allocator>::const_iterator iterator;
 
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }
+    vector.resize(collection.size());
 
-    template<typename Value, typename HashFunctions, typename Traits, typename Allocator, size_t inlineCapacity, typename VectorAllocator>
-    inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits, Allocator>& collection, Vector<Value, inlineCapacity, VectorAllocator>& vector)
-    {
-        typedef typename HashCountedSet<Value, HashFunctions, Traits, Allocator>::const_iterator iterator;
-
-        vector.resize(collection.size());
-
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = (*it).key;
-    }
+    iterator it = collection.begin();
+    iterator end = collection.end();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        vector[i] = (*it).key;
+}
 
 #if !ENABLE(OILPAN)
-    template<typename T, typename U, typename V>
-    struct NeedsTracing<HashCountedSet<T, U, V>> {
-        static const bool value = false;
-    };
+template <typename T, typename U, typename V>
+struct NeedsTracing<HashCountedSet<T, U, V>> {
+    static const bool value = false;
+};
 #endif
 
 } // namespace WTF
 
 using WTF::HashCountedSet;
 
-#endif /* WTF_HashCountedSet_h */
+#endif // WTF_HashCountedSet_h
diff --git a/third_party/WebKit/Source/wtf/HashFunctions.h b/third_party/WebKit/Source/wtf/HashFunctions.h
index 2ccf357..885f30c 100644
--- a/third_party/WebKit/Source/wtf/HashFunctions.h
+++ b/third_party/WebKit/Source/wtf/HashFunctions.h
@@ -28,220 +28,220 @@
 
 namespace WTF {
 
-    template<size_t size> struct IntTypes;
-    template<> struct IntTypes<1> { typedef int8_t SignedType; typedef uint8_t UnsignedType; };
-    template<> struct IntTypes<2> { typedef int16_t SignedType; typedef uint16_t UnsignedType; };
-    template<> struct IntTypes<4> { typedef int32_t SignedType; typedef uint32_t UnsignedType; };
-    template<> struct IntTypes<8> { typedef int64_t SignedType; typedef uint64_t UnsignedType; };
+template <size_t size> struct IntTypes;
+template <> struct IntTypes<1> { typedef int8_t SignedType; typedef uint8_t UnsignedType; };
+template <> struct IntTypes<2> { typedef int16_t SignedType; typedef uint16_t UnsignedType; };
+template <> struct IntTypes<4> { typedef int32_t SignedType; typedef uint32_t UnsignedType; };
+template <> struct IntTypes<8> { typedef int64_t SignedType; typedef uint64_t UnsignedType; };
 
-    // integer hash function
+// integer hash function
 
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint8_t key8)
+// Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+inline unsigned intHash(uint8_t key8)
+{
+    unsigned key = key8;
+    key += ~(key << 15);
+    key ^= (key >> 10);
+    key += (key << 3);
+    key ^= (key >> 6);
+    key += ~(key << 11);
+    key ^= (key >> 16);
+    return key;
+}
+
+// Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+inline unsigned intHash(uint16_t key16)
+{
+    unsigned key = key16;
+    key += ~(key << 15);
+    key ^= (key >> 10);
+    key += (key << 3);
+    key ^= (key >> 6);
+    key += ~(key << 11);
+    key ^= (key >> 16);
+    return key;
+}
+
+// Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+inline unsigned intHash(uint32_t key)
+{
+    key += ~(key << 15);
+    key ^= (key >> 10);
+    key += (key << 3);
+    key ^= (key >> 6);
+    key += ~(key << 11);
+    key ^= (key >> 16);
+    return key;
+}
+
+// Thomas Wang's 64 bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
+inline unsigned intHash(uint64_t key)
+{
+    key += ~(key << 32);
+    key ^= (key >> 22);
+    key += ~(key << 13);
+    key ^= (key >> 8);
+    key += (key << 3);
+    key ^= (key >> 15);
+    key += ~(key << 27);
+    key ^= (key >> 31);
+    return static_cast<unsigned>(key);
+}
+
+// Compound integer hash method: http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
+inline unsigned pairIntHash(unsigned key1, unsigned key2)
+{
+    unsigned shortRandom1 = 277951225; // A random 32-bit value.
+    unsigned shortRandom2 = 95187966; // A random 32-bit value.
+    uint64_t longRandom = 19248658165952622LL; // A random 64-bit value.
+
+    uint64_t product = longRandom * (shortRandom1 * key1 + shortRandom2 * key2);
+    unsigned highBits = static_cast<unsigned>(product >> (sizeof(uint64_t) - sizeof(unsigned)));
+    return highBits;
+}
+
+template <typename T> struct IntHash {
+    static unsigned hash(T key) { return intHash(static_cast<typename IntTypes<sizeof(T)>::UnsignedType>(key)); }
+    static bool equal(T a, T b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+template <typename T> struct FloatHash {
+    typedef typename IntTypes<sizeof(T)>::UnsignedType Bits;
+    static unsigned hash(T key)
     {
-        unsigned key = key8;
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
+        return intHash(bitwise_cast<Bits>(key));
     }
-
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint16_t key16)
+    static bool equal(T a, T b)
     {
-        unsigned key = key16;
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
+        return bitwise_cast<Bits>(a) == bitwise_cast<Bits>(b);
     }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
 
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint32_t key)
+// pointer identity hash function
+
+template <typename T> struct PtrHash {
+    static unsigned hash(T key)
     {
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
-    }
-
-    // Thomas Wang's 64 bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint64_t key)
-    {
-        key += ~(key << 32);
-        key ^= (key >> 22);
-        key += ~(key << 13);
-        key ^= (key >> 8);
-        key += (key << 3);
-        key ^= (key >> 15);
-        key += ~(key << 27);
-        key ^= (key >> 31);
-        return static_cast<unsigned>(key);
-    }
-
-    // Compound integer hash method: http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
-    inline unsigned pairIntHash(unsigned key1, unsigned key2)
-    {
-        unsigned shortRandom1 = 277951225; // A random 32-bit value.
-        unsigned shortRandom2 = 95187966; // A random 32-bit value.
-        uint64_t longRandom = 19248658165952622LL; // A random 64-bit value.
-
-        uint64_t product = longRandom * (shortRandom1 * key1 + shortRandom2 * key2);
-        unsigned highBits = static_cast<unsigned>(product >> (sizeof(uint64_t) - sizeof(unsigned)));
-        return highBits;
-    }
-
-    template<typename T> struct IntHash {
-        static unsigned hash(T key) { return intHash(static_cast<typename IntTypes<sizeof(T)>::UnsignedType>(key)); }
-        static bool equal(T a, T b) { return a == b; }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-
-    template<typename T> struct FloatHash {
-        typedef typename IntTypes<sizeof(T)>::UnsignedType Bits;
-        static unsigned hash(T key)
-        {
-            return intHash(bitwise_cast<Bits>(key));
-        }
-        static bool equal(T a, T b)
-        {
-            return bitwise_cast<Bits>(a) == bitwise_cast<Bits>(b);
-        }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-
-    // pointer identity hash function
-
-    template<typename T> struct PtrHash {
-        static unsigned hash(T key)
-        {
 #if COMPILER(MSVC)
 #pragma warning(push)
 #pragma warning(disable: 4244) // work around what seems to be a bug in MSVC's conversion warnings
 #endif
-            return IntHash<uintptr_t>::hash(reinterpret_cast<uintptr_t>(key));
+        return IntHash<uintptr_t>::hash(reinterpret_cast<uintptr_t>(key));
 #if COMPILER(MSVC)
 #pragma warning(pop)
 #endif
-        }
-        static bool equal(T a, T b) { return a == b; }
-        static bool equal(std::nullptr_t, T b) { return b == 0; }
-        static bool equal(T a, std::nullptr_t) { return a == 0; }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-    template<typename P> struct PtrHash<RefPtr<P>> : PtrHash<P*> {
-        using PtrHash<P*>::hash;
-        static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
-        static unsigned hash(const PassRefPtr<P>& key) { return hash(key.get()); }
-        using PtrHash<P*>::equal;
-        static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
-        static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
-        static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
-        static bool equal(const RefPtr<P>& a, const PassRefPtr<P>& b) { return a == b; }
-    };
-    template<typename P> struct PtrHash<RawPtr<P>> : PtrHash<P*> {
-        using PtrHash<P*>::hash;
-        static unsigned hash(const RawPtr<P>& key) { return hash(key.get()); }
-        using PtrHash<P*>::equal;
-        static bool equal(const RawPtr<P>& a, const RawPtr<P>& b) { return a == b; }
-        static bool equal(P* a, const RawPtr<P>& b) { return a == b; }
-        static bool equal(const RawPtr<P>& a, P* b) { return a == b; }
-    };
-    template<typename P> struct PtrHash<OwnPtr<P>> : PtrHash<P*> {
-        using PtrHash<P*>::hash;
-        static unsigned hash(const OwnPtr<P>& key) { return hash(key.get()); }
-        static unsigned hash(const PassOwnPtr<P>& key) { return hash(key.get()); }
+    }
+    static bool equal(T a, T b) { return a == b; }
+    static bool equal(std::nullptr_t, T b) { return b == 0; }
+    static bool equal(T a, std::nullptr_t) { return a == 0; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+template <typename P> struct PtrHash<RefPtr<P>> : PtrHash<P*> {
+    using PtrHash<P*>::hash;
+    static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
+    static unsigned hash(const PassRefPtr<P>& key) { return hash(key.get()); }
+    using PtrHash<P*>::equal;
+    static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
+    static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
+    static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
+    static bool equal(const RefPtr<P>& a, const PassRefPtr<P>& b) { return a == b; }
+};
+template <typename P> struct PtrHash<RawPtr<P>> : PtrHash<P*> {
+    using PtrHash<P*>::hash;
+    static unsigned hash(const RawPtr<P>& key) { return hash(key.get()); }
+    using PtrHash<P*>::equal;
+    static bool equal(const RawPtr<P>& a, const RawPtr<P>& b) { return a == b; }
+    static bool equal(P* a, const RawPtr<P>& b) { return a == b; }
+    static bool equal(const RawPtr<P>& a, P* b) { return a == b; }
+};
+template <typename P> struct PtrHash<OwnPtr<P>> : PtrHash<P*> {
+    using PtrHash<P*>::hash;
+    static unsigned hash(const OwnPtr<P>& key) { return hash(key.get()); }
+    static unsigned hash(const PassOwnPtr<P>& key) { return hash(key.get()); }
 
-        static bool equal(const OwnPtr<P>& a, const OwnPtr<P>& b)
-        {
-            return a.get() == b.get();
-        }
-        static bool equal(const OwnPtr<P>& a, P* b) { return a == b; }
-        static bool equal(const OwnPtr<P>& a, const PassOwnPtr<P>& b)
-        {
-            return a.get() == b.get();
-        }
-    };
+    static bool equal(const OwnPtr<P>& a, const OwnPtr<P>& b)
+    {
+        return a.get() == b.get();
+    }
+    static bool equal(const OwnPtr<P>& a, P* b) { return a == b; }
+    static bool equal(const OwnPtr<P>& a, const PassOwnPtr<P>& b)
+    {
+        return a.get() == b.get();
+    }
+};
 
-    // default hash function for each type
+// default hash function for each type
 
-    template<typename T> struct DefaultHash;
+template <typename T> struct DefaultHash;
 
-    template<typename T, typename U> struct PairHash {
-        static unsigned hash(const std::pair<T, U>& p)
-        {
-            return pairIntHash(DefaultHash<T>::Hash::hash(p.first), DefaultHash<U>::Hash::hash(p.second));
-        }
-        static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
-        {
-            return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second);
-        }
-        static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted
-                                                            && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
-    };
+template <typename T, typename U> struct PairHash {
+    static unsigned hash(const std::pair<T, U>& p)
+    {
+        return pairIntHash(DefaultHash<T>::Hash::hash(p.first), DefaultHash<U>::Hash::hash(p.second));
+    }
+    static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
+    {
+        return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second);
+    }
+    static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted
+        && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
+};
 
-    template<typename T, typename U> struct IntPairHash {
-        static unsigned hash(const std::pair<T, U>& p) { return pairIntHash(p.first, p.second); }
-        static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b) { return PairHash<T, T>::equal(a, b); }
-        static const bool safeToCompareToEmptyOrDeleted = PairHash<T, U>::safeToCompareToEmptyOrDeleted;
-    };
+template <typename T, typename U> struct IntPairHash {
+    static unsigned hash(const std::pair<T, U>& p) { return pairIntHash(p.first, p.second); }
+    static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b) { return PairHash<T, T>::equal(a, b); }
+    static const bool safeToCompareToEmptyOrDeleted = PairHash<T, U>::safeToCompareToEmptyOrDeleted;
+};
 
-    // make IntHash the default hash function for many integer types
+// make IntHash the default hash function for many integer types
 
-    template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; };
-    template<> struct DefaultHash<unsigned long> { typedef IntHash<unsigned long> Hash; };
-    template<> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; };
-    template<> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; };
+template <> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
+template <> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; };
+template <> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; };
+template <> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; };
+template <> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; };
+template <> struct DefaultHash<unsigned long> { typedef IntHash<unsigned long> Hash; };
+template <> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; };
+template <> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; };
 
 #if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    template<> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; };
+template <> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; };
 #endif
 
-    template<> struct DefaultHash<float> { typedef FloatHash<float> Hash; };
-    template<> struct DefaultHash<double> { typedef FloatHash<double> Hash; };
+template <> struct DefaultHash<float> { typedef FloatHash<float> Hash; };
+template <> struct DefaultHash<double> { typedef FloatHash<double> Hash; };
 
-    // make PtrHash the default hash function for pointer types that don't specialize
+// make PtrHash the default hash function for pointer types that don't specialize
 
-    template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
-    template<typename P> struct DefaultHash<RefPtr<P>> { typedef PtrHash<RefPtr<P>> Hash; };
-    template<typename P> struct DefaultHash<RawPtr<P>> { typedef PtrHash<RawPtr<P>> Hash; };
-    template<typename P> struct DefaultHash<OwnPtr<P>> { typedef PtrHash<OwnPtr<P>> Hash; };
+template <typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
+template <typename P> struct DefaultHash<RefPtr<P>> { typedef PtrHash<RefPtr<P>> Hash; };
+template <typename P> struct DefaultHash<RawPtr<P>> { typedef PtrHash<RawPtr<P>> Hash; };
+template <typename P> struct DefaultHash<OwnPtr<P>> { typedef PtrHash<OwnPtr<P>> Hash; };
 
-    // make IntPairHash the default hash function for pairs of (at most) 32-bit integers.
+// make IntPairHash the default hash function for pairs of (at most) 32-bit integers.
 
-    template<> struct DefaultHash<std::pair<short, short>> { typedef IntPairHash<short, short> Hash; };
-    template<> struct DefaultHash<std::pair<short, unsigned short>> { typedef IntPairHash<short, unsigned short> Hash; };
-    template<> struct DefaultHash<std::pair<short, int>> { typedef IntPairHash<short, int> Hash; };
-    template<> struct DefaultHash<std::pair<short, unsigned>> { typedef IntPairHash<short, unsigned> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned short, short>> { typedef IntPairHash<unsigned short, short> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned short, unsigned short>> { typedef IntPairHash<unsigned short, unsigned short> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned short, int>> { typedef IntPairHash<unsigned short, int> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned short, unsigned>> { typedef IntPairHash<unsigned short, unsigned> Hash; };
-    template<> struct DefaultHash<std::pair<int, short>> { typedef IntPairHash<int, short> Hash; };
-    template<> struct DefaultHash<std::pair<int, unsigned short>> { typedef IntPairHash<int, unsigned short> Hash; };
-    template<> struct DefaultHash<std::pair<int, int>> { typedef IntPairHash<int, int> Hash; };
-    template<> struct DefaultHash<std::pair<int, unsigned>> { typedef IntPairHash<unsigned, unsigned> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned, short>> { typedef IntPairHash<unsigned, short> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned, unsigned short>> { typedef IntPairHash<unsigned, unsigned short> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned, int>> { typedef IntPairHash<unsigned, int> Hash; };
-    template<> struct DefaultHash<std::pair<unsigned, unsigned>> { typedef IntPairHash<unsigned, unsigned> Hash; };
+template <> struct DefaultHash<std::pair<short, short>> { typedef IntPairHash<short, short> Hash; };
+template <> struct DefaultHash<std::pair<short, unsigned short>> { typedef IntPairHash<short, unsigned short> Hash; };
+template <> struct DefaultHash<std::pair<short, int>> { typedef IntPairHash<short, int> Hash; };
+template <> struct DefaultHash<std::pair<short, unsigned>> { typedef IntPairHash<short, unsigned> Hash; };
+template <> struct DefaultHash<std::pair<unsigned short, short>> { typedef IntPairHash<unsigned short, short> Hash; };
+template <> struct DefaultHash<std::pair<unsigned short, unsigned short>> { typedef IntPairHash<unsigned short, unsigned short> Hash; };
+template <> struct DefaultHash<std::pair<unsigned short, int>> { typedef IntPairHash<unsigned short, int> Hash; };
+template <> struct DefaultHash<std::pair<unsigned short, unsigned>> { typedef IntPairHash<unsigned short, unsigned> Hash; };
+template <> struct DefaultHash<std::pair<int, short>> { typedef IntPairHash<int, short> Hash; };
+template <> struct DefaultHash<std::pair<int, unsigned short>> { typedef IntPairHash<int, unsigned short> Hash; };
+template <> struct DefaultHash<std::pair<int, int>> { typedef IntPairHash<int, int> Hash; };
+template <> struct DefaultHash<std::pair<int, unsigned>> { typedef IntPairHash<unsigned, unsigned> Hash; };
+template <> struct DefaultHash<std::pair<unsigned, short>> { typedef IntPairHash<unsigned, short> Hash; };
+template <> struct DefaultHash<std::pair<unsigned, unsigned short>> { typedef IntPairHash<unsigned, unsigned short> Hash; };
+template <> struct DefaultHash<std::pair<unsigned, int>> { typedef IntPairHash<unsigned, int> Hash; };
+template <> struct DefaultHash<std::pair<unsigned, unsigned>> { typedef IntPairHash<unsigned, unsigned> Hash; };
 
-    // make PairHash the default hash function for pairs of arbitrary values.
+// make PairHash the default hash function for pairs of arbitrary values.
 
-    template<typename T, typename U> struct DefaultHash<std::pair<T, U>> { typedef PairHash<T, U> Hash; };
+template <typename T, typename U> struct DefaultHash<std::pair<T, U>> { typedef PairHash<T, U> Hash; };
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/HashIterators.h b/third_party/WebKit/Source/wtf/HashIterators.h
index df37b2e..e751e9d 100644
--- a/third_party/WebKit/Source/wtf/HashIterators.h
+++ b/third_party/WebKit/Source/wtf/HashIterators.h
@@ -28,190 +28,198 @@
 
 namespace WTF {
 
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator;
+template <typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator;
+template <typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator;
+template <typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator;
+template <typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator;
 
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> {
-    private:
-        typedef KeyValuePair<KeyType, MappedType> ValueType;
-    public:
-        typedef HashTableConstKeysIterator<HashTableType, KeyType, MappedType> Keys;
-        typedef HashTableConstValuesIterator<HashTableType, KeyType, MappedType> Values;
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> {
+private:
+    typedef KeyValuePair<KeyType, MappedType> ValueType;
+public:
+    typedef HashTableConstKeysIterator<HashTableType, KeyType, MappedType> Keys;
+    typedef HashTableConstValuesIterator<HashTableType, KeyType, MappedType> Values;
 
-        HashTableConstIteratorAdapter() {}
-        HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
+    HashTableConstIteratorAdapter() {}
+    HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
 
-        const ValueType* get() const { return (const ValueType*)m_impl.get(); }
-        const ValueType& operator*() const { return *get(); }
-        const ValueType* operator->() const { return get(); }
+    const ValueType* get() const { return (const ValueType*)m_impl.get(); }
+    const ValueType& operator*() const { return *get(); }
+    const ValueType* operator->() const { return get(); }
 
-        HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
+    HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
 
-        Keys keys() { return Keys(*this); }
-        Values values() { return Values(*this); }
+    Keys keys() { return Keys(*this); }
+    Values values() { return Values(*this); }
 
-        typename HashTableType::const_iterator m_impl;
-    };
+    typename HashTableType::const_iterator m_impl;
+};
 
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> {
-    private:
-        typedef KeyValuePair<KeyType, MappedType> ValueType;
-    public:
-        typedef HashTableKeysIterator<HashTableType, KeyType, MappedType> Keys;
-        typedef HashTableValuesIterator<HashTableType, KeyType, MappedType> Values;
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> {
+private:
+    typedef KeyValuePair<KeyType, MappedType> ValueType;
+public:
+    typedef HashTableKeysIterator<HashTableType, KeyType, MappedType> Keys;
+    typedef HashTableValuesIterator<HashTableType, KeyType, MappedType> Values;
 
-        HashTableIteratorAdapter() {}
-        HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
+    HashTableIteratorAdapter() {}
+    HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
 
-        ValueType* get() const { return (ValueType*)m_impl.get(); }
-        ValueType& operator*() const { return *get(); }
-        ValueType* operator->() const { return get(); }
+    ValueType* get() const { return (ValueType*)m_impl.get(); }
+    ValueType& operator*() const { return *get(); }
+    ValueType* operator->() const { return get(); }
 
-        HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
+    HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
 
-        operator HashTableConstIteratorAdapter<HashTableType, ValueType>() {
-            typename HashTableType::const_iterator i = m_impl;
-            return i;
-        }
-
-        Keys keys() { return Keys(*this); }
-        Values values() { return Values(*this); }
-
-        typename HashTableType::iterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator {
-    private:
-        typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
-
-    public:
-        HashTableConstKeysIterator(const ConstIterator& impl) : m_impl(impl) {}
-
-        const KeyType* get() const { return &(m_impl.get()->key); }
-        const KeyType& operator*() const { return *get(); }
-        const KeyType* operator->() const { return get(); }
-
-        HashTableConstKeysIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        ConstIterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator {
-    private:
-        typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
-
-    public:
-        HashTableConstValuesIterator(const ConstIterator& impl) : m_impl(impl) {}
-
-        const MappedType* get() const { return &(m_impl.get()->value); }
-        const MappedType& operator*() const { return *get(); }
-        const MappedType* operator->() const { return get(); }
-
-        HashTableConstValuesIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        ConstIterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator {
-    private:
-        typedef HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> Iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
-
-    public:
-        HashTableKeysIterator(const Iterator& impl) : m_impl(impl) {}
-
-        KeyType* get() const { return &(m_impl.get()->key); }
-        KeyType& operator*() const { return *get(); }
-        KeyType* operator->() const { return get(); }
-
-        HashTableKeysIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstKeysIterator<HashTableType, KeyType, MappedType>() {
-            ConstIterator i = m_impl;
-            return i;
-        }
-
-        Iterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator {
-    private:
-        typedef HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> Iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
-
-    public:
-        HashTableValuesIterator(const Iterator& impl) : m_impl(impl) {}
-
-        MappedType* get() const { return &(m_impl.get()->value); }
-        MappedType& operator*() const { return *get(); }
-        MappedType* operator->() const { return get(); }
-
-        HashTableValuesIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstValuesIterator<HashTableType, KeyType, MappedType>() {
-            ConstIterator i = m_impl;
-            return i;
-        }
-
-        Iterator m_impl;
-    };
-
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
+    operator HashTableConstIteratorAdapter<HashTableType, ValueType>()
     {
-        return a.m_impl == b.m_impl;
+        typename HashTableType::const_iterator i = m_impl;
+        return i;
     }
 
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
+    Keys keys() { return Keys(*this); }
+    Values values() { return Values(*this); }
+
+    typename HashTableType::iterator m_impl;
+};
+
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableConstKeysIterator {
+private:
+    typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
+
+public:
+    HashTableConstKeysIterator(const ConstIterator& impl) : m_impl(impl) {}
+
+    const KeyType* get() const { return &(m_impl.get()->key); }
+    const KeyType& operator*() const { return *get(); }
+    const KeyType* operator->() const { return get(); }
+
+    HashTableConstKeysIterator& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    ConstIterator m_impl;
+};
+
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableConstValuesIterator {
+private:
+    typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
+
+public:
+    HashTableConstValuesIterator(const ConstIterator& impl) : m_impl(impl) {}
+
+    const MappedType* get() const { return &(m_impl.get()->value); }
+    const MappedType& operator*() const { return *get(); }
+    const MappedType* operator->() const { return get(); }
+
+    HashTableConstValuesIterator& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    ConstIterator m_impl;
+};
+
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableKeysIterator {
+private:
+    typedef HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> Iterator;
+    typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
+
+public:
+    HashTableKeysIterator(const Iterator& impl) : m_impl(impl) {}
+
+    KeyType* get() const { return &(m_impl.get()->key); }
+    KeyType& operator*() const { return *get(); }
+    KeyType* operator->() const { return get(); }
+
+    HashTableKeysIterator& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    operator HashTableConstKeysIterator<HashTableType, KeyType, MappedType>()
     {
-        return a.m_impl != b.m_impl;
+        ConstIterator i = m_impl;
+        return i;
     }
 
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
+    Iterator m_impl;
+};
+
+template <typename HashTableType, typename KeyType, typename MappedType>
+struct HashTableValuesIterator {
+private:
+    typedef HashTableIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> Iterator;
+    typedef HashTableConstIteratorAdapter<HashTableType, KeyValuePair<KeyType, MappedType>> ConstIterator;
+
+public:
+    HashTableValuesIterator(const Iterator& impl) : m_impl(impl) {}
+
+    MappedType* get() const { return &(m_impl.get()->value); }
+    MappedType& operator*() const { return *get(); }
+    MappedType* operator->() const { return get(); }
+
+    HashTableValuesIterator& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    operator HashTableConstValuesIterator<HashTableType, KeyType, MappedType>()
     {
-        return a.m_impl == b.m_impl;
+        ConstIterator i = m_impl;
+        return i;
     }
 
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
+    Iterator m_impl;
+};
 
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
+template <typename T, typename U, typename V>
+inline bool operator==(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
+{
+    return a.m_impl == b.m_impl;
+}
 
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
+template <typename T, typename U, typename V>
+inline bool operator!=(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
+{
+    return a.m_impl != b.m_impl;
+}
 
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
+template <typename T, typename U, typename V>
+inline bool operator==(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
+{
+    return a.m_impl == b.m_impl;
+}
 
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
+template <typename T, typename U, typename V>
+inline bool operator!=(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
+{
+    return a.m_impl != b.m_impl;
+}
 
+template <typename T, typename U, typename V>
+inline bool operator==(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U, typename V>
+inline bool operator!=(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
+{
+    return a.m_impl != b.m_impl;
+}
+
+template <typename T, typename U, typename V>
+inline bool operator==(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U, typename V>
+inline bool operator!=(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
+{
+    return a.m_impl != b.m_impl;
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/HashMap.h b/third_party/WebKit/Source/wtf/HashMap.h
index eac2b991..ac75e27 100644
--- a/third_party/WebKit/Source/wtf/HashMap.h
+++ b/third_party/WebKit/Source/wtf/HashMap.h
@@ -26,475 +26,484 @@
 
 namespace WTF {
 
-    template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits;
+template <typename KeyTraits, typename MappedTraits> struct HashMapValueTraits;
 
-    template<typename T> struct ReferenceTypeMaker {
-        typedef T& ReferenceType;
-    };
-    template<typename T> struct ReferenceTypeMaker<T&> {
-        typedef T& ReferenceType;
-    };
+template <typename T> struct ReferenceTypeMaker {
+    typedef T& ReferenceType;
+};
+template <typename T> struct ReferenceTypeMaker<T&> {
+    typedef T& ReferenceType;
+};
 
-    struct KeyValuePairKeyExtractor {
-        template<typename T>
-        static const typename T::KeyType& extract(const T& p) { return p.key; }
-    };
+struct KeyValuePairKeyExtractor {
+    template <typename T>
+    static const typename T::KeyType& extract(const T& p) { return p.key; }
+};
 
-    // Note: empty or deleted key values are not allowed, using them may lead to undefined behavior.
-    // For pointer keys this means that null pointers are not allowed unless you supply custom key traits.
-    template<
-        typename KeyArg,
-        typename MappedArg,
-        typename HashArg = typename DefaultHash<KeyArg>::Hash,
-        typename KeyTraitsArg = HashTraits<KeyArg>,
-        typename MappedTraitsArg = HashTraits<MappedArg>,
-        typename Allocator = DefaultAllocator>
-    class HashMap {
-        WTF_USE_ALLOCATOR(HashMap, Allocator);
-    private:
-        typedef KeyTraitsArg KeyTraits;
-        typedef MappedTraitsArg MappedTraits;
-        typedef HashMapValueTraits<KeyTraits, MappedTraits> ValueTraits;
+// Note: empty or deleted key values are not allowed, using them may lead to
+// undefined behavior.  For pointer keys this means that null pointers are not
+// allowed unless you supply custom key traits.
+template <
+    typename KeyArg,
+    typename MappedArg,
+    typename HashArg = typename DefaultHash<KeyArg>::Hash,
+    typename KeyTraitsArg = HashTraits<KeyArg>,
+    typename MappedTraitsArg = HashTraits<MappedArg>,
+    typename Allocator = DefaultAllocator>
+class HashMap {
+    WTF_USE_ALLOCATOR(HashMap, Allocator);
+private:
+    typedef KeyTraitsArg KeyTraits;
+    typedef MappedTraitsArg MappedTraits;
+    typedef HashMapValueTraits<KeyTraits, MappedTraits> ValueTraits;
 
-    public:
-        typedef typename KeyTraits::TraitType KeyType;
-        typedef const typename KeyTraits::PeekInType& KeyPeekInType;
-        typedef typename MappedTraits::TraitType MappedType;
-        typedef typename ValueTraits::TraitType ValueType;
+public:
+    typedef typename KeyTraits::TraitType KeyType;
+    typedef const typename KeyTraits::PeekInType& KeyPeekInType;
+    typedef typename MappedTraits::TraitType MappedType;
+    typedef typename ValueTraits::TraitType ValueType;
 
-    private:
-        typedef typename MappedTraits::PassInType MappedPassInType;
-        typedef typename MappedTraits::PassOutType MappedPassOutType;
-        typedef typename MappedTraits::PeekOutType MappedPeekType;
+private:
+    typedef typename MappedTraits::PassInType MappedPassInType;
+    typedef typename MappedTraits::PassOutType MappedPassOutType;
+    typedef typename MappedTraits::PeekOutType MappedPeekType;
 
-        typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType;
+    typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType;
 
-        typedef HashArg HashFunctions;
+    typedef HashArg HashFunctions;
 
-        typedef HashTable<KeyType, ValueType, KeyValuePairKeyExtractor,
-            HashFunctions, ValueTraits, KeyTraits, Allocator> HashTableType;
+    typedef HashTable<KeyType, ValueType, KeyValuePairKeyExtractor,
+        HashFunctions, ValueTraits, KeyTraits, Allocator> HashTableType;
 
-        class HashMapKeysProxy;
-        class HashMapValuesProxy;
+    class HashMapKeysProxy;
+    class HashMapValuesProxy;
 
-    public:
-        typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
-        typedef typename HashTableType::AddResult AddResult;
+public:
+    typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
+    typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
+    typedef typename HashTableType::AddResult AddResult;
 
-    public:
-        void swap(HashMap& ref)
-        {
-            m_impl.swap(ref.m_impl);
-        }
-
-        void swap(typename Allocator::template OtherType<HashMap>::Type other)
-        {
-            HashMap& ref = Allocator::getOther(other);
-            m_impl.swap(ref.m_impl);
-        }
-
-        unsigned size() const;
-        unsigned capacity() const;
-        bool isEmpty() const;
-
-        // iterators iterate over pairs of keys and values
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
-
-        HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); }
-        const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); }
-
-        HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); }
-        const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); }
-
-        iterator find(KeyPeekInType);
-        const_iterator find(KeyPeekInType) const;
-        bool contains(KeyPeekInType) const;
-        MappedPeekType get(KeyPeekInType) const;
-
-        // replaces value but not key if key is already present
-        // return value is a pair of the iterator to the key location,
-        // and a boolean that's true if a new value was actually added
-        AddResult set(KeyPeekInType, MappedPassInType);
-
-        // does nothing if key is already present
-        // return value is a pair of the iterator to the key location,
-        // and a boolean that's true if a new value was actually added
-        AddResult add(KeyPeekInType, MappedPassInType);
-
-        void remove(KeyPeekInType);
-        void remove(iterator);
-        void clear();
-        template<typename Collection>
-        void removeAll(const Collection& toBeRemoved) { WTF::removeAll(*this, toBeRemoved); }
-
-        MappedPassOutType take(KeyPeekInType); // efficient combination of get with remove
-
-        // An alternate version of find() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion. HashTranslator
-        // must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        template<typename HashTranslator, typename T> iterator find(const T&);
-        template<typename HashTranslator, typename T> const_iterator find(const T&) const;
-        template<typename HashTranslator, typename T> bool contains(const T&) const;
-
-        // An alternate version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table. HashTranslator must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        //   static translate(ValueType&, const T&, unsigned hashCode);
-        template<typename HashTranslator, typename T> AddResult add(const T&, MappedPassInType);
-
-        static bool isValidKey(KeyPeekInType);
-
-        template<typename VisitorDispatcher>
-        void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
-
-    private:
-        AddResult inlineAdd(KeyPeekInType, MappedPassInReferenceType);
-
-        HashTableType m_impl;
-    };
-
-    template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
-    class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapKeysProxy :
-        private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
-        public:
-            typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
-            typedef typename HashMapType::iterator::Keys iterator;
-            typedef typename HashMapType::const_iterator::Keys const_iterator;
-
-            iterator begin()
-            {
-                return HashMapType::begin().keys();
-            }
-
-            iterator end()
-            {
-                return HashMapType::end().keys();
-            }
-
-            const_iterator begin() const
-            {
-                return HashMapType::begin().keys();
-            }
-
-            const_iterator end() const
-            {
-                return HashMapType::end().keys();
-            }
-
-        private:
-            friend class HashMap;
-
-            // These are intentionally not implemented.
-            HashMapKeysProxy();
-            HashMapKeysProxy(const HashMapKeysProxy&);
-            HashMapKeysProxy& operator=(const HashMapKeysProxy&);
-            ~HashMapKeysProxy();
-    };
-
-    template<typename KeyArg, typename MappedArg, typename HashArg,  typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
-    class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapValuesProxy :
-        private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
-        public:
-            typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
-            typedef typename HashMapType::iterator::Values iterator;
-            typedef typename HashMapType::const_iterator::Values const_iterator;
-
-            iterator begin()
-            {
-                return HashMapType::begin().values();
-            }
-
-            iterator end()
-            {
-                return HashMapType::end().values();
-            }
-
-            const_iterator begin() const
-            {
-                return HashMapType::begin().values();
-            }
-
-            const_iterator end() const
-            {
-                return HashMapType::end().values();
-            }
-
-        private:
-            friend class HashMap;
-
-            // These are intentionally not implemented.
-            HashMapValuesProxy();
-            HashMapValuesProxy(const HashMapValuesProxy&);
-            HashMapValuesProxy& operator=(const HashMapValuesProxy&);
-            ~HashMapValuesProxy();
-    };
-
-    template<typename KeyTraits, typename MappedTraits> struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
-        static const bool hasIsEmptyValueFunction = true;
-        static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
-        {
-            return isHashTraitsEmptyValue<KeyTraits>(value.key);
-        }
-    };
-
-    template<typename ValueTraits, typename HashFunctions>
-    struct HashMapTranslator {
-        template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
-        template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped)
-        {
-            location.key = key;
-            ValueTraits::ValueTraits::store(mapped, location.value);
-        }
-    };
-
-    template<typename ValueTraits, typename Translator>
-    struct HashMapTranslatorAdapter {
-        template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
-        template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode)
-        {
-            Translator::translate(location.key, key, hashCode);
-            ValueTraits::ValueTraits::store(mapped, location.value);
-        }
-    };
-
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline unsigned HashMap<T, U, V, W, X, Y>::size() const
+public:
+    void swap(HashMap& ref)
     {
-        return m_impl.size();
+        m_impl.swap(ref.m_impl);
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline unsigned HashMap<T, U, V, W, X, Y>::capacity() const
+    void swap(typename Allocator::template OtherType<HashMap>::Type other)
     {
-        return m_impl.capacity();
+        HashMap& ref = Allocator::getOther(other);
+        m_impl.swap(ref.m_impl);
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline bool HashMap<T, U, V, W, X, Y>::isEmpty() const
+    unsigned size() const;
+    unsigned capacity() const;
+    void reserveCapacityForSize(unsigned size)
     {
-        return m_impl.isEmpty();
+        m_impl.reserveCapacityForSize(size);
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::begin()
+    bool isEmpty() const;
+
+    // iterators iterate over pairs of keys and values
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); }
+    const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); }
+
+    HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); }
+    const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); }
+
+    iterator find(KeyPeekInType);
+    const_iterator find(KeyPeekInType) const;
+    bool contains(KeyPeekInType) const;
+    MappedPeekType get(KeyPeekInType) const;
+
+    // replaces value but not key if key is already present return value is a
+    // pair of the iterator to the key location, and a boolean that's true if a
+    // new value was actually added
+    AddResult set(KeyPeekInType, MappedPassInType);
+
+    // does nothing if key is already present return value is a pair of the
+    // iterator to the key location, and a boolean that's true if a new value
+    // was actually added
+    AddResult add(KeyPeekInType, MappedPassInType);
+
+    void remove(KeyPeekInType);
+    void remove(iterator);
+    void clear();
+    template <typename Collection>
+    void removeAll(const Collection& toBeRemoved) { WTF::removeAll(*this, toBeRemoved); }
+
+    MappedPassOutType take(KeyPeekInType); // efficient combination of get with remove
+
+    // An alternate version of find() that finds the object by hashing and
+    // comparing with some other type, to avoid the cost of type
+    // conversion. HashTranslator must have the following function members:
+    //   static unsigned hash(const T&);
+    //   static bool equal(const ValueType&, const T&);
+    template <typename HashTranslator, typename T> iterator find(const T&);
+    template <typename HashTranslator, typename T> const_iterator find(const T&) const;
+    template <typename HashTranslator, typename T> bool contains(const T&) const;
+
+    // An alternate version of add() that finds the object by hashing and
+    // comparing with some other type, to avoid the cost of type conversion if
+    // the object is already in the table. HashTranslator must have the
+    // following function members:
+    //   static unsigned hash(const T&);
+    //   static bool equal(const ValueType&, const T&);
+    //   static translate(ValueType&, const T&, unsigned hashCode);
+    template <typename HashTranslator, typename T> AddResult add(const T&, MappedPassInType);
+
+    static bool isValidKey(KeyPeekInType);
+
+    template <typename VisitorDispatcher>
+    void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
+
+private:
+    AddResult inlineAdd(KeyPeekInType, MappedPassInReferenceType);
+
+    HashTableType m_impl;
+};
+
+template <typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
+class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapKeysProxy :
+    private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
+public:
+    typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
+    typedef typename HashMapType::iterator::Keys iterator;
+    typedef typename HashMapType::const_iterator::Keys const_iterator;
+
+    iterator begin()
     {
-        return m_impl.begin();
+        return HashMapType::begin().keys();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::end()
+    iterator end()
     {
-        return m_impl.end();
+        return HashMapType::end().keys();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::begin() const
+    const_iterator begin() const
     {
-        return m_impl.begin();
+        return HashMapType::begin().keys();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::end() const
+    const_iterator end() const
     {
-        return m_impl.end();
+        return HashMapType::end().keys();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key)
+private:
+    friend class HashMap;
+
+    // These are intentionally not implemented.
+    HashMapKeysProxy();
+    HashMapKeysProxy(const HashMapKeysProxy&);
+    HashMapKeysProxy& operator=(const HashMapKeysProxy&);
+    ~HashMapKeysProxy();
+};
+
+template <typename KeyArg, typename MappedArg, typename HashArg,  typename KeyTraitsArg, typename MappedTraitsArg, typename Allocator>
+class HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator>::HashMapValuesProxy :
+    private HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> {
+public:
+    typedef HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg, Allocator> HashMapType;
+    typedef typename HashMapType::iterator::Values iterator;
+    typedef typename HashMapType::const_iterator::Values const_iterator;
+
+    iterator begin()
     {
-        return m_impl.find(key);
+        return HashMapType::begin().values();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key) const
+    iterator end()
     {
-        return m_impl.find(key);
+        return HashMapType::end().values();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline bool HashMap<T, U, V, W, X, Y>::contains(KeyPeekInType key) const
+    const_iterator begin() const
     {
-        return m_impl.contains(key);
+        return HashMapType::begin().values();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    template<typename HashTranslator, typename TYPE>
-    inline typename HashMap<T, U, V, W, X, Y>::iterator
-    HashMap<T, U, V, W, X, Y>::find(const TYPE& value)
+    const_iterator end() const
     {
-        return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
+        return HashMapType::end().values();
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    template<typename HashTranslator, typename TYPE>
-    inline typename HashMap<T, U, V, W, X, Y>::const_iterator
-    HashMap<T, U, V, W, X, Y>::find(const TYPE& value) const
-    {
-        return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
-    }
+private:
+    friend class HashMap;
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    template<typename HashTranslator, typename TYPE>
-    inline bool
-    HashMap<T, U, V, W, X, Y>::contains(const TYPE& value) const
-    {
-        return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
-    }
+    // These are intentionally not implemented.
+    HashMapValuesProxy();
+    HashMapValuesProxy(const HashMapValuesProxy&);
+    HashMapValuesProxy& operator=(const HashMapValuesProxy&);
+    ~HashMapValuesProxy();
+};
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    typename HashMap<T, U, V, W, X, Y>::AddResult
-    HashMap<T, U, V, W, X, Y>::inlineAdd(KeyPeekInType key, MappedPassInReferenceType mapped)
+template <typename KeyTraits, typename MappedTraits>
+struct HashMapValueTraits : KeyValuePairHashTraits<KeyTraits, MappedTraits> {
+    static const bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const typename KeyValuePairHashTraits<KeyTraits, MappedTraits>::TraitType& value)
     {
-        return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions>>(key, mapped);
+        return isHashTraitsEmptyValue<KeyTraits>(value.key);
     }
+};
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    typename HashMap<T, U, V, W, X, Y>::AddResult
-    HashMap<T, U, V, W, X, Y>::set(KeyPeekInType key, MappedPassInType mapped)
+template <typename ValueTraits, typename HashFunctions>
+struct HashMapTranslator {
+    template <typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
+    template <typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped)
     {
-        AddResult result = inlineAdd(key, mapped);
-        if (!result.isNewEntry) {
-            // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
-            MappedTraits::store(mapped, result.storedValue->value);
-        }
-        return result;
+        location.key = key;
+        ValueTraits::ValueTraits::store(mapped, location.value);
     }
+};
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    template<typename HashTranslator, typename TYPE>
-    typename HashMap<T, U, V, W, X, Y>::AddResult
-    HashMap<T, U, V, W, X, Y>::add(const TYPE& key, MappedPassInType value)
+template <typename ValueTraits, typename Translator>
+struct HashMapTranslatorAdapter {
+    template <typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
+    template <typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode)
     {
-        return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(key, value);
+        Translator::translate(location.key, key, hashCode);
+        ValueTraits::ValueTraits::store(mapped, location.value);
     }
+};
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    typename HashMap<T, U, V, W, X, Y>::AddResult
-    HashMap<T, U, V, W, X, Y>::add(KeyPeekInType key, MappedPassInType mapped)
-    {
-        return inlineAdd(key, mapped);
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline unsigned HashMap<T, U, V, W, X, Y>::size() const
+{
+    return m_impl.size();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline unsigned HashMap<T, U, V, W, X, Y>::capacity() const
+{
+    return m_impl.capacity();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline bool HashMap<T, U, V, W, X, Y>::isEmpty() const
+{
+    return m_impl.isEmpty();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::begin()
+{
+    return m_impl.begin();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::end()
+{
+    return m_impl.end();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::begin() const
+{
+    return m_impl.begin();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::end() const
+{
+    return m_impl.end();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key)
+{
+    return m_impl.find(key);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline typename HashMap<T, U, V, W, X, Y>::const_iterator HashMap<T, U, V, W, X, Y>::find(KeyPeekInType key) const
+{
+    return m_impl.find(key);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline bool HashMap<T, U, V, W, X, Y>::contains(KeyPeekInType key) const
+{
+    return m_impl.contains(key);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+template <typename HashTranslator, typename TYPE>
+inline typename HashMap<T, U, V, W, X, Y>::iterator
+HashMap<T, U, V, W, X, Y>::find(const TYPE& value)
+{
+    return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+template <typename HashTranslator, typename TYPE>
+inline typename HashMap<T, U, V, W, X, Y>::const_iterator
+HashMap<T, U, V, W, X, Y>::find(const TYPE& value) const
+{
+    return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+template <typename HashTranslator, typename TYPE>
+inline bool
+HashMap<T, U, V, W, X, Y>::contains(const TYPE& value) const
+{
+    return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+typename HashMap<T, U, V, W, X, Y>::AddResult
+HashMap<T, U, V, W, X, Y>::inlineAdd(KeyPeekInType key, MappedPassInReferenceType mapped)
+{
+    return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions>>(key, mapped);
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+typename HashMap<T, U, V, W, X, Y>::AddResult
+HashMap<T, U, V, W, X, Y>::set(KeyPeekInType key, MappedPassInType mapped)
+{
+    AddResult result = inlineAdd(key, mapped);
+    if (!result.isNewEntry) {
+        // The inlineAdd call above found an existing hash table entry; we need
+        // to set the mapped value.
+        MappedTraits::store(mapped, result.storedValue->value);
     }
+    return result;
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    typename HashMap<T, U, V, W, X, Y>::MappedPeekType
-    HashMap<T, U, V, W, X, Y>::get(KeyPeekInType key) const
-    {
-        ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
-        if (!entry)
-            return MappedTraits::peek(MappedTraits::emptyValue());
-        return MappedTraits::peek(entry->value);
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+template <typename HashTranslator, typename TYPE>
+typename HashMap<T, U, V, W, X, Y>::AddResult
+HashMap<T, U, V, W, X, Y>::add(const TYPE& key, MappedPassInType value)
+{
+    return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(key, value);
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline void HashMap<T, U, V, W, X, Y>::remove(iterator it)
-    {
-        m_impl.remove(it.m_impl);
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+typename HashMap<T, U, V, W, X, Y>::AddResult
+HashMap<T, U, V, W, X, Y>::add(KeyPeekInType key, MappedPassInType mapped)
+{
+    return inlineAdd(key, mapped);
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline void HashMap<T, U, V, W, X, Y>::remove(KeyPeekInType key)
-    {
-        remove(find(key));
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+typename HashMap<T, U, V, W, X, Y>::MappedPeekType
+HashMap<T, U, V, W, X, Y>::get(KeyPeekInType key) const
+{
+    ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
+    if (!entry)
+        return MappedTraits::peek(MappedTraits::emptyValue());
+    return MappedTraits::peek(entry->value);
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline void HashMap<T, U, V, W, X, Y>::clear()
-    {
-        m_impl.clear();
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline void HashMap<T, U, V, W, X, Y>::remove(iterator it)
+{
+    m_impl.remove(it.m_impl);
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    typename HashMap<T, U, V, W, X, Y>::MappedPassOutType
-    HashMap<T, U, V, W, X, Y>::take(KeyPeekInType key)
-    {
-        iterator it = find(key);
-        if (it == end())
-            return MappedTraits::passOut(MappedTraits::emptyValue());
-        MappedPassOutType result = MappedTraits::passOut(it->value);
-        remove(it);
-        return result;
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline void HashMap<T, U, V, W, X, Y>::remove(KeyPeekInType key)
+{
+    remove(find(key));
+}
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline bool HashMap<T, U, V, W, X, Y>::isValidKey(KeyPeekInType key)
-    {
-        if (KeyTraits::isDeletedValue(key))
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline void HashMap<T, U, V, W, X, Y>::clear()
+{
+    m_impl.clear();
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+typename HashMap<T, U, V, W, X, Y>::MappedPassOutType
+HashMap<T, U, V, W, X, Y>::take(KeyPeekInType key)
+{
+    iterator it = find(key);
+    if (it == end())
+        return MappedTraits::passOut(MappedTraits::emptyValue());
+    MappedPassOutType result = MappedTraits::passOut(it->value);
+    remove(it);
+    return result;
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline bool HashMap<T, U, V, W, X, Y>::isValidKey(KeyPeekInType key)
+{
+    if (KeyTraits::isDeletedValue(key))
+        return false;
+
+    if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+        if (key == KeyTraits::emptyValue())
             return false;
-
-        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-            if (key == KeyTraits::emptyValue())
-                return false;
-        } else {
-            if (isHashTraitsEmptyValue<KeyTraits>(key))
-                return false;
-        }
-
-        return true;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    bool operator==(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
-    {
-        if (a.size() != b.size())
+    } else {
+        if (isHashTraitsEmptyValue<KeyTraits>(key))
             return false;
-
-        typedef typename HashMap<T, U, V, W, X, Y>::const_iterator const_iterator;
-
-        const_iterator aEnd = a.end();
-        const_iterator bEnd = b.end();
-        for (const_iterator it = a.begin(); it != aEnd; ++it) {
-            const_iterator bPos = b.find(it->key);
-            if (bPos == bEnd || it->value != bPos->value)
-                return false;
-        }
-
-        return true;
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline bool operator!=(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
-    {
-        return !(a == b);
+    return true;
+}
+
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+bool operator==(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
+{
+    if (a.size() != b.size())
+        return false;
+
+    typedef typename HashMap<T, U, V, W, X, Y>::const_iterator const_iterator;
+
+    const_iterator aEnd = a.end();
+    const_iterator bEnd = b.end();
+    for (const_iterator it = a.begin(); it != aEnd; ++it) {
+        const_iterator bPos = b.find(it->key);
+        if (bPos == bEnd || it->value != bPos->value)
+            return false;
     }
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
-    inline void copyKeysToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
-    {
-        typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Keys iterator;
+    return true;
+}
 
-        vector.resize(collection.size());
+template <typename T, typename U, typename V, typename W, typename X, typename Y>
+inline bool operator!=(const HashMap<T, U, V, W, X, Y>& a, const HashMap<T, U, V, W, X, Y>& b)
+{
+    return !(a == b);
+}
 
-        iterator it = collection.begin().keys();
-        iterator end = collection.end().keys();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
+inline void copyKeysToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
+{
+    typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Keys iterator;
 
-    template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
-    inline void copyValuesToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
-    {
-        typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Values iterator;
+    vector.resize(collection.size());
 
-        vector.resize(collection.size());
+    iterator it = collection.begin().keys();
+    iterator end = collection.end().keys();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        vector[i] = *it;
+}
 
-        iterator it = collection.begin().values();
-        iterator end = collection.end().values();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }
+template <typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
+inline void copyValuesToVector(const HashMap<T, U, V, W, X, Y>& collection, Z& vector)
+{
+    typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::Values iterator;
+
+    vector.resize(collection.size());
+
+    iterator it = collection.begin().values();
+    iterator end = collection.end().values();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        vector[i] = *it;
+}
 
 #if !ENABLE(OILPAN)
-template<typename T, typename U, typename V, typename W, typename X>
+template <typename T, typename U, typename V, typename W, typename X>
 struct NeedsTracing<HashMap<T, U, V, W, X>> {
     static const bool value = false;
 };
@@ -504,4 +513,4 @@
 
 using WTF::HashMap;
 
-#endif /* WTF_HashMap_h */
+#endif // WTF_HashMap_h
diff --git a/third_party/WebKit/Source/wtf/HashSet.h b/third_party/WebKit/Source/wtf/HashSet.h
index b8960331..5724968 100644
--- a/third_party/WebKit/Source/wtf/HashSet.h
+++ b/third_party/WebKit/Source/wtf/HashSet.h
@@ -26,267 +26,270 @@
 
 namespace WTF {
 
-    struct IdentityExtractor;
+struct IdentityExtractor;
 
-    // Note: empty or deleted values are not allowed, using them may lead to undefined behavior.
-    // For pointer valuess this means that null pointers are not allowed unless you supply custom traits.
-    template<
-        typename ValueArg,
-        typename HashArg = typename DefaultHash<ValueArg>::Hash,
-        typename TraitsArg = HashTraits<ValueArg>,
-        typename Allocator = DefaultAllocator> class HashSet {
-        WTF_USE_ALLOCATOR(HashSet, Allocator);
-    private:
-        typedef HashArg HashFunctions;
-        typedef TraitsArg ValueTraits;
-        typedef typename ValueTraits::PeekInType ValuePeekInType;
-        typedef typename ValueTraits::PassInType ValuePassInType;
-        typedef typename ValueTraits::PassOutType ValuePassOutType;
+// Note: empty or deleted values are not allowed, using them may lead to
+// undefined behavior.  For pointer valuess this means that null pointers are
+// not allowed unless you supply custom traits.
+template <
+    typename ValueArg,
+    typename HashArg = typename DefaultHash<ValueArg>::Hash,
+    typename TraitsArg = HashTraits<ValueArg>,
+    typename Allocator = DefaultAllocator>
+class HashSet {
+    WTF_USE_ALLOCATOR(HashSet, Allocator);
+private:
+    typedef HashArg HashFunctions;
+    typedef TraitsArg ValueTraits;
+    typedef typename ValueTraits::PeekInType ValuePeekInType;
+    typedef typename ValueTraits::PassInType ValuePassInType;
+    typedef typename ValueTraits::PassOutType ValuePassOutType;
 
-    public:
-        typedef typename ValueTraits::TraitType ValueType;
+public:
+    typedef typename ValueTraits::TraitType ValueType;
 
-    private:
-        typedef HashTable<ValueType, ValueType, IdentityExtractor,
-            HashFunctions, ValueTraits, ValueTraits, Allocator> HashTableType;
+private:
+    typedef HashTable<ValueType, ValueType, IdentityExtractor,
+        HashFunctions, ValueTraits, ValueTraits, Allocator> HashTableType;
 
-    public:
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> const_iterator;
-        typedef typename HashTableType::AddResult AddResult;
+public:
+    typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> iterator;
+    typedef HashTableConstIteratorAdapter<HashTableType, ValueTraits> const_iterator;
+    typedef typename HashTableType::AddResult AddResult;
 
-        void swap(HashSet& ref)
-        {
-            m_impl.swap(ref.m_impl);
-        }
-
-        void swap(typename Allocator::template OtherType<HashSet>::Type other)
-        {
-            HashSet& ref = Allocator::getOther(other);
-            m_impl.swap(ref.m_impl);
-        }
-
-        unsigned size() const;
-        unsigned capacity() const;
-        bool isEmpty() const;
-
-        void reserveCapacityForSize(unsigned size)
-        {
-            m_impl.reserveCapacityForSize(size);
-        }
-
-        iterator begin() const;
-        iterator end() const;
-
-        iterator find(ValuePeekInType) const;
-        bool contains(ValuePeekInType) const;
-
-        // An alternate version of find() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion. HashTranslator
-        // must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        template<typename HashTranslator, typename T> iterator find(const T&) const;
-        template<typename HashTranslator, typename T> bool contains(const T&) const;
-
-        // The return value is a pair of an iterator to the new value's location,
-        // and a bool that is true if an new entry was added.
-        AddResult add(ValuePassInType);
-
-        // An alternate version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table. HashTranslator must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        //   static translate(ValueType&, const T&, unsigned hashCode);
-        template<typename HashTranslator, typename T> AddResult add(const T&);
-
-        void remove(ValuePeekInType);
-        void remove(iterator);
-        void clear();
-        template<typename Collection>
-        void removeAll(const Collection& toBeRemoved) { WTF::removeAll(*this, toBeRemoved); }
-
-        static bool isValidValue(ValuePeekInType);
-
-        ValuePassOutType take(iterator);
-        ValuePassOutType take(ValuePeekInType);
-        ValuePassOutType takeAny();
-
-        template<typename VisitorDispatcher>
-        void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
-
-    private:
-        HashTableType m_impl;
-    };
-
-    struct IdentityExtractor {
-        template<typename T>
-        static const T& extract(const T& t) { return t; }
-    };
-
-    template<typename Translator>
-    struct HashSetTranslatorAdapter {
-        template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
-        template<typename T, typename U> static void translate(T& location, const U& key, const U&, unsigned hashCode)
-        {
-            Translator::translate(location, key, hashCode);
-        }
-    };
-
-    template<typename T, typename U, typename V, typename W>
-    inline unsigned HashSet<T, U, V, W>::size() const
+    void swap(HashSet& ref)
     {
-        return m_impl.size();
+        m_impl.swap(ref.m_impl);
     }
 
-    template<typename T, typename U, typename V, typename W>
-    inline unsigned HashSet<T, U, V, W>::capacity() const
+    void swap(typename Allocator::template OtherType<HashSet>::Type other)
     {
-        return m_impl.capacity();
+        HashSet& ref = Allocator::getOther(other);
+        m_impl.swap(ref.m_impl);
     }
 
-    template<typename T, typename U, typename V, typename W>
-    inline bool HashSet<T, U, V, W>::isEmpty() const
+    unsigned size() const;
+    unsigned capacity() const;
+    bool isEmpty() const;
+
+    void reserveCapacityForSize(unsigned size)
     {
-        return m_impl.isEmpty();
+        m_impl.reserveCapacityForSize(size);
     }
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::begin() const
-    {
-        return m_impl.begin();
-    }
+    iterator begin() const;
+    iterator end() const;
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::end() const
-    {
-        return m_impl.end();
-    }
+    iterator find(ValuePeekInType) const;
+    bool contains(ValuePeekInType) const;
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::find(ValuePeekInType value) const
-    {
-        return m_impl.find(value);
-    }
+    // An alternate version of find() that finds the object by hashing and
+    // comparing with some other type, to avoid the cost of type
+    // conversion. HashTranslator must have the following function members:
+    //   static unsigned hash(const T&);
+    //   static bool equal(const ValueType&, const T&);
+    template <typename HashTranslator, typename T> iterator find(const T&) const;
+    template <typename HashTranslator, typename T> bool contains(const T&) const;
 
-    template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
-    inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(ValuePeekInType value) const
-    {
-        return m_impl.contains(value);
-    }
+    // The return value is a pair of an iterator to the new value's location,
+    // and a bool that is true if an new entry was added.
+    AddResult add(ValuePassInType);
 
-    template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    typename HashSet<Value, HashFunctions, Traits, Allocator>::iterator
-    inline HashSet<Value, HashFunctions, Traits, Allocator>::find(const T& value) const
-    {
-        return m_impl.template find<HashSetTranslatorAdapter<HashTranslator>>(value);
-    }
+    // An alternate version of add() that finds the object by hashing and
+    // comparing with some other type, to avoid the cost of type conversion if
+    // the object is already in the table. HashTranslator must have the
+    // following function members:
+    //   static unsigned hash(const T&);
+    //   static bool equal(const ValueType&, const T&);
+    //   static translate(ValueType&, const T&, unsigned hashCode);
+    template <typename HashTranslator, typename T> AddResult add(const T&);
 
-    template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(const T& value) const
-    {
-        return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator>>(value);
-    }
+    void remove(ValuePeekInType);
+    void remove(iterator);
+    void clear();
+    template <typename Collection>
+    void removeAll(const Collection& toBeRemoved) { WTF::removeAll(*this, toBeRemoved); }
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::add(ValuePassInType value)
-    {
-        return m_impl.add(value);
-    }
+    static bool isValidValue(ValuePeekInType);
 
-    template<typename Value, typename HashFunctions, typename Traits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline typename HashSet<Value, HashFunctions, Traits, Allocator>::AddResult
-    HashSet<Value, HashFunctions, Traits, Allocator>::add(const T& value)
-    {
-        return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator>>(value, value);
-    }
+    ValuePassOutType take(iterator);
+    ValuePassOutType take(ValuePeekInType);
+    ValuePassOutType takeAny();
 
-    template<typename T, typename U, typename V, typename W>
-    inline void HashSet<T, U, V, W>::remove(iterator it)
-    {
-        m_impl.remove(it.m_impl);
-    }
+    template <typename VisitorDispatcher>
+    void trace(VisitorDispatcher visitor) { m_impl.trace(visitor); }
 
-    template<typename T, typename U, typename V, typename W>
-    inline void HashSet<T, U, V, W>::remove(ValuePeekInType value)
-    {
-        remove(find(value));
-    }
+private:
+    HashTableType m_impl;
+};
 
-    template<typename T, typename U, typename V, typename W>
-    inline void HashSet<T, U, V, W>::clear()
-    {
-        m_impl.clear();
-    }
+struct IdentityExtractor {
+    template <typename T>
+    static const T& extract(const T& t) { return t; }
+};
 
-    template<typename T, typename U, typename V, typename W>
-    inline bool HashSet<T, U, V, W>::isValidValue(ValuePeekInType value)
+template <typename Translator>
+struct HashSetTranslatorAdapter {
+    template <typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); }
+    template <typename T, typename U> static void translate(T& location, const U& key, const U&, unsigned hashCode)
     {
-        if (ValueTraits::isDeletedValue(value))
+        Translator::translate(location, key, hashCode);
+    }
+};
+
+template <typename T, typename U, typename V, typename W>
+inline unsigned HashSet<T, U, V, W>::size() const
+{
+    return m_impl.size();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline unsigned HashSet<T, U, V, W>::capacity() const
+{
+    return m_impl.capacity();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline bool HashSet<T, U, V, W>::isEmpty() const
+{
+    return m_impl.isEmpty();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::begin() const
+{
+    return m_impl.begin();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::end() const
+{
+    return m_impl.end();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::iterator HashSet<T, U, V, W>::find(ValuePeekInType value) const
+{
+    return m_impl.find(value);
+}
+
+template <typename Value, typename HashFunctions, typename Traits, typename Allocator>
+inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(ValuePeekInType value) const
+{
+    return m_impl.contains(value);
+}
+
+template <typename Value, typename HashFunctions, typename Traits, typename Allocator>
+template <typename HashTranslator, typename T>
+typename HashSet<Value, HashFunctions, Traits, Allocator>::iterator
+inline HashSet<Value, HashFunctions, Traits, Allocator>::find(const T& value) const
+{
+    return m_impl.template find<HashSetTranslatorAdapter<HashTranslator>>(value);
+}
+
+template <typename Value, typename HashFunctions, typename Traits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline bool HashSet<Value, HashFunctions, Traits, Allocator>::contains(const T& value) const
+{
+    return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator>>(value);
+}
+
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::AddResult HashSet<T, U, V, W>::add(ValuePassInType value)
+{
+    return m_impl.add(value);
+}
+
+template <typename Value, typename HashFunctions, typename Traits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline typename HashSet<Value, HashFunctions, Traits, Allocator>::AddResult
+HashSet<Value, HashFunctions, Traits, Allocator>::add(const T& value)
+{
+    return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator>>(value, value);
+}
+
+template <typename T, typename U, typename V, typename W>
+inline void HashSet<T, U, V, W>::remove(iterator it)
+{
+    m_impl.remove(it.m_impl);
+}
+
+template <typename T, typename U, typename V, typename W>
+inline void HashSet<T, U, V, W>::remove(ValuePeekInType value)
+{
+    remove(find(value));
+}
+
+template <typename T, typename U, typename V, typename W>
+inline void HashSet<T, U, V, W>::clear()
+{
+    m_impl.clear();
+}
+
+template <typename T, typename U, typename V, typename W>
+inline bool HashSet<T, U, V, W>::isValidValue(ValuePeekInType value)
+{
+    if (ValueTraits::isDeletedValue(value))
+        return false;
+
+    if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+        if (value == ValueTraits::emptyValue())
             return false;
-
-        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-            if (value == ValueTraits::emptyValue())
-                return false;
-        } else {
-            if (isHashTraitsEmptyValue<ValueTraits>(value))
-                return false;
-        }
-
-        return true;
+    } else {
+        if (isHashTraitsEmptyValue<ValueTraits>(value))
+            return false;
     }
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(iterator it)
-    {
-        if (it == end())
-            return ValueTraits::emptyValue();
+    return true;
+}
 
-        ValuePassOutType result = ValueTraits::passOut(const_cast<ValueType&>(*it));
-        remove(it);
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(iterator it)
+{
+    if (it == end())
+        return ValueTraits::emptyValue();
 
-        return result;
-    }
+    ValuePassOutType result = ValueTraits::passOut(const_cast<ValueType&>(*it));
+    remove(it);
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(ValuePeekInType value)
-    {
-        return take(find(value));
-    }
+    return result;
+}
 
-    template<typename T, typename U, typename V, typename W>
-    inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::takeAny()
-    {
-        return take(begin());
-    }
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::take(ValuePeekInType value)
+{
+    return take(find(value));
+}
 
-    template<typename C, typename W>
-    inline void copyToVector(const C& collection, W& vector)
-    {
-        typedef typename C::const_iterator iterator;
+template <typename T, typename U, typename V, typename W>
+inline typename HashSet<T, U, V, W>::ValuePassOutType HashSet<T, U, V, W>::takeAny()
+{
+    return take(begin());
+}
 
-        vector.resize(collection.size());
+template <typename C, typename W>
+inline void copyToVector(const C& collection, W& vector)
+{
+    typedef typename C::const_iterator iterator;
 
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }
+    vector.resize(collection.size());
+
+    iterator it = collection.begin();
+    iterator end = collection.end();
+    for (unsigned i = 0; it != end; ++it, ++i)
+        vector[i] = *it;
+}
 
 #if !ENABLE(OILPAN)
-    template<typename T, typename U, typename V>
-    struct NeedsTracing<HashSet<T, U, V>> {
-        static const bool value = false;
-    };
+template <typename T, typename U, typename V>
+struct NeedsTracing<HashSet<T, U, V>> {
+    static const bool value = false;
+};
 #endif
 
 } // namespace WTF
 
 using WTF::HashSet;
 
-#endif /* WTF_HashSet_h */
+#endif // WTF_HashSet_h
diff --git a/third_party/WebKit/Source/wtf/HashTable.cpp b/third_party/WebKit/Source/wtf/HashTable.cpp
index cf9d48d..a233650 100644
--- a/third_party/WebKit/Source/wtf/HashTable.cpp
+++ b/third_party/WebKit/Source/wtf/HashTable.cpp
@@ -18,8 +18,9 @@
 */
 
 #include "config.h"
-#include "HashTable.h"
-#include "DataLog.h"
+#include "wtf/HashTable.h"
+
+#include "wtf/DataLog.h"
 
 namespace WTF {
 
diff --git a/third_party/WebKit/Source/wtf/HashTable.h b/third_party/WebKit/Source/wtf/HashTable.h
index 75dc8a90..ff7731e 100644
--- a/third_party/WebKit/Source/wtf/HashTable.h
+++ b/third_party/WebKit/Source/wtf/HashTable.h
@@ -71,1402 +71,1399 @@
 
 #if DUMP_HASHTABLE_STATS
 
-    struct HashTableStats {
-        // The following variables are all atomically incremented when modified.
-        static int numAccesses;
-        static int numRehashes;
-        static int numRemoves;
-        static int numReinserts;
+struct HashTableStats {
+    // The following variables are all atomically incremented when modified.
+    static int numAccesses;
+    static int numRehashes;
+    static int numRemoves;
+    static int numReinserts;
 
-        // The following variables are only modified in the recordCollisionAtCount method within a mutex.
-        static int maxCollisions;
-        static int numCollisions;
-        static int collisionGraph[4096];
+    // The following variables are only modified in the recordCollisionAtCount
+    // method within a mutex.
+    static int maxCollisions;
+    static int numCollisions;
+    static int collisionGraph[4096];
 
-        static void recordCollisionAtCount(int count);
-        static void dumpStats();
-    };
+    static void recordCollisionAtCount(int count);
+    static void dumpStats();
+};
 
 #endif
 
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTable;
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTableIterator;
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTableConstIterator;
-    template<typename Value, typename HashFunctions, typename HashTraits, typename Allocator>
-    class LinkedHashSet;
-    template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
-    struct WeakProcessingHashTableHelper;
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTable;
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTableIterator;
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTableConstIterator;
+template <typename Value, typename HashFunctions, typename HashTraits, typename Allocator>
+class LinkedHashSet;
+template <WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
+struct WeakProcessingHashTableHelper;
 
-    typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
+typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
 
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTableConstIterator {
-    private:
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
-        typedef Value ValueType;
-        typedef typename Traits::IteratorConstGetType GetType;
-        typedef const ValueType* PointerType;
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTableConstIterator {
+private:
+    typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
+    typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
+    typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
+    typedef Value ValueType;
+    typedef typename Traits::IteratorConstGetType GetType;
+    typedef const ValueType* PointerType;
 
-        friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
-        friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
+    friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
+    friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
 
-        void skipEmptyBuckets()
-        {
-            while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position))
-                ++m_position;
-        }
-
-        HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container)
-            : m_position(position)
-            , m_endPosition(endPosition)
-#if ENABLE(ASSERT)
-            , m_container(container)
-            , m_containerModifications(container->modifications())
-#endif
-        {
-            skipEmptyBuckets();
-        }
-
-        HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container, HashItemKnownGoodTag)
-            : m_position(position)
-            , m_endPosition(endPosition)
-#if ENABLE(ASSERT)
-            , m_container(container)
-            , m_containerModifications(container->modifications())
-#endif
-        {
-            ASSERT(m_containerModifications == m_container->modifications());
-        }
-
-        void checkModifications() const
-        {
-            // HashTable and collections that build on it do not support
-            // modifications while there is an iterator in use. The exception
-            // is ListHashSet, which has its own iterators that tolerate
-            // modification of the underlying set.
-            ASSERT(m_containerModifications == m_container->modifications());
-        }
-
-    public:
-        HashTableConstIterator()
-        {
-        }
-
-        GetType get() const
-        {
-            checkModifications();
-            return m_position;
-        }
-        typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
-        GetType operator->() const { return get(); }
-
-        const_iterator& operator++()
-        {
-            ASSERT(m_position != m_endPosition);
-            checkModifications();
+    void skipEmptyBuckets()
+    {
+        while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position))
             ++m_position;
-            skipEmptyBuckets();
-            return *this;
-        }
-
-        // postfix ++ intentionally omitted
-
-        // Comparison.
-        bool operator==(const const_iterator& other) const
-        {
-            return m_position == other.m_position;
-        }
-        bool operator!=(const const_iterator& other) const
-        {
-            return m_position != other.m_position;
-        }
-        bool operator==(const iterator& other) const
-        {
-            return *this == static_cast<const_iterator>(other);
-        }
-        bool operator!=(const iterator& other) const
-        {
-            return *this != static_cast<const_iterator>(other);
-        }
-
-    private:
-        PointerType m_position;
-        PointerType m_endPosition;
-#if ENABLE(ASSERT)
-        const HashTableType* m_container;
-        int64_t m_containerModifications;
-#endif
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTableIterator {
-    private:
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
-        typedef Value ValueType;
-        typedef typename Traits::IteratorGetType GetType;
-        typedef ValueType* PointerType;
-
-        friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
-
-        HashTableIterator(PointerType pos, PointerType end, const HashTableType* container) : m_iterator(pos, end, container) { }
-        HashTableIterator(PointerType pos, PointerType end, const HashTableType* container, HashItemKnownGoodTag tag) : m_iterator(pos, end, container, tag) { }
-
-    public:
-        HashTableIterator() { }
-
-        // default copy, assignment and destructor are OK
-
-        GetType get() const { return const_cast<GetType>(m_iterator.get()); }
-        typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
-        GetType operator->() const { return get(); }
-
-        iterator& operator++() { ++m_iterator; return *this; }
-
-        // postfix ++ intentionally omitted
-
-        // Comparison.
-        bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
-        bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
-        bool operator==(const const_iterator& other) const { return m_iterator == other; }
-        bool operator!=(const const_iterator& other) const { return m_iterator != other; }
-
-        operator const_iterator() const { return m_iterator; }
-
-    private:
-        const_iterator m_iterator;
-    };
-
-    using std::swap;
-
-    // Work around MSVC's standard library, whose swap for pairs does not swap by component.
-    template<typename T> inline void hashTableSwap(T& a, T& b)
-    {
-        swap(a, b);
     }
 
-    template<typename T, typename U> inline void hashTableSwap(KeyValuePair<T, U>& a, KeyValuePair<T, U>& b)
+    HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container)
+        : m_position(position)
+        , m_endPosition(endPosition)
+#if ENABLE(ASSERT)
+        , m_container(container)
+        , m_containerModifications(container->modifications())
+#endif
     {
-        swap(a.key, b.key);
-        swap(a.value, b.value);
+        skipEmptyBuckets();
     }
 
-    template<typename T, typename Allocator, bool useSwap = !IsTriviallyDestructible<T>::value>
-    struct Mover;
-    template<typename T, typename Allocator> struct Mover<T, Allocator, true> {
-        static void move(T& from, T& to)
-        {
-            // The key and value cannot be swapped atomically, and it would be
-            // wrong to have a GC when only one was swapped and the other still
-            // contained garbage (eg. from a previous use of the same slot).
-            // Therefore we forbid a GC until both the key and the value are
-            // swapped.
-            Allocator::enterGCForbiddenScope();
-            hashTableSwap(from, to);
-            Allocator::leaveGCForbiddenScope();
-        }
-    };
-    template<typename T, typename Allocator> struct Mover<T, Allocator, false> {
-        static void move(T& from, T& to) { to = from; }
-    };
-
-    template<typename HashFunctions> class IdentityHashTranslator {
-    public:
-        template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
-        template<typename T, typename U, typename V> static void translate(T& location, const U&, const V& value) { location = value; }
-    };
-
-    template<typename HashTableType, typename ValueType> struct HashTableAddResult {
-        HashTableAddResult(const HashTableType* container, ValueType* storedValue, bool isNewEntry)
-            : storedValue(storedValue)
-            , isNewEntry(isNewEntry)
-#if ENABLE(SECURITY_ASSERT)
-            , m_container(container)
-            , m_containerModifications(container->modifications())
-#endif
-        {
-            ASSERT_UNUSED(container, container);
-        }
-
-        ValueType* storedValue;
-        bool isNewEntry;
-
-#if ENABLE(SECURITY_ASSERT)
-        ~HashTableAddResult()
-        {
-            // If rehash happened before accessing storedValue, it's
-            // use-after-free. Any modification may cause a rehash, so we check
-            // for modifications here.
-            // Rehash after accessing storedValue is harmless but will assert if
-            // the AddResult destructor takes place after a modification. You
-            // may need to limit the scope of the AddResult.
-            ASSERT_WITH_SECURITY_IMPLICATION(m_containerModifications == m_container->modifications());
-        }
-
-    private:
-        const HashTableType* m_container;
-        const int64_t m_containerModifications;
-#endif
-    };
-
-    template<typename Value, typename Extractor, typename KeyTraits>
-    struct HashTableHelper {
-        static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
-        static bool isDeletedBucket(const Value& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
-        static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
-    };
-
-    template<typename HashTranslator, typename KeyTraits, bool safeToCompareToEmptyOrDeleted>
-    struct HashTableKeyChecker {
-        // There's no simple generic way to make this check if safeToCompareToEmptyOrDeleted is false,
-        // so the check always passes.
-        template <typename T>
-        static bool checkKey(const T&) { return true; }
-    };
-
-    template<typename HashTranslator, typename KeyTraits>
-    struct HashTableKeyChecker<HashTranslator, KeyTraits, true> {
-        template <typename T>
-        static bool checkKey(const T& key)
-        {
-            // FIXME : Check also equality to the deleted value.
-            return !HashTranslator::equal(KeyTraits::emptyValue(), key);
-        }
-    };
-
-    // Note: empty or deleted key values are not allowed, using them may lead to undefined behavior.
-    // For pointer keys this means that null pointers are not allowed unless you supply custom key traits.
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    class HashTable : public ConditionalDestructor<HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollected> {
-    public:
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
-        typedef Traits ValueTraits;
-        typedef Key KeyType;
-        typedef typename KeyTraits::PeekInType KeyPeekInType;
-        typedef typename KeyTraits::PassInType KeyPassInType;
-        typedef Value ValueType;
-        typedef Extractor ExtractorType;
-        typedef KeyTraits KeyTraitsType;
-        typedef typename Traits::PassInType ValuePassInType;
-        typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
-        typedef HashTableAddResult<HashTable, ValueType> AddResult;
-
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        struct Stats {
-            Stats()
-                : numAccesses(0)
-                , numRehashes(0)
-                , numRemoves(0)
-                , numReinserts(0)
-                , maxCollisions(0)
-                , numCollisions(0)
-                , collisionGraph()
-            {
-            }
-
-            int numAccesses;
-            int numRehashes;
-            int numRemoves;
-            int numReinserts;
-
-            int maxCollisions;
-            int numCollisions;
-            int collisionGraph[4096];
-
-            void recordCollisionAtCount(int count)
-            {
-                if (count > maxCollisions)
-                    maxCollisions = count;
-                numCollisions++;
-                collisionGraph[count]++;
-            }
-
-            void dumpStats()
-            {
-                dataLogF("\nWTF::HashTable::Stats dump\n\n");
-                dataLogF("%d accesses\n", numAccesses);
-                dataLogF("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
-                dataLogF("longest collision chain: %d\n", maxCollisions);
-                for (int i = 1; i <= maxCollisions; i++) {
-                    dataLogF("  %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses);
-                }
-                dataLogF("%d rehashes\n", numRehashes);
-                dataLogF("%d reinserts\n", numReinserts);
-            }
-        };
-#endif
-
-        HashTable();
-        void finalize()
-        {
-            ASSERT(!Allocator::isGarbageCollected);
-            if (LIKELY(!m_table))
-                return;
-            deleteAllBucketsAndDeallocate(m_table, m_tableSize);
-            m_table = 0;
-        }
-
-        HashTable(const HashTable&);
-        void swap(HashTable&);
-        HashTable& operator=(const HashTable&);
-
-        // When the hash table is empty, just return the same iterator for end as for begin.
-        // This is more efficient because we don't have to skip all the empty and deleted
-        // buckets, and iterating an empty table is a common case that's worth optimizing.
-        iterator begin() { return isEmpty() ? end() : makeIterator(m_table); }
-        iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
-        const_iterator begin() const { return isEmpty() ? end() : makeConstIterator(m_table); }
-        const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); }
-
-        unsigned size() const { return m_keyCount; }
-        unsigned capacity() const { return m_tableSize; }
-        bool isEmpty() const { return !m_keyCount; }
-
-        void reserveCapacityForSize(unsigned size);
-
-        AddResult add(ValuePassInType value)
-        {
-            return add<IdentityTranslatorType>(Extractor::extract(value), value);
-        }
-
-        // A special version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table.
-        template<typename HashTranslator, typename T, typename Extra> AddResult add(const T& key, const Extra&);
-        template<typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(const T& key, const Extra&);
-
-        iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); }
-        const_iterator find(KeyPeekInType key) const { return find<IdentityTranslatorType>(key); }
-        bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorType>(key); }
-
-        template<typename HashTranslator, typename T> iterator find(const T&);
-        template<typename HashTranslator, typename T> const_iterator find(const T&) const;
-        template<typename HashTranslator, typename T> bool contains(const T&) const;
-
-        void remove(KeyPeekInType);
-        void remove(iterator);
-        void remove(const_iterator);
-        void clear();
-
-        static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
-        static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
-        static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
-
-        ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); }
-        template<typename HashTranslator, typename T> ValueType* lookup(T);
-        template<typename HashTranslator, typename T> const ValueType* lookup(T) const;
-
-        template<typename VisitorDispatcher> void trace(VisitorDispatcher);
-
+    HashTableConstIterator(PointerType position, PointerType endPosition, const HashTableType* container, HashItemKnownGoodTag)
+        : m_position(position)
+        , m_endPosition(endPosition)
 #if ENABLE(ASSERT)
-        int64_t modifications() const { return m_modifications; }
-        void registerModification() { m_modifications++; }
+        , m_container(container)
+        , m_containerModifications(container->modifications())
+#endif
+    {
+        ASSERT(m_containerModifications == m_container->modifications());
+    }
+
+    void checkModifications() const
+    {
         // HashTable and collections that build on it do not support
         // modifications while there is an iterator in use. The exception is
         // ListHashSet, which has its own iterators that tolerate modification
         // of the underlying set.
-        void checkModifications(int64_t mods) const { ASSERT(mods == m_modifications); }
-#else
-        int64_t modifications() const { return 0; }
-        void registerModification() { }
-        void checkModifications(int64_t mods) const { }
-#endif
-
-    private:
-        static ValueType* allocateTable(unsigned size);
-        static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size);
-
-        typedef std::pair<ValueType*, bool> LookupType;
-        typedef std::pair<LookupType, unsigned> FullLookupType;
-
-        LookupType lookupForWriting(const Key& key) { return lookupForWriting<IdentityTranslatorType>(key); }
-        template<typename HashTranslator, typename T> FullLookupType fullLookupForWriting(const T&);
-        template<typename HashTranslator, typename T> LookupType lookupForWriting(const T&);
-
-        void remove(ValueType*);
-
-        bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
-        bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
-        bool shouldShrink() const
-        {
-            // isAllocationAllowed check should be at the last because it's
-            // expensive.
-            return m_keyCount * m_minLoad < m_tableSize
-                && m_tableSize > KeyTraits::minimumTableSize
-                && Allocator::isAllocationAllowed();
-        }
-        ValueType* expand(ValueType* entry = 0);
-        void shrink() { rehash(m_tableSize / 2, 0); }
-
-        ValueType* expandBuffer(unsigned newTableSize, ValueType* entry, bool&);
-        ValueType* rehashTo(ValueType* newTable, unsigned newTableSize, ValueType* entry);
-        ValueType* rehash(unsigned newTableSize, ValueType* entry);
-        ValueType* reinsert(ValueType&);
-
-        static void initializeBucket(ValueType& bucket);
-        static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket, Allocator::isGarbageCollected); }
-
-        FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
-            { return FullLookupType(LookupType(position, found), hash); }
-
-        iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this); }
-        const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this); }
-        iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
-        const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
-
-        static const unsigned m_maxLoad = 2;
-        static const unsigned m_minLoad = 6;
-
-        unsigned tableSizeMask() const
-        {
-            size_t mask = m_tableSize - 1;
-            ASSERT((mask & m_tableSize) == 0);
-            return mask;
-        }
-
-        void setEnqueued() { m_queueFlag = true; }
-        void clearEnqueued() { m_queueFlag = false; }
-        bool enqueued() { return m_queueFlag; }
-
-        ValueType* m_table;
-        unsigned m_tableSize;
-        unsigned m_keyCount;
-        unsigned m_deletedCount:31;
-        bool m_queueFlag:1;
-#if ENABLE(ASSERT)
-        unsigned m_modifications;
-#endif
-
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-    public:
-        mutable OwnPtr<Stats> m_stats;
-#endif
-
-        template<WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper;
-        template<typename T, typename U, typename V, typename W> friend class LinkedHashSet;
-    };
-
-    // Set all the bits to one after the most significant bit: 00110101010 -> 00111111111.
-    template<unsigned size> struct OneifyLowBits;
-    template<>
-    struct OneifyLowBits<0> {
-        static const unsigned value = 0;
-    };
-    template<unsigned number>
-    struct OneifyLowBits {
-        static const unsigned value = number | OneifyLowBits<(number >> 1)>::value;
-    };
-    // Compute the first power of two integer that is an upper bound of the parameter 'number'.
-    template<unsigned number>
-    struct UpperPowerOfTwoBound {
-        static const unsigned value = (OneifyLowBits<number - 1>::value + 1) * 2;
-    };
-
-    // Because power of two numbers are the limit of maxLoad, their capacity is twice the
-    // UpperPowerOfTwoBound, or 4 times their values.
-    template<unsigned size, bool isPowerOfTwo> struct HashTableCapacityForSizeSplitter;
-    template<unsigned size>
-    struct HashTableCapacityForSizeSplitter<size, true> {
-        static const unsigned value = size * 4;
-    };
-    template<unsigned size>
-    struct HashTableCapacityForSizeSplitter<size, false> {
-        static const unsigned value = UpperPowerOfTwoBound<size>::value;
-    };
-
-    // HashTableCapacityForSize computes the upper power of two capacity to hold the size parameter.
-    // This is done at compile time to initialize the HashTraits.
-    template<unsigned size>
-    struct HashTableCapacityForSize {
-        static const unsigned value = HashTableCapacityForSizeSplitter<size, !(size & (size - 1))>::value;
-        static_assert(size > 0, "HashTable minimum capacity should be > 0");
-        static_assert(!static_cast<int>(value >> 31), "HashTable capacity should not overflow 32bit int");
-        static_assert(value > (2 * size), "HashTable capacity should be able to hold content size");
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable()
-        : m_table(0)
-        , m_tableSize(0)
-        , m_keyCount(0)
-        , m_deletedCount(0)
-        , m_queueFlag(false)
-#if ENABLE(ASSERT)
-        , m_modifications(0)
-#endif
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        , m_stats(adoptPtr(new Stats))
-#endif
-    {
+        ASSERT(m_containerModifications == m_container->modifications());
     }
 
-    inline unsigned doubleHash(unsigned key)
+public:
+    HashTableConstIterator() {}
+
+    GetType get() const
     {
-        key = ~key + (key >> 23);
-        key ^= (key << 12);
-        key ^= (key >> 7);
-        key ^= (key << 2);
-        key ^= (key >> 20);
-        return key;
+        checkModifications();
+        return m_position;
     }
+    typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
+    GetType operator->() const { return get(); }
 
-    inline unsigned calculateCapacity(unsigned size)
+    const_iterator& operator++()
     {
-        for (unsigned mask = size; mask; mask >>= 1)
-            size |= mask; // 00110101010 -> 00111111111
-        return (size + 1) * 2; // 00111111111 -> 10000000000
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reserveCapacityForSize(unsigned newSize)
-    {
-        unsigned newCapacity = calculateCapacity(newSize);
-        if (newCapacity > capacity()) {
-            RELEASE_ASSERT(!static_cast<int>(newCapacity >> 31)); // HashTable capacity should not overflow 32bit int.
-            rehash(newCapacity, 0);
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key)
-    {
-        return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTranslator, T>(key));
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key) const
-    {
-        ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeToCompareToEmptyOrDeleted>::checkKey(key)));
-        const ValueType* table = m_table;
-        if (!table)
-            return 0;
-
-        size_t k = 0;
-        size_t sizeMask = tableSizeMask();
-        unsigned h = HashTranslator::hash(key);
-        size_t i = h & sizeMask;
-
-        UPDATE_ACCESS_COUNTS();
-
-        while (1) {
-            const ValueType* entry = table + i;
-
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return entry;
-
-                if (isEmptyBucket(*entry))
-                    return 0;
-            } else {
-                if (isEmptyBucket(*entry))
-                    return 0;
-
-                if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key))
-                    return entry;
-            }
-            UPDATE_PROBE_COUNTS();
-            if (!k)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookupForWriting(const T& key)
-    {
-        ASSERT(m_table);
-        registerModification();
-
-        ValueType* table = m_table;
-        size_t k = 0;
-        size_t sizeMask = tableSizeMask();
-        unsigned h = HashTranslator::hash(key);
-        size_t i = h & sizeMask;
-
-        UPDATE_ACCESS_COUNTS();
-
-        ValueType* deletedEntry = 0;
-
-        while (1) {
-            ValueType* entry = table + i;
-
-            if (isEmptyBucket(*entry))
-                return LookupType(deletedEntry ? deletedEntry : entry, false);
-
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return LookupType(entry, true);
-
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return LookupType(entry, true);
-            }
-            UPDATE_PROBE_COUNTS();
-            if (!k)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key)
-    {
-        ASSERT(m_table);
-        registerModification();
-
-        ValueType* table = m_table;
-        size_t k = 0;
-        size_t sizeMask = tableSizeMask();
-        unsigned h = HashTranslator::hash(key);
-        size_t i = h & sizeMask;
-
-        UPDATE_ACCESS_COUNTS();
-
-        ValueType* deletedEntry = 0;
-
-        while (1) {
-            ValueType* entry = table + i;
-
-            if (isEmptyBucket(*entry))
-                return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
-
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return makeLookupResult(entry, true, h);
-
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return makeLookupResult(entry, true, h);
-            }
-            UPDATE_PROBE_COUNTS();
-            if (!k)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<bool emptyValueIsZero> struct HashTableBucketInitializer;
-
-    template<> struct HashTableBucketInitializer<false> {
-        template<typename Traits, typename Value> static void initialize(Value& bucket)
-        {
-            new (NotNull, &bucket) Value(Traits::emptyValue());
-        }
-    };
-
-    template<> struct HashTableBucketInitializer<true> {
-        template<typename Traits, typename Value> static void initialize(Value& bucket)
-        {
-            // This initializes the bucket without copying the empty value.
-            // That makes it possible to use this with types that don't support copying.
-            // The memset to 0 looks like a slow operation but is optimized by the compilers.
-            memset(&bucket, 0, sizeof(bucket));
-        }
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::initializeBucket(ValueType& bucket)
-    {
-        // The key and value cannot be initialied atomically, and it would be
-        // wrong to have a GC when only one was initialized and the other still
-        // contained garbage (eg. from a previous use of the same slot).
-        // Therefore we forbid a GC while both the key and the value are
-        // initialized.
-        Allocator::enterGCForbiddenScope();
-        HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Traits>(bucket);
-        Allocator::leaveGCForbiddenScope();
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T, typename Extra>
-    typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::add(const T& key, const Extra& extra)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        if (!m_table)
-            expand();
-
-        ASSERT(m_table);
-
-        ValueType* table = m_table;
-        size_t k = 0;
-        size_t sizeMask = tableSizeMask();
-        unsigned h = HashTranslator::hash(key);
-        size_t i = h & sizeMask;
-
-        UPDATE_ACCESS_COUNTS();
-
-        ValueType* deletedEntry = 0;
-        ValueType* entry;
-        while (1) {
-            entry = table + i;
-
-            if (isEmptyBucket(*entry))
-                break;
-
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return AddResult(this, entry, false);
-
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return AddResult(this, entry, false);
-            }
-            UPDATE_PROBE_COUNTS();
-            if (!k)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-
-        registerModification();
-
-        if (deletedEntry) {
-            // Overwrite any data left over from last use, using placement new
-            // or memset.
-            initializeBucket(*deletedEntry);
-            entry = deletedEntry;
-            --m_deletedCount;
-        }
-
-        HashTranslator::translate(*entry, key, extra);
-        ASSERT(!isEmptyOrDeletedBucket(*entry));
-
-        ++m_keyCount;
-
-        if (shouldExpand())
-            entry = expand(entry);
-
-        return AddResult(this, entry, true);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename HashTranslator, typename T, typename Extra>
-    typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        if (!m_table)
-            expand();
-
-        FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key);
-
-        ValueType* entry = lookupResult.first.first;
-        bool found = lookupResult.first.second;
-        unsigned h = lookupResult.second;
-
-        if (found)
-            return AddResult(this, entry, false);
-
-        registerModification();
-
-        if (isDeletedBucket(*entry)) {
-            initializeBucket(*entry);
-            --m_deletedCount;
-        }
-
-        HashTranslator::translate(*entry, key, extra, h);
-        ASSERT(!isEmptyOrDeletedBucket(*entry));
-
-        ++m_keyCount;
-        if (shouldExpand())
-            entry = expand(entry);
-
-        return AddResult(this, entry, true);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reinsert(ValueType& entry)
-    {
-        ASSERT(m_table);
-        registerModification();
-        ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
-        ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numReinserts);
-#endif
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        ++m_stats->numReinserts;
-#endif
-        Value* newEntry = lookupForWriting(Extractor::extract(entry)).first;
-        Mover<ValueType, Allocator>::move(entry, *newEntry);
-
-        return newEntry;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template <typename HashTranslator, typename T>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key)
-    {
-        ValueType* entry = lookup<HashTranslator>(key);
-        if (!entry)
-            return end();
-
-        return makeKnownGoodIterator(entry);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template <typename HashTranslator, typename T>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key) const
-    {
-        ValueType* entry = const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
-        if (!entry)
-            return end();
-
-        return makeKnownGoodConstIterator(entry);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template <typename HashTranslator, typename T>
-    bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::contains(const T& key) const
-    {
-        return const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(ValueType* pos)
-    {
-        registerModification();
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numRemoves);
-#endif
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        ++m_stats->numRemoves;
-#endif
-
-        deleteBucket(*pos);
-        ++m_deletedCount;
-        --m_keyCount;
-
-        if (shouldShrink())
-            shrink();
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(iterator it)
-    {
-        if (it == end())
-            return;
-
-        remove(const_cast<ValueType*>(it.m_iterator.m_position));
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(const_iterator it)
-    {
-        if (it == end())
-            return;
-
-        remove(const_cast<ValueType*>(it.m_position));
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(KeyPeekInType key)
-    {
-        remove(find(key));
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::allocateTable(unsigned size)
-    {
-        size_t allocSize = size * sizeof(ValueType);
-        ValueType* result;
-        // Assert that we will not use memset on things with a vtable entry.
-        // The compiler will also check this on some platforms. We would
-        // like to check this on the whole value (key-value pair), but
-        // IsPolymorphic will return false for a pair of two types, even if
-        // one of the components is polymorphic.
-        static_assert(!Traits::emptyValueIsZero || !IsPolymorphic<KeyType>::value, "empty value cannot be zero for things with a vtable");
-
-#if ENABLE(OILPAN)
-        static_assert(Allocator::isGarbageCollected
-            || ((!IsAllowOnlyInlineAllocation<KeyType>::value || !NeedsTracing<KeyType>::value)
-            && (!IsAllowOnlyInlineAllocation<ValueType>::value || !NeedsTracing<ValueType>::value))
-            , "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap HashTable");
-#endif
-        if (Traits::emptyValueIsZero) {
-            result = Allocator::template allocateZeroedHashTableBacking<ValueType, HashTable>(allocSize);
-        } else {
-            result = Allocator::template allocateHashTableBacking<ValueType, HashTable>(allocSize);
-            for (unsigned i = 0; i < size; i++)
-                initializeBucket(result[i]);
-        }
-        return result;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size)
-    {
-        if (!IsTriviallyDestructible<ValueType>::value) {
-            for (unsigned i = 0; i < size; ++i) {
-                // This code is called when the hash table is cleared or
-                // resized. We have allocated a new backing store and we need
-                // to run the destructors on the old backing store, as it is
-                // being freed. If we are GCing we need to both call the
-                // destructor and mark the bucket as deleted, otherwise the
-                // destructor gets called again when the GC finds the backing
-                // store. With the default allocator it's enough to call the
-                // destructor, since we will free the memory explicitly and
-                // we won't see the memory with the bucket again.
-                if (Allocator::isGarbageCollected) {
-                    if (!isEmptyOrDeletedBucket(table[i]))
-                        deleteBucket(table[i]);
-                } else {
-                    if (!isDeletedBucket(table[i]))
-                        table[i].~ValueType();
-                }
-            }
-        }
-        Allocator::freeHashTableBacking(table);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::expand(Value* entry)
-    {
-        unsigned newSize;
-        if (!m_tableSize) {
-            newSize = KeyTraits::minimumTableSize;
-        } else if (mustRehashInPlace()) {
-            newSize = m_tableSize;
-        } else {
-            newSize = m_tableSize * 2;
-            RELEASE_ASSERT(newSize > m_tableSize);
-        }
-
-        return rehash(newSize, entry);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::expandBuffer(unsigned newTableSize, Value* entry, bool& success)
-    {
-        success = false;
-        ASSERT(m_tableSize < newTableSize);
-        if (!Allocator::expandHashTableBacking(m_table, newTableSize * sizeof(ValueType)))
-            return 0;
-
-        success = true;
-
-        Value* newEntry = nullptr;
-        unsigned oldTableSize = m_tableSize;
-        ValueType* originalTable = m_table;
-
-        ValueType* temporaryTable = allocateTable(oldTableSize);
-        for (unsigned i = 0; i < oldTableSize; i++) {
-            if (&m_table[i] == entry)
-                newEntry = &temporaryTable[i];
-            if (isEmptyOrDeletedBucket(m_table[i])) {
-                ASSERT(&m_table[i] != entry);
-                if (Traits::emptyValueIsZero) {
-                    memset(&temporaryTable[i], 0, sizeof(ValueType));
-                } else {
-                    initializeBucket(temporaryTable[i]);
-                }
-            } else {
-                Mover<ValueType, Allocator>::move(m_table[i], temporaryTable[i]);
-            }
-        }
-        m_table = temporaryTable;
-
-        if (Traits::emptyValueIsZero) {
-            memset(originalTable, 0, newTableSize * sizeof(ValueType));
-        } else {
-            for (unsigned i = 0; i < newTableSize; i++)
-                initializeBucket(originalTable[i]);
-        }
-        newEntry = rehashTo(originalTable, newTableSize, newEntry);
-        deleteAllBucketsAndDeallocate(temporaryTable, oldTableSize);
-
-        return newEntry;
-    }
-
-template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehashTo(ValueType* newTable, unsigned newTableSize, Value* entry)
-    {
-        unsigned oldTableSize = m_tableSize;
-        ValueType* oldTable = m_table;
-
-#if DUMP_HASHTABLE_STATS
-        if (oldTableSize != 0)
-            atomicIncrement(&HashTableStats::numRehashes);
-#endif
-
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        if (oldTableSize != 0)
-            ++m_stats->numRehashes;
-#endif
-
-        m_table = newTable;
-        m_tableSize = newTableSize;
-
-        Value* newEntry = 0;
-        for (unsigned i = 0; i != oldTableSize; ++i) {
-            if (isEmptyOrDeletedBucket(oldTable[i])) {
-                ASSERT(&oldTable[i] != entry);
-                continue;
-            }
-            Value* reinsertedEntry = reinsert(oldTable[i]);
-            if (&oldTable[i] == entry) {
-                ASSERT(!newEntry);
-                newEntry = reinsertedEntry;
-            }
-        }
-
-        m_deletedCount = 0;
-
-        return newEntry;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehash(unsigned newTableSize, Value* entry)
-    {
-        unsigned oldTableSize = m_tableSize;
-        ValueType* oldTable = m_table;
-
-#if DUMP_HASHTABLE_STATS
-        if (oldTableSize != 0)
-            atomicIncrement(&HashTableStats::numRehashes);
-#endif
-
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        if (oldTableSize != 0)
-            ++m_stats->numRehashes;
-#endif
-
-        // The Allocator::isGarbageCollected check is not needed.
-        // The check is just a static hint for a compiler to indicate that
-        // Base::expandBuffer returns false if Allocator is a DefaultAllocator.
-        if (Allocator::isGarbageCollected && newTableSize > oldTableSize) {
-            bool success;
-            Value* newEntry = expandBuffer(newTableSize, entry, success);
-            if (success)
-                return newEntry;
-        }
-
-        ValueType* newTable = allocateTable(newTableSize);
-        Value* newEntry = rehashTo(newTable, newTableSize, entry);
-        deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
-
-        return newEntry;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::clear()
-    {
-        registerModification();
-        if (!m_table)
-            return;
-
-        deleteAllBucketsAndDeallocate(m_table, m_tableSize);
-        m_table = 0;
-        m_tableSize = 0;
-        m_keyCount = 0;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable(const HashTable& other)
-        : m_table(0)
-        , m_tableSize(0)
-        , m_keyCount(0)
-        , m_deletedCount(0)
-        , m_queueFlag(false)
-#if ENABLE(ASSERT)
-        , m_modifications(0)
-#endif
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        , m_stats(adoptPtr(new Stats(*other.m_stats)))
-#endif
-    {
-        // Copy the hash table the dumb way, by adding each element to the new table.
-        // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed.
-        const_iterator end = other.end();
-        for (const_iterator it = other.begin(); it != end; ++it)
-            add(*it);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::swap(HashTable& other)
-    {
-        std::swap(m_table, other.m_table);
-        std::swap(m_tableSize, other.m_tableSize);
-        std::swap(m_keyCount, other.m_keyCount);
-        // std::swap does not work for bit fields.
-        unsigned deleted = m_deletedCount;
-        m_deletedCount = other.m_deletedCount;
-        other.m_deletedCount = deleted;
-        ASSERT(!m_queueFlag);
-        ASSERT(!other.m_queueFlag);
-
-#if ENABLE(ASSERT)
-        std::swap(m_modifications, other.m_modifications);
-#endif
-
-#if DUMP_HASHTABLE_STATS_PER_TABLE
-        m_stats.swap(other.m_stats);
-#endif
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::operator=(const HashTable& other)
-    {
-        HashTable tmp(other);
-        swap(tmp);
+        ASSERT(m_position != m_endPosition);
+        checkModifications();
+        ++m_position;
+        skipEmptyBuckets();
         return *this;
     }
 
-    template<WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    struct WeakProcessingHashTableHelper;
+    // postfix ++ intentionally omitted
 
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
-        static void process(typename Allocator::Visitor* visitor, void* closure) { }
-        static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure) { }
-        static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure) { }
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
-        // Used for purely weak and for weak-and-strong tables (ephemerons).
-        static void process(typename Allocator::Visitor* visitor, void* closure)
-        {
-            typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
-            HashTableType* table = reinterpret_cast<HashTableType*>(closure);
-            ASSERT(table->m_table);
-            // Now perform weak processing (this is a no-op if the backing
-            // was accessible through an iterator and was already marked
-            // strongly).
-            typedef typename HashTableType::ValueType ValueType;
-            for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
-                if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
-                    // At this stage calling trace can make no difference
-                    // (everything is already traced), but we use the
-                    // return value to remove things from the collection.
-
-                    // FIXME: This should be rewritten so that this can check
-                    // if the element is dead without calling trace,
-                    // which is semantically not correct to be called in
-                    // weak processing stage.
-                    if (TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element)) {
-                        table->registerModification();
-                        HashTableType::deleteBucket(*element); // Also calls the destructor.
-                        table->m_deletedCount++;
-                        table->m_keyCount--;
-                        // We don't rehash the backing until the next add
-                        // or delete, because that would cause allocation
-                        // during GC.
-                    }
-                }
-            }
-        }
-
-        // Called repeatedly for tables that have both weak and strong pointers.
-        static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure)
-        {
-            typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
-            HashTableType* table = reinterpret_cast<HashTableType*>(closure);
-            ASSERT(table->m_table);
-            // Check the hash table for elements that we now know will not
-            // be removed by weak processing. Those elements need to have
-            // their strong pointers traced.
-            typedef typename HashTableType::ValueType ValueType;
-            for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
-                if (!HashTableType::isEmptyOrDeletedBucket(*element))
-                    TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element);
-            }
-        }
-
-        // Called when the ephemeron iteration is done and before running the per thread
-        // weak processing. It is guaranteed to be called before any thread is resumed.
-        static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure)
-        {
-            typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
-            HashTableType* table = reinterpret_cast<HashTableType*>(closure);
-            ASSERT(Allocator::weakTableRegistered(visitor, table));
-            table->clearEnqueued();
-        }
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
-    template<typename VisitorDispatcher>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::trace(VisitorDispatcher visitor)
+    // Comparison.
+    bool operator==(const const_iterator& other) const
     {
-        // If someone else already marked the backing and queued up the trace
-        // and/or weak callback then we are done. This optimization does not
-        // happen for ListHashSet since its iterator does not point at the
-        // backing.
-        if (!m_table || Allocator::isHeapObjectAlive(m_table))
+        return m_position == other.m_position;
+    }
+    bool operator!=(const const_iterator& other) const
+    {
+        return m_position != other.m_position;
+    }
+    bool operator==(const iterator& other) const
+    {
+        return *this == static_cast<const_iterator>(other);
+    }
+    bool operator!=(const iterator& other) const
+    {
+        return *this != static_cast<const_iterator>(other);
+    }
+
+private:
+    PointerType m_position;
+    PointerType m_endPosition;
+#if ENABLE(ASSERT)
+    const HashTableType* m_container;
+    int64_t m_containerModifications;
+#endif
+};
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTableIterator {
+private:
+    typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
+    typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
+    typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
+    typedef Value ValueType;
+    typedef typename Traits::IteratorGetType GetType;
+    typedef ValueType* PointerType;
+
+    friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>;
+
+    HashTableIterator(PointerType pos, PointerType end, const HashTableType* container) : m_iterator(pos, end, container) {}
+    HashTableIterator(PointerType pos, PointerType end, const HashTableType* container, HashItemKnownGoodTag tag) : m_iterator(pos, end, container, tag) {}
+
+public:
+    HashTableIterator() {}
+
+    // default copy, assignment and destructor are OK
+
+    GetType get() const { return const_cast<GetType>(m_iterator.get()); }
+    typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
+    GetType operator->() const { return get(); }
+
+    iterator& operator++() { ++m_iterator; return *this; }
+
+    // postfix ++ intentionally omitted
+
+    // Comparison.
+    bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
+    bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
+    bool operator==(const const_iterator& other) const { return m_iterator == other; }
+    bool operator!=(const const_iterator& other) const { return m_iterator != other; }
+
+    operator const_iterator() const { return m_iterator; }
+
+private:
+    const_iterator m_iterator;
+};
+
+using std::swap;
+
+// Work around MSVC's standard library, whose swap for pairs does not swap by component.
+template <typename T> inline void hashTableSwap(T& a, T& b)
+{
+    swap(a, b);
+}
+
+template <typename T, typename U> inline void hashTableSwap(KeyValuePair<T, U>& a, KeyValuePair<T, U>& b)
+{
+    swap(a.key, b.key);
+    swap(a.value, b.value);
+}
+
+template <typename T, typename Allocator, bool useSwap = !IsTriviallyDestructible<T>::value>
+struct Mover;
+template <typename T, typename Allocator> struct Mover<T, Allocator, true> {
+    static void move(T& from, T& to)
+    {
+        // The key and value cannot be swapped atomically, and it would be wrong
+        // to have a GC when only one was swapped and the other still contained
+        // garbage (eg. from a previous use of the same slot).  Therefore we
+        // forbid a GC until both the key and the value are swapped.
+        Allocator::enterGCForbiddenScope();
+        hashTableSwap(from, to);
+        Allocator::leaveGCForbiddenScope();
+    }
+};
+
+template <typename T, typename Allocator> struct Mover<T, Allocator, false> {
+    static void move(T& from, T& to) { to = from; }
+};
+
+template <typename HashFunctions> class IdentityHashTranslator {
+public:
+    template <typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
+    template <typename T, typename U, typename V> static void translate(T& location, const U&, const V& value) { location = value; }
+};
+
+template <typename HashTableType, typename ValueType> struct HashTableAddResult {
+    HashTableAddResult(const HashTableType* container, ValueType* storedValue, bool isNewEntry)
+        : storedValue(storedValue)
+        , isNewEntry(isNewEntry)
+#if ENABLE(SECURITY_ASSERT)
+        , m_container(container)
+        , m_containerModifications(container->modifications())
+#endif
+    {
+        ASSERT_UNUSED(container, container);
+    }
+
+    ValueType* storedValue;
+    bool isNewEntry;
+
+#if ENABLE(SECURITY_ASSERT)
+    ~HashTableAddResult()
+    {
+        // If rehash happened before accessing storedValue, it's
+        // use-after-free. Any modification may cause a rehash, so we check for
+        // modifications here.
+
+        // Rehash after accessing storedValue is harmless but will assert if the
+        // AddResult destructor takes place after a modification. You may need
+        // to limit the scope of the AddResult.
+        ASSERT_WITH_SECURITY_IMPLICATION(m_containerModifications == m_container->modifications());
+    }
+
+private:
+    const HashTableType* m_container;
+    const int64_t m_containerModifications;
+#endif
+};
+
+template <typename Value, typename Extractor, typename KeyTraits>
+struct HashTableHelper {
+    static bool isEmptyBucket(const Value& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
+    static bool isDeletedBucket(const Value& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
+    static bool isEmptyOrDeletedBucket(const Value& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
+};
+
+template <typename HashTranslator, typename KeyTraits, bool safeToCompareToEmptyOrDeleted>
+struct HashTableKeyChecker {
+    // There's no simple generic way to make this check if
+    // safeToCompareToEmptyOrDeleted is false, so the check always passes.
+    template <typename T>
+    static bool checkKey(const T&) { return true; }
+};
+
+template <typename HashTranslator, typename KeyTraits>
+struct HashTableKeyChecker<HashTranslator, KeyTraits, true> {
+    template <typename T>
+    static bool checkKey(const T& key)
+    {
+        // FIXME : Check also equality to the deleted value.
+        return !HashTranslator::equal(KeyTraits::emptyValue(), key);
+    }
+};
+
+// Note: empty or deleted key values are not allowed, using them may lead to
+// undefined behavior.  For pointer keys this means that null pointers are not
+// allowed unless you supply custom key traits.
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+class HashTable : public ConditionalDestructor<HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>, Allocator::isGarbageCollected> {
+public:
+    typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> iterator;
+    typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> const_iterator;
+    typedef Traits ValueTraits;
+    typedef Key KeyType;
+    typedef typename KeyTraits::PeekInType KeyPeekInType;
+    typedef typename KeyTraits::PassInType KeyPassInType;
+    typedef Value ValueType;
+    typedef Extractor ExtractorType;
+    typedef KeyTraits KeyTraitsType;
+    typedef typename Traits::PassInType ValuePassInType;
+    typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
+    typedef HashTableAddResult<HashTable, ValueType> AddResult;
+
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    struct Stats {
+        Stats()
+            : numAccesses(0)
+            , numRehashes(0)
+            , numRemoves(0)
+            , numReinserts(0)
+            , maxCollisions(0)
+            , numCollisions(0)
+            , collisionGraph()
+        {
+        }
+
+        int numAccesses;
+        int numRehashes;
+        int numRemoves;
+        int numReinserts;
+
+        int maxCollisions;
+        int numCollisions;
+        int collisionGraph[4096];
+
+        void recordCollisionAtCount(int count)
+        {
+            if (count > maxCollisions)
+                maxCollisions = count;
+            numCollisions++;
+            collisionGraph[count]++;
+        }
+
+        void dumpStats()
+        {
+            dataLogF("\nWTF::HashTable::Stats dump\n\n");
+            dataLogF("%d accesses\n", numAccesses);
+            dataLogF("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
+            dataLogF("longest collision chain: %d\n", maxCollisions);
+            for (int i = 1; i <= maxCollisions; i++) {
+                dataLogF("  %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses);
+            }
+            dataLogF("%d rehashes\n", numRehashes);
+            dataLogF("%d reinserts\n", numReinserts);
+        }
+    };
+#endif
+
+    HashTable();
+    void finalize()
+    {
+        ASSERT(!Allocator::isGarbageCollected);
+        if (LIKELY(!m_table))
             return;
-        // Normally, we mark the backing store without performing trace. This
-        // means it is marked live, but the pointers inside it are not marked.
-        // Instead we will mark the pointers below. However, for backing
-        // stores that contain weak pointers the handling is rather different.
-        // We don't mark the backing store here, so the marking GC will leave
-        // the backing unmarked. If the backing is found in any other way than
-        // through its HashTable (ie from an iterator) then the mark bit will
-        // be set and the pointers will be marked strongly, avoiding problems
-        // with iterating over things that disappear due to weak processing
-        // while we are iterating over them. We register the backing store
-        // pointer for delayed marking which will take place after we know if
-        // the backing is reachable from elsewhere. We also register a
-        // weakProcessing callback which will perform weak processing if needed.
-        if (Traits::weakHandlingFlag == NoWeakHandlingInCollections) {
-            Allocator::markNoTracing(visitor, m_table);
+        deleteAllBucketsAndDeallocate(m_table, m_tableSize);
+        m_table = nullptr;
+    }
+
+    HashTable(const HashTable&);
+    void swap(HashTable&);
+    HashTable& operator=(const HashTable&);
+
+    // When the hash table is empty, just return the same iterator for end as
+    // for begin.  This is more efficient because we don't have to skip all the
+    // empty and deleted buckets, and iterating an empty table is a common case
+    // that's worth optimizing.
+    iterator begin() { return isEmpty() ? end() : makeIterator(m_table); }
+    iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
+    const_iterator begin() const { return isEmpty() ? end() : makeConstIterator(m_table); }
+    const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); }
+
+    unsigned size() const { return m_keyCount; }
+    unsigned capacity() const { return m_tableSize; }
+    bool isEmpty() const { return !m_keyCount; }
+
+    void reserveCapacityForSize(unsigned size);
+
+    AddResult add(ValuePassInType value)
+    {
+        return add<IdentityTranslatorType>(Extractor::extract(value), value);
+    }
+
+    // A special version of add() that finds the object by hashing and comparing
+    // with some other type, to avoid the cost of type conversion if the object
+    // is already in the table.
+    template <typename HashTranslator, typename T, typename Extra> AddResult add(const T& key, const Extra&);
+    template <typename HashTranslator, typename T, typename Extra> AddResult addPassingHashCode(const T& key, const Extra&);
+
+    iterator find(KeyPeekInType key) { return find<IdentityTranslatorType>(key); }
+    const_iterator find(KeyPeekInType key) const { return find<IdentityTranslatorType>(key); }
+    bool contains(KeyPeekInType key) const { return contains<IdentityTranslatorType>(key); }
+
+    template <typename HashTranslator, typename T> iterator find(const T&);
+    template <typename HashTranslator, typename T> const_iterator find(const T&) const;
+    template <typename HashTranslator, typename T> bool contains(const T&) const;
+
+    void remove(KeyPeekInType);
+    void remove(iterator);
+    void remove(const_iterator);
+    void clear();
+
+    static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); }
+    static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
+    static bool isEmptyOrDeletedBucket(const ValueType& value) { return HashTableHelper<ValueType, Extractor, KeyTraits>:: isEmptyOrDeletedBucket(value); }
+
+    ValueType* lookup(KeyPeekInType key) { return lookup<IdentityTranslatorType, KeyPeekInType>(key); }
+    template <typename HashTranslator, typename T> ValueType* lookup(T);
+    template <typename HashTranslator, typename T> const ValueType* lookup(T) const;
+
+    template <typename VisitorDispatcher> void trace(VisitorDispatcher);
+
+#if ENABLE(ASSERT)
+    int64_t modifications() const { return m_modifications; }
+    void registerModification() { m_modifications++; }
+    // HashTable and collections that build on it do not support modifications
+    // while there is an iterator in use. The exception is ListHashSet, which
+    // has its own iterators that tolerate modification of the underlying set.
+    void checkModifications(int64_t mods) const { ASSERT(mods == m_modifications); }
+#else
+    int64_t modifications() const { return 0; }
+    void registerModification() {}
+    void checkModifications(int64_t mods) const {}
+#endif
+
+private:
+    static ValueType* allocateTable(unsigned size);
+    static void deleteAllBucketsAndDeallocate(ValueType* table, unsigned size);
+
+    typedef std::pair<ValueType*, bool> LookupType;
+    typedef std::pair<LookupType, unsigned> FullLookupType;
+
+    LookupType lookupForWriting(const Key& key) { return lookupForWriting<IdentityTranslatorType>(key); }
+    template <typename HashTranslator, typename T> FullLookupType fullLookupForWriting(const T&);
+    template <typename HashTranslator, typename T> LookupType lookupForWriting(const T&);
+
+    void remove(ValueType*);
+
+    bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
+    bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
+    bool shouldShrink() const
+    {
+        // isAllocationAllowed check should be at the last because it's
+        // expensive.
+        return m_keyCount * m_minLoad < m_tableSize
+            && m_tableSize > KeyTraits::minimumTableSize
+            && Allocator::isAllocationAllowed();
+    }
+    ValueType* expand(ValueType* entry = 0);
+    void shrink() { rehash(m_tableSize / 2, 0); }
+
+    ValueType* expandBuffer(unsigned newTableSize, ValueType* entry, bool&);
+    ValueType* rehashTo(ValueType* newTable, unsigned newTableSize, ValueType* entry);
+    ValueType* rehash(unsigned newTableSize, ValueType* entry);
+    ValueType* reinsert(ValueType&);
+
+    static void initializeBucket(ValueType& bucket);
+    static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket, Allocator::isGarbageCollected); }
+
+    FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
+        { return FullLookupType(LookupType(position, found), hash); }
+
+    iterator makeIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this); }
+    const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this); }
+    iterator makeKnownGoodIterator(ValueType* pos) { return iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
+    const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(pos, m_table + m_tableSize, this, HashItemKnownGood); }
+
+    static const unsigned m_maxLoad = 2;
+    static const unsigned m_minLoad = 6;
+
+    unsigned tableSizeMask() const
+    {
+        size_t mask = m_tableSize - 1;
+        ASSERT((mask & m_tableSize) == 0);
+        return mask;
+    }
+
+    void setEnqueued() { m_queueFlag = true; }
+    void clearEnqueued() { m_queueFlag = false; }
+    bool enqueued() { return m_queueFlag; }
+
+    ValueType* m_table;
+    unsigned m_tableSize;
+    unsigned m_keyCount;
+    unsigned m_deletedCount:31;
+    bool m_queueFlag:1;
+#if ENABLE(ASSERT)
+    unsigned m_modifications;
+#endif
+
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+public:
+    mutable OwnPtr<Stats> m_stats;
+#endif
+
+    template <WeakHandlingFlag x, typename T, typename U, typename V, typename W, typename X, typename Y, typename Z> friend struct WeakProcessingHashTableHelper;
+    template <typename T, typename U, typename V, typename W> friend class LinkedHashSet;
+};
+
+// Set all the bits to one after the most significant bit:
+// 00110101010 -> 00111111111.
+template <unsigned size> struct OneifyLowBits;
+template <>
+struct OneifyLowBits<0> {
+    static const unsigned value = 0;
+};
+template <unsigned number>
+struct OneifyLowBits {
+    static const unsigned value = number | OneifyLowBits<(number >> 1)>::value;
+};
+// Compute the first power of two integer that is an upper bound of the
+// parameter 'number'.
+template <unsigned number>
+struct UpperPowerOfTwoBound {
+    static const unsigned value = (OneifyLowBits<number - 1>::value + 1) * 2;
+};
+
+// Because power of two numbers are the limit of maxLoad, their capacity is
+// twice the UpperPowerOfTwoBound, or 4 times their values.
+template <unsigned size, bool isPowerOfTwo> struct HashTableCapacityForSizeSplitter;
+template <unsigned size>
+struct HashTableCapacityForSizeSplitter<size, true> {
+    static const unsigned value = size * 4;
+};
+template <unsigned size>
+struct HashTableCapacityForSizeSplitter<size, false> {
+    static const unsigned value = UpperPowerOfTwoBound<size>::value;
+};
+
+// HashTableCapacityForSize computes the upper power of two capacity to hold the
+// size parameter.  This is done at compile time to initialize the HashTraits.
+template <unsigned size>
+struct HashTableCapacityForSize {
+    static const unsigned value = HashTableCapacityForSizeSplitter<size, !(size & (size - 1))>::value;
+    static_assert(size > 0, "HashTable minimum capacity should be > 0");
+    static_assert(!static_cast<int>(value >> 31), "HashTable capacity should not overflow 32bit int");
+    static_assert(value > (2 * size), "HashTable capacity should be able to hold content size");
+};
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable()
+    : m_table(nullptr)
+    , m_tableSize(0)
+    , m_keyCount(0)
+    , m_deletedCount(0)
+    , m_queueFlag(false)
+#if ENABLE(ASSERT)
+    , m_modifications(0)
+#endif
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    , m_stats(adoptPtr(new Stats))
+#endif
+{
+}
+
+inline unsigned doubleHash(unsigned key)
+{
+    key = ~key + (key >> 23);
+    key ^= (key << 12);
+    key ^= (key >> 7);
+    key ^= (key << 2);
+    key ^= (key >> 20);
+    return key;
+}
+
+inline unsigned calculateCapacity(unsigned size)
+{
+    for (unsigned mask = size; mask; mask >>= 1)
+        size |= mask; // 00110101010 -> 00111111111
+    return (size + 1) * 2; // 00111111111 -> 10000000000
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reserveCapacityForSize(unsigned newSize)
+{
+    unsigned newCapacity = calculateCapacity(newSize);
+    if (newCapacity > capacity()) {
+        RELEASE_ASSERT(!static_cast<int>(newCapacity >> 31)); // HashTable capacity should not overflow 32bit int.
+        rehash(newCapacity, 0);
+    }
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key)
+{
+    return const_cast<Value*>(const_cast<const HashTable*>(this)->lookup<HashTranslator, T>(key));
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline const Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookup(T key) const
+{
+    ASSERT((HashTableKeyChecker<HashTranslator, KeyTraits, HashFunctions::safeToCompareToEmptyOrDeleted>::checkKey(key)));
+    const ValueType* table = m_table;
+    if (!table)
+        return nullptr;
+
+    size_t k = 0;
+    size_t sizeMask = tableSizeMask();
+    unsigned h = HashTranslator::hash(key);
+    size_t i = h & sizeMask;
+
+    UPDATE_ACCESS_COUNTS();
+
+    while (1) {
+        const ValueType* entry = table + i;
+
+        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+            if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return entry;
+
+            if (isEmptyBucket(*entry))
+                return nullptr;
         } else {
-            Allocator::registerDelayedMarkNoTracing(visitor, m_table);
-            // Since we're delaying marking this HashTable, it is possible
-            // that the registerWeakMembers is called multiple times (in rare
-            // cases). However, it shouldn't cause any issue.
-            Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
+            if (isEmptyBucket(*entry))
+                return nullptr;
+
+            if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key))
+                return entry;
         }
-        if (ShouldBeTraced<Traits>::value) {
-            if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
-                // If we have both strong and weak pointers in the collection
-                // then we queue up the collection for fixed point iteration a
-                // la Ephemerons:
-                // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
-                // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
-                ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
-                if (!enqueued()) {
-                    Allocator::registerWeakTable(visitor, this,
-                        WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
-                        WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
-                    setEnqueued();
+        UPDATE_PROBE_COUNTS();
+        if (!k)
+            k = 1 | doubleHash(h);
+        i = (i + k) & sizeMask;
+    }
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::lookupForWriting(const T& key)
+{
+    ASSERT(m_table);
+    registerModification();
+
+    ValueType* table = m_table;
+    size_t k = 0;
+    size_t sizeMask = tableSizeMask();
+    unsigned h = HashTranslator::hash(key);
+    size_t i = h & sizeMask;
+
+    UPDATE_ACCESS_COUNTS();
+
+    ValueType* deletedEntry = nullptr;
+
+    while (1) {
+        ValueType* entry = table + i;
+
+        if (isEmptyBucket(*entry))
+            return LookupType(deletedEntry ? deletedEntry : entry, false);
+
+        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+            if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return LookupType(entry, true);
+
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+        } else {
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+            else if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return LookupType(entry, true);
+        }
+        UPDATE_PROBE_COUNTS();
+        if (!k)
+            k = 1 | doubleHash(h);
+        i = (i + k) & sizeMask;
+    }
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::fullLookupForWriting(const T& key)
+{
+    ASSERT(m_table);
+    registerModification();
+
+    ValueType* table = m_table;
+    size_t k = 0;
+    size_t sizeMask = tableSizeMask();
+    unsigned h = HashTranslator::hash(key);
+    size_t i = h & sizeMask;
+
+    UPDATE_ACCESS_COUNTS();
+
+    ValueType* deletedEntry = nullptr;
+
+    while (1) {
+        ValueType* entry = table + i;
+
+        if (isEmptyBucket(*entry))
+            return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
+
+        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+            if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return makeLookupResult(entry, true, h);
+
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+        } else {
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+            else if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return makeLookupResult(entry, true, h);
+        }
+        UPDATE_PROBE_COUNTS();
+        if (!k)
+            k = 1 | doubleHash(h);
+        i = (i + k) & sizeMask;
+    }
+}
+
+template <bool emptyValueIsZero> struct HashTableBucketInitializer;
+
+template <> struct HashTableBucketInitializer<false> {
+    template <typename Traits, typename Value> static void initialize(Value& bucket)
+    {
+        new (NotNull, &bucket) Value(Traits::emptyValue());
+    }
+};
+
+template <> struct HashTableBucketInitializer<true> {
+    template <typename Traits, typename Value> static void initialize(Value& bucket)
+    {
+        // This initializes the bucket without copying the empty value.  That
+        // makes it possible to use this with types that don't support copying.
+        // The memset to 0 looks like a slow operation but is optimized by the
+        // compilers.
+        memset(&bucket, 0, sizeof(bucket));
+    }
+};
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::initializeBucket(ValueType& bucket)
+{
+    // The key and value cannot be initialied atomically, and it would be wrong
+    // to have a GC when only one was initialized and the other still contained
+    // garbage (eg. from a previous use of the same slot).  Therefore we forbid
+    // a GC while both the key and the value are initialized.
+    Allocator::enterGCForbiddenScope();
+    HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Traits>(bucket);
+    Allocator::leaveGCForbiddenScope();
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T, typename Extra>
+typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::add(const T& key, const Extra& extra)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    if (!m_table)
+        expand();
+
+    ASSERT(m_table);
+
+    ValueType* table = m_table;
+    size_t k = 0;
+    size_t sizeMask = tableSizeMask();
+    unsigned h = HashTranslator::hash(key);
+    size_t i = h & sizeMask;
+
+    UPDATE_ACCESS_COUNTS();
+
+    ValueType* deletedEntry = nullptr;
+    ValueType* entry;
+    while (1) {
+        entry = table + i;
+
+        if (isEmptyBucket(*entry))
+            break;
+
+        if (HashFunctions::safeToCompareToEmptyOrDeleted) {
+            if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return AddResult(this, entry, false);
+
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+        } else {
+            if (isDeletedBucket(*entry))
+                deletedEntry = entry;
+            else if (HashTranslator::equal(Extractor::extract(*entry), key))
+                return AddResult(this, entry, false);
+        }
+        UPDATE_PROBE_COUNTS();
+        if (!k)
+            k = 1 | doubleHash(h);
+        i = (i + k) & sizeMask;
+    }
+
+    registerModification();
+
+    if (deletedEntry) {
+        // Overwrite any data left over from last use, using placement new or
+        // memset.
+        initializeBucket(*deletedEntry);
+        entry = deletedEntry;
+        --m_deletedCount;
+    }
+
+    HashTranslator::translate(*entry, key, extra);
+    ASSERT(!isEmptyOrDeletedBucket(*entry));
+
+    ++m_keyCount;
+
+    if (shouldExpand())
+        entry = expand(entry);
+
+    return AddResult(this, entry, true);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T, typename Extra>
+typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::AddResult HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::addPassingHashCode(const T& key, const Extra& extra)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    if (!m_table)
+        expand();
+
+    FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key);
+
+    ValueType* entry = lookupResult.first.first;
+    bool found = lookupResult.first.second;
+    unsigned h = lookupResult.second;
+
+    if (found)
+        return AddResult(this, entry, false);
+
+    registerModification();
+
+    if (isDeletedBucket(*entry)) {
+        initializeBucket(*entry);
+        --m_deletedCount;
+    }
+
+    HashTranslator::translate(*entry, key, extra, h);
+    ASSERT(!isEmptyOrDeletedBucket(*entry));
+
+    ++m_keyCount;
+    if (shouldExpand())
+        entry = expand(entry);
+
+    return AddResult(this, entry, true);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::reinsert(ValueType& entry)
+{
+    ASSERT(m_table);
+    registerModification();
+    ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
+    ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
+#if DUMP_HASHTABLE_STATS
+    atomicIncrement(&HashTableStats::numReinserts);
+#endif
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    ++m_stats->numReinserts;
+#endif
+    Value* newEntry = lookupForWriting(Extractor::extract(entry)).first;
+    Mover<ValueType, Allocator>::move(entry, *newEntry);
+
+    return newEntry;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key)
+{
+    ValueType* entry = lookup<HashTranslator>(key);
+    if (!entry)
+        return end();
+
+    return makeKnownGoodIterator(entry);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::find(const T& key) const
+{
+    ValueType* entry = const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
+    if (!entry)
+        return end();
+
+    return makeKnownGoodConstIterator(entry);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename HashTranslator, typename T>
+bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::contains(const T& key) const
+{
+    return const_cast<HashTable*>(this)->lookup<HashTranslator>(key);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(ValueType* pos)
+{
+    registerModification();
+#if DUMP_HASHTABLE_STATS
+    atomicIncrement(&HashTableStats::numRemoves);
+#endif
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    ++m_stats->numRemoves;
+#endif
+
+    deleteBucket(*pos);
+    ++m_deletedCount;
+    --m_keyCount;
+
+    if (shouldShrink())
+        shrink();
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(iterator it)
+{
+    if (it == end())
+        return;
+    remove(const_cast<ValueType*>(it.m_iterator.m_position));
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(const_iterator it)
+{
+    if (it == end())
+        return;
+    remove(const_cast<ValueType*>(it.m_position));
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::remove(KeyPeekInType key)
+{
+    remove(find(key));
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::allocateTable(unsigned size)
+{
+    size_t allocSize = size * sizeof(ValueType);
+    ValueType* result;
+    // Assert that we will not use memset on things with a vtable entry.  The
+    // compiler will also check this on some platforms. We would like to check
+    // this on the whole value (key-value pair), but IsPolymorphic will return
+    // false for a pair of two types, even if one of the components is
+    // polymorphic.
+    static_assert(!Traits::emptyValueIsZero || !IsPolymorphic<KeyType>::value, "empty value cannot be zero for things with a vtable");
+
+#if ENABLE(OILPAN)
+    static_assert(Allocator::isGarbageCollected
+        || ((!IsAllowOnlyInlineAllocation<KeyType>::value || !NeedsTracing<KeyType>::value)
+        && (!IsAllowOnlyInlineAllocation<ValueType>::value || !NeedsTracing<ValueType>::value))
+        , "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap HashTable");
+#endif
+    if (Traits::emptyValueIsZero) {
+        result = Allocator::template allocateZeroedHashTableBacking<ValueType, HashTable>(allocSize);
+    } else {
+        result = Allocator::template allocateHashTableBacking<ValueType, HashTable>(allocSize);
+        for (unsigned i = 0; i < size; i++)
+            initializeBucket(result[i]);
+    }
+    return result;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::deleteAllBucketsAndDeallocate(ValueType* table, unsigned size)
+{
+    if (!IsTriviallyDestructible<ValueType>::value) {
+        for (unsigned i = 0; i < size; ++i) {
+            // This code is called when the hash table is cleared or resized. We
+            // have allocated a new backing store and we need to run the
+            // destructors on the old backing store, as it is being freed. If we
+            // are GCing we need to both call the destructor and mark the bucket
+            // as deleted, otherwise the destructor gets called again when the
+            // GC finds the backing store. With the default allocator it's
+            // enough to call the destructor, since we will free the memory
+            // explicitly and we won't see the memory with the bucket again.
+            if (Allocator::isGarbageCollected) {
+                if (!isEmptyOrDeletedBucket(table[i]))
+                    deleteBucket(table[i]);
+            } else {
+                if (!isDeletedBucket(table[i]))
+                    table[i].~ValueType();
+            }
+        }
+    }
+    Allocator::freeHashTableBacking(table);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::expand(Value* entry)
+{
+    unsigned newSize;
+    if (!m_tableSize) {
+        newSize = KeyTraits::minimumTableSize;
+    } else if (mustRehashInPlace()) {
+        newSize = m_tableSize;
+    } else {
+        newSize = m_tableSize * 2;
+        RELEASE_ASSERT(newSize > m_tableSize);
+    }
+
+    return rehash(newSize, entry);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::expandBuffer(unsigned newTableSize, Value* entry, bool& success)
+{
+    success = false;
+    ASSERT(m_tableSize < newTableSize);
+    if (!Allocator::expandHashTableBacking(m_table, newTableSize * sizeof(ValueType)))
+        return nullptr;
+
+    success = true;
+
+    Value* newEntry = nullptr;
+    unsigned oldTableSize = m_tableSize;
+    ValueType* originalTable = m_table;
+
+    ValueType* temporaryTable = allocateTable(oldTableSize);
+    for (unsigned i = 0; i < oldTableSize; i++) {
+        if (&m_table[i] == entry)
+            newEntry = &temporaryTable[i];
+        if (isEmptyOrDeletedBucket(m_table[i])) {
+            ASSERT(&m_table[i] != entry);
+            if (Traits::emptyValueIsZero) {
+                memset(&temporaryTable[i], 0, sizeof(ValueType));
+            } else {
+                initializeBucket(temporaryTable[i]);
+            }
+        } else {
+            Mover<ValueType, Allocator>::move(m_table[i], temporaryTable[i]);
+        }
+    }
+    m_table = temporaryTable;
+
+    if (Traits::emptyValueIsZero) {
+        memset(originalTable, 0, newTableSize * sizeof(ValueType));
+    } else {
+        for (unsigned i = 0; i < newTableSize; i++)
+            initializeBucket(originalTable[i]);
+    }
+    newEntry = rehashTo(originalTable, newTableSize, newEntry);
+    deleteAllBucketsAndDeallocate(temporaryTable, oldTableSize);
+
+    return newEntry;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehashTo(ValueType* newTable, unsigned newTableSize, Value* entry)
+{
+    unsigned oldTableSize = m_tableSize;
+    ValueType* oldTable = m_table;
+
+#if DUMP_HASHTABLE_STATS
+    if (oldTableSize != 0)
+        atomicIncrement(&HashTableStats::numRehashes);
+#endif
+
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    if (oldTableSize != 0)
+        ++m_stats->numRehashes;
+#endif
+
+    m_table = newTable;
+    m_tableSize = newTableSize;
+
+    Value* newEntry = nullptr;
+    for (unsigned i = 0; i != oldTableSize; ++i) {
+        if (isEmptyOrDeletedBucket(oldTable[i])) {
+            ASSERT(&oldTable[i] != entry);
+            continue;
+        }
+        Value* reinsertedEntry = reinsert(oldTable[i]);
+        if (&oldTable[i] == entry) {
+            ASSERT(!newEntry);
+            newEntry = reinsertedEntry;
+        }
+    }
+
+    m_deletedCount = 0;
+
+    return newEntry;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::rehash(unsigned newTableSize, Value* entry)
+{
+    unsigned oldTableSize = m_tableSize;
+    ValueType* oldTable = m_table;
+
+#if DUMP_HASHTABLE_STATS
+    if (oldTableSize != 0)
+        atomicIncrement(&HashTableStats::numRehashes);
+#endif
+
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    if (oldTableSize != 0)
+        ++m_stats->numRehashes;
+#endif
+
+    // The Allocator::isGarbageCollected check is not needed.  The check is just
+    // a static hint for a compiler to indicate that Base::expandBuffer returns
+    // false if Allocator is a DefaultAllocator.
+    if (Allocator::isGarbageCollected && newTableSize > oldTableSize) {
+        bool success;
+        Value* newEntry = expandBuffer(newTableSize, entry, success);
+        if (success)
+            return newEntry;
+    }
+
+    ValueType* newTable = allocateTable(newTableSize);
+    Value* newEntry = rehashTo(newTable, newTableSize, entry);
+    deleteAllBucketsAndDeallocate(oldTable, oldTableSize);
+
+    return newEntry;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::clear()
+{
+    registerModification();
+    if (!m_table)
+        return;
+
+    deleteAllBucketsAndDeallocate(m_table, m_tableSize);
+    m_table = nullptr;
+    m_tableSize = 0;
+    m_keyCount = 0;
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::HashTable(const HashTable& other)
+    : m_table(nullptr)
+    , m_tableSize(0)
+    , m_keyCount(0)
+    , m_deletedCount(0)
+    , m_queueFlag(false)
+#if ENABLE(ASSERT)
+    , m_modifications(0)
+#endif
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    , m_stats(adoptPtr(new Stats(*other.m_stats)))
+#endif
+{
+    // Copy the hash table the dumb way, by adding each element to the new
+    // table.  It might be more efficient to copy the table slots, but it's not
+    // clear that efficiency is needed.
+    const_iterator end = other.end();
+    for (const_iterator it = other.begin(); it != end; ++it)
+        add(*it);
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::swap(HashTable& other)
+{
+    std::swap(m_table, other.m_table);
+    std::swap(m_tableSize, other.m_tableSize);
+    std::swap(m_keyCount, other.m_keyCount);
+    // std::swap does not work for bit fields.
+    unsigned deleted = m_deletedCount;
+    m_deletedCount = other.m_deletedCount;
+    other.m_deletedCount = deleted;
+    ASSERT(!m_queueFlag);
+    ASSERT(!other.m_queueFlag);
+
+#if ENABLE(ASSERT)
+    std::swap(m_modifications, other.m_modifications);
+#endif
+
+#if DUMP_HASHTABLE_STATS_PER_TABLE
+    m_stats.swap(other.m_stats);
+#endif
+}
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::operator=(const HashTable& other)
+{
+    HashTable tmp(other);
+    swap(tmp);
+    return *this;
+}
+
+template <WeakHandlingFlag weakHandlingFlag, typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+struct WeakProcessingHashTableHelper;
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+struct WeakProcessingHashTableHelper<NoWeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
+    static void process(typename Allocator::Visitor* visitor, void* closure) {}
+    static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure) {}
+    static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure) {}
+};
+
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+struct WeakProcessingHashTableHelper<WeakHandlingInCollections, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> {
+    // Used for purely weak and for weak-and-strong tables (ephemerons).
+    static void process(typename Allocator::Visitor* visitor, void* closure)
+    {
+        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
+        HashTableType* table = reinterpret_cast<HashTableType*>(closure);
+        ASSERT(table->m_table);
+        // Now perform weak processing (this is a no-op if the backing was
+        // accessible through an iterator and was already marked strongly).
+        typedef typename HashTableType::ValueType ValueType;
+        for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
+            if (!HashTableType::isEmptyOrDeletedBucket(*element)) {
+                // At this stage calling trace can make no difference
+                // (everything is already traced), but we use the return value
+                // to remove things from the collection.
+
+                // FIXME: This should be rewritten so that this can check if the
+                // element is dead without calling trace, which is semantically
+                // not correct to be called in weak processing stage.
+                if (TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element)) {
+                    table->registerModification();
+                    HashTableType::deleteBucket(*element); // Also calls the destructor.
+                    table->m_deletedCount++;
+                    table->m_keyCount--;
+                    // We don't rehash the backing until the next add or delete,
+                    // because that would cause allocation during GC.
                 }
-                // We don't need to trace the elements here, since registering
-                // as a weak table above will cause them to be traced (perhaps
-                // several times). It's better to wait until everything else is
-                // traced before tracing the elements for the first time; this
-                // may reduce (by one) the number of iterations needed to get
-                // to a fixed point.
-                return;
-            }
-            for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
-                if (!isEmptyOrDeletedBucket(*element))
-                    Allocator::template trace<VisitorDispatcher, ValueType, Traits>(visitor, *element);
             }
         }
     }
 
-    // iterator adapters
-
-    template<typename HashTableType, typename Traits> struct HashTableConstIteratorAdapter {
-        HashTableConstIteratorAdapter() {}
-        HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
-        typedef typename Traits::IteratorConstGetType GetType;
-        typedef typename HashTableType::ValueTraits::IteratorConstGetType SourceGetType;
-
-        GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
-        typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
-        GetType operator->() const { return get(); }
-
-        HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        typename HashTableType::const_iterator m_impl;
-    };
-
-    template<typename HashTableType, typename Traits> struct HashTableIteratorAdapter {
-        typedef typename Traits::IteratorGetType GetType;
-        typedef typename HashTableType::ValueTraits::IteratorGetType SourceGetType;
-
-        HashTableIteratorAdapter() {}
-        HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
-
-        GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
-        typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
-        GetType operator->() const { return get(); }
-
-        HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstIteratorAdapter<HashTableType, Traits>()
-        {
-            typename HashTableType::const_iterator i = m_impl;
-            return i;
+    // Called repeatedly for tables that have both weak and strong pointers.
+    static void ephemeronIteration(typename Allocator::Visitor* visitor, void* closure)
+    {
+        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
+        HashTableType* table = reinterpret_cast<HashTableType*>(closure);
+        ASSERT(table->m_table);
+        // Check the hash table for elements that we now know will not be
+        // removed by weak processing. Those elements need to have their strong
+        // pointers traced.
+        typedef typename HashTableType::ValueType ValueType;
+        for (ValueType* element = table->m_table + table->m_tableSize - 1; element >= table->m_table; element--) {
+            if (!HashTableType::isEmptyOrDeletedBucket(*element))
+                TraceInCollectionTrait<WeakHandlingInCollections, WeakPointersActWeak, ValueType, Traits>::trace(visitor, *element);
         }
-
-        typename HashTableType::iterator m_impl;
-    };
-
-    template<typename T, typename U>
-    inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
     }
 
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
+    // Called when the ephemeron iteration is done and before running the per
+    // thread weak processing. It is guaranteed to be called before any thread
+    // is resumed.
+    static void ephemeronIterationDone(typename Allocator::Visitor* visitor, void* closure)
     {
-        return a.m_impl != b.m_impl;
+        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator> HashTableType;
+        HashTableType* table = reinterpret_cast<HashTableType*>(closure);
+        ASSERT(Allocator::weakTableRegistered(visitor, table));
+        table->clearEnqueued();
     }
+};
 
-    template<typename T, typename U>
-    inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
+template <typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits, typename Allocator>
+template <typename VisitorDispatcher>
+void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::trace(VisitorDispatcher visitor)
+{
+    // If someone else already marked the backing and queued up the trace and/or
+    // weak callback then we are done. This optimization does not happen for
+    // ListHashSet since its iterator does not point at the backing.
+    if (!m_table || Allocator::isHeapObjectAlive(m_table))
+        return;
+    // Normally, we mark the backing store without performing trace. This means
+    // it is marked live, but the pointers inside it are not marked.  Instead we
+    // will mark the pointers below. However, for backing stores that contain
+    // weak pointers the handling is rather different.  We don't mark the
+    // backing store here, so the marking GC will leave the backing unmarked. If
+    // the backing is found in any other way than through its HashTable (ie from
+    // an iterator) then the mark bit will be set and the pointers will be
+    // marked strongly, avoiding problems with iterating over things that
+    // disappear due to weak processing while we are iterating over them. We
+    // register the backing store pointer for delayed marking which will take
+    // place after we know if the backing is reachable from elsewhere. We also
+    // register a weakProcessing callback which will perform weak processing if
+    // needed.
+    if (Traits::weakHandlingFlag == NoWeakHandlingInCollections) {
+        Allocator::markNoTracing(visitor, m_table);
+    } else {
+        Allocator::registerDelayedMarkNoTracing(visitor, m_table);
+        // Since we're delaying marking this HashTable, it is possible that the
+        // registerWeakMembers is called multiple times (in rare
+        // cases). However, it shouldn't cause any issue.
+        Allocator::registerWeakMembers(visitor, this, m_table, WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::process);
     }
-
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    // All 4 combinations of ==, != and Const,non const.
-    template<typename T, typename U>
-    inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename Collection1, typename Collection2>
-    inline void removeAll(Collection1& collection, const Collection2& toBeRemoved)
-    {
-        if (collection.isEmpty() || toBeRemoved.isEmpty())
+    if (ShouldBeTraced<Traits>::value) {
+        if (Traits::weakHandlingFlag == WeakHandlingInCollections) {
+            // If we have both strong and weak pointers in the collection then
+            // we queue up the collection for fixed point iteration a la
+            // Ephemerons:
+            // http://dl.acm.org/citation.cfm?doid=263698.263733 - see also
+            // http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
+            ASSERT(!enqueued() || Allocator::weakTableRegistered(visitor, this));
+            if (!enqueued()) {
+                Allocator::registerWeakTable(visitor, this,
+                    WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIteration,
+                    WeakProcessingHashTableHelper<Traits::weakHandlingFlag, Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::ephemeronIterationDone);
+                setEnqueued();
+            }
+            // We don't need to trace the elements here, since registering as a
+            // weak table above will cause them to be traced (perhaps several
+            // times). It's better to wait until everything else is traced
+            // before tracing the elements for the first time; this may reduce
+            // (by one) the number of iterations needed to get to a fixed point.
             return;
-        typedef typename Collection2::const_iterator CollectionIterator;
-        CollectionIterator end(toBeRemoved.end());
-        for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it)
-            collection.remove(*it);
+        }
+        for (ValueType* element = m_table + m_tableSize - 1; element >= m_table; element--) {
+            if (!isEmptyOrDeletedBucket(*element))
+                Allocator::template trace<VisitorDispatcher, ValueType, Traits>(visitor, *element);
+        }
     }
+}
+
+// iterator adapters
+
+template <typename HashTableType, typename Traits> struct HashTableConstIteratorAdapter {
+    HashTableConstIteratorAdapter() {}
+    HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
+    typedef typename Traits::IteratorConstGetType GetType;
+    typedef typename HashTableType::ValueTraits::IteratorConstGetType SourceGetType;
+
+    GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
+    typename Traits::IteratorConstReferenceType operator*() const { return Traits::getToReferenceConstConversion(get()); }
+    GetType operator->() const { return get(); }
+
+    HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    typename HashTableType::const_iterator m_impl;
+};
+
+template <typename HashTableType, typename Traits> struct HashTableIteratorAdapter {
+    typedef typename Traits::IteratorGetType GetType;
+    typedef typename HashTableType::ValueTraits::IteratorGetType SourceGetType;
+
+    HashTableIteratorAdapter() {}
+    HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
+
+    GetType get() const { return const_cast<GetType>(SourceGetType(m_impl.get())); }
+    typename Traits::IteratorReferenceType operator*() const { return Traits::getToReferenceConversion(get()); }
+    GetType operator->() const { return get(); }
+
+    HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
+    // postfix ++ intentionally omitted
+
+    operator HashTableConstIteratorAdapter<HashTableType, Traits>()
+    {
+        typename HashTableType::const_iterator i = m_impl;
+        return i;
+    }
+
+    typename HashTableType::iterator m_impl;
+};
+
+template <typename T, typename U>
+inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
+{
+    return a.m_impl != b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
+{
+    return a.m_impl != b.m_impl;
+}
+
+// All 4 combinations of ==, != and Const,non const.
+template <typename T, typename U>
+inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
+{
+    return a.m_impl != b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
+{
+    return a.m_impl == b.m_impl;
+}
+
+template <typename T, typename U>
+inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
+{
+    return a.m_impl != b.m_impl;
+}
+
+template <typename Collection1, typename Collection2>
+inline void removeAll(Collection1& collection, const Collection2& toBeRemoved)
+{
+    if (collection.isEmpty() || toBeRemoved.isEmpty())
+        return;
+    typedef typename Collection2::const_iterator CollectionIterator;
+    CollectionIterator end(toBeRemoved.end());
+    for (CollectionIterator it(toBeRemoved.begin()); it != end; ++it)
+        collection.remove(*it);
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/HashTraits.h b/third_party/WebKit/Source/wtf/HashTraits.h
index 371011fa..51d89726 100644
--- a/third_party/WebKit/Source/wtf/HashTraits.h
+++ b/third_party/WebKit/Source/wtf/HashTraits.h
@@ -31,282 +31,285 @@
 
 namespace WTF {
 
-    class String;
+class String;
+template <bool isInteger, typename T> struct GenericHashTraitsBase;
+template <typename T> class OwnPtr;
+template <typename T> class PassOwnPtr;
+template <typename T> struct HashTraits;
 
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnPtr;
+enum ShouldWeakPointersBeMarkedStrongly {
+    WeakPointersActStrong,
+    WeakPointersActWeak
+};
 
-    template<typename T> struct HashTraits;
+template <typename T> struct GenericHashTraitsBase<false, T> {
+    // The emptyValueIsZero flag is used to optimize allocation of empty hash
+    // tables with zeroed memory.
+    static const bool emptyValueIsZero = false;
 
-    template<bool isInteger, typename T> struct GenericHashTraitsBase;
+    // The hasIsEmptyValueFunction flag allows the hash table to automatically
+    // generate code to check for the empty value when it can be done with the
+    // equality operator, but allows custom functions for cases like String that
+    // need them.
+    static const bool hasIsEmptyValueFunction = false;
 
-    enum ShouldWeakPointersBeMarkedStrongly {
-        WeakPointersActStrong,
-        WeakPointersActWeak
-    };
-
-    template<typename T> struct GenericHashTraitsBase<false, T> {
-        // The emptyValueIsZero flag is used to optimize allocation of empty hash tables with zeroed memory.
-        static const bool emptyValueIsZero = false;
-
-        // The hasIsEmptyValueFunction flag allows the hash table to automatically generate code to check
-        // for the empty value when it can be done with the equality operator, but allows custom functions
-        // for cases like String that need them.
-        static const bool hasIsEmptyValueFunction = false;
-
-        // The starting table size. Can be overridden when we know beforehand that
-        // a hash table will have at least N entries.
+    // The starting table size. Can be overridden when we know beforehand that a
+    // hash table will have at least N entries.
 #if defined(MEMORY_SANITIZER_INITIAL_SIZE)
-        static const unsigned minimumTableSize = 1;
+    static const unsigned minimumTableSize = 1;
 #else
-        static const unsigned minimumTableSize = 8;
+    static const unsigned minimumTableSize = 8;
 #endif
 
-        template<typename U = void>
-        struct NeedsTracingLazily {
-            static const bool value = NeedsTracing<T>::value;
-        };
-        static const WeakHandlingFlag weakHandlingFlag = IsWeak<T>::value ? WeakHandlingInCollections : NoWeakHandlingInCollections;
+    template <typename U = void>
+    struct NeedsTracingLazily {
+        static const bool value = NeedsTracing<T>::value;
     };
+    static const WeakHandlingFlag weakHandlingFlag = IsWeak<T>::value ? WeakHandlingInCollections : NoWeakHandlingInCollections;
+};
 
-    // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned).
-    template<typename T> struct GenericHashTraitsBase<true, T> : GenericHashTraitsBase<false, T> {
-        static const bool emptyValueIsZero = true;
-        static void constructDeletedValue(T& slot, bool) { slot = static_cast<T>(-1); }
-        static bool isDeletedValue(T value) { return value == static_cast<T>(-1); }
-    };
+// Default integer traits disallow both 0 and -1 as keys (max value instead of
+// -1 for unsigned).
+template <typename T> struct GenericHashTraitsBase<true, T> : GenericHashTraitsBase<false, T> {
+    static const bool emptyValueIsZero = true;
+    static void constructDeletedValue(T& slot, bool) { slot = static_cast<T>(-1); }
+    static bool isDeletedValue(T value) { return value == static_cast<T>(-1); }
+};
 
-    template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> {
-        typedef T TraitType;
-        typedef T EmptyValueType;
+template <typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> {
+    typedef T TraitType;
+    typedef T EmptyValueType;
 
-        static T emptyValue() { return T(); }
+    static T emptyValue() { return T(); }
 
-        // Type for functions that do not take ownership, such as contains.
-        typedef const T& PeekInType;
-        typedef T* IteratorGetType;
-        typedef const T* IteratorConstGetType;
-        typedef T& IteratorReferenceType;
-        typedef const T& IteratorConstReferenceType;
-        static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
-        static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; }
-        // Type for functions that take ownership, such as add.
-        // The store function either not be called or called once to store something passed in.
-        // The value passed to the store function will be PassInType.
-        typedef const T& PassInType;
-        static void store(const T& value, T& storage) { storage = value; }
+    // Type for functions that do not take ownership, such as contains.
+    typedef const T& PeekInType;
+    typedef T* IteratorGetType;
+    typedef const T* IteratorConstGetType;
+    typedef T& IteratorReferenceType;
+    typedef const T& IteratorConstReferenceType;
+    static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
+    static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; }
+    // Type for functions that take ownership, such as add.
+    // The store function either not be called or called once to store something
+    // passed in.  The value passed to the store function will be PassInType.
+    typedef const T& PassInType;
+    static void store(const T& value, T& storage) { storage = value; }
 
-        // Type for return value of functions that transfer ownership, such as take.
-        typedef T PassOutType;
-        static const T& passOut(const T& value) { return value; }
+    // Type for return value of functions that transfer ownership, such as take.
+    typedef T PassOutType;
+    static const T& passOut(const T& value) { return value; }
 
-        // Type for return value of functions that do not transfer ownership, such as get.
-        // FIXME: We could change this type to const T& for better performance if we figured out
-        // a way to handle the return value from emptyValue, which is a temporary.
-        typedef T PeekOutType;
-        static const T& peek(const T& value) { return value; }
-    };
+    // Type for return value of functions that do not transfer ownership, such
+    // as get.
+    // FIXME: We could change this type to const T& for better performance if we
+    // figured out a way to handle the return value from emptyValue, which is a
+    // temporary.
+    typedef T PeekOutType;
+    static const T& peek(const T& value) { return value; }
+};
 
-    template<typename T> struct HashTraits : GenericHashTraits<T> { };
+template <typename T> struct HashTraits : GenericHashTraits<T> { };
 
-    template<typename T> struct FloatHashTraits : GenericHashTraits<T> {
-        static T emptyValue() { return std::numeric_limits<T>::infinity(); }
-        static void constructDeletedValue(T& slot, bool) { slot = -std::numeric_limits<T>::infinity(); }
-        static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); }
-    };
+template <typename T> struct FloatHashTraits : GenericHashTraits<T> {
+    static T emptyValue() { return std::numeric_limits<T>::infinity(); }
+    static void constructDeletedValue(T& slot, bool) { slot = -std::numeric_limits<T>::infinity(); }
+    static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); }
+};
 
-    template<> struct HashTraits<float> : FloatHashTraits<float> { };
-    template<> struct HashTraits<double> : FloatHashTraits<double> { };
+template <> struct HashTraits<float> : FloatHashTraits<float> { };
+template <> struct HashTraits<double> : FloatHashTraits<double> { };
 
-    // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1.
-    template<typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> {
-        static const bool emptyValueIsZero = false;
-        static T emptyValue() { return std::numeric_limits<T>::max(); }
-        static void constructDeletedValue(T& slot, bool) { slot = std::numeric_limits<T>::max() - 1; }
-        static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; }
-    };
+// Default unsigned traits disallow both 0 and max as keys -- use these traits
+// to allow zero and disallow max - 1.
+template <typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> {
+    static const bool emptyValueIsZero = false;
+    static T emptyValue() { return std::numeric_limits<T>::max(); }
+    static void constructDeletedValue(T& slot, bool) { slot = std::numeric_limits<T>::max() - 1; }
+    static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; }
+};
 
-    template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> {
-        static const bool emptyValueIsZero = true;
-        static void constructDeletedValue(P*& slot, bool) { slot = reinterpret_cast<P*>(-1); }
-        static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
-    };
+template <typename P> struct HashTraits<P*> : GenericHashTraits<P*> {
+    static const bool emptyValueIsZero = true;
+    static void constructDeletedValue(P*& slot, bool) { slot = reinterpret_cast<P*>(-1); }
+    static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
+};
 
-    template<typename T> struct SimpleClassHashTraits : GenericHashTraits<T> {
-        static const bool emptyValueIsZero = true;
-        static void constructDeletedValue(T& slot, bool) { new (NotNull, &slot) T(HashTableDeletedValue); }
-        static bool isDeletedValue(const T& value) { return value.isHashTableDeletedValue(); }
-    };
+template <typename T> struct SimpleClassHashTraits : GenericHashTraits<T> {
+    static const bool emptyValueIsZero = true;
+    static void constructDeletedValue(T& slot, bool) { new (NotNull, &slot) T(HashTableDeletedValue); }
+    static bool isDeletedValue(const T& value) { return value.isHashTableDeletedValue(); }
+};
 
-    template<typename P> struct HashTraits<OwnPtr<P>> : SimpleClassHashTraits<OwnPtr<P>> {
-        typedef std::nullptr_t EmptyValueType;
+template <typename P> struct HashTraits<OwnPtr<P>> : SimpleClassHashTraits<OwnPtr<P>> {
+    typedef std::nullptr_t EmptyValueType;
 
-        static EmptyValueType emptyValue() { return nullptr; }
+    static EmptyValueType emptyValue() { return nullptr; }
 
-        static const bool hasIsEmptyValueFunction = true;
-        static bool isEmptyValue(const OwnPtr<P>& value) { return !value; }
+    static const bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const OwnPtr<P>& value) { return !value; }
 
-        typedef typename OwnPtr<P>::PtrType PeekInType;
+    typedef typename OwnPtr<P>::PtrType PeekInType;
 
-        typedef PassOwnPtr<P> PassInType;
-        static void store(PassOwnPtr<P> value, OwnPtr<P>& storage) { storage = value; }
+    typedef PassOwnPtr<P> PassInType;
+    static void store(PassOwnPtr<P> value, OwnPtr<P>& storage) { storage = value; }
 
-        typedef PassOwnPtr<P> PassOutType;
-        static PassOwnPtr<P> passOut(OwnPtr<P>& value) { return value.release(); }
-        static PassOwnPtr<P> passOut(std::nullptr_t) { return nullptr; }
+    typedef PassOwnPtr<P> PassOutType;
+    static PassOwnPtr<P> passOut(OwnPtr<P>& value) { return value.release(); }
+    static PassOwnPtr<P> passOut(std::nullptr_t) { return nullptr; }
 
-        typedef typename OwnPtr<P>::PtrType PeekOutType;
-        static PeekOutType peek(const OwnPtr<P>& value) { return value.get(); }
-        static PeekOutType peek(std::nullptr_t) { return 0; }
-    };
+    typedef typename OwnPtr<P>::PtrType PeekOutType;
+    static PeekOutType peek(const OwnPtr<P>& value) { return value.get(); }
+    static PeekOutType peek(std::nullptr_t) { return 0; }
+};
 
-    template<typename P> struct HashTraits<RefPtr<P>> : SimpleClassHashTraits<RefPtr<P>> {
-        typedef std::nullptr_t EmptyValueType;
-        static EmptyValueType emptyValue() { return nullptr; }
+template <typename P> struct HashTraits<RefPtr<P>> : SimpleClassHashTraits<RefPtr<P>> {
+    typedef std::nullptr_t EmptyValueType;
+    static EmptyValueType emptyValue() { return nullptr; }
 
-        static const bool hasIsEmptyValueFunction = true;
-        static bool isEmptyValue(const RefPtr<P>& value) { return !value; }
+    static const bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const RefPtr<P>& value) { return !value; }
 
-        typedef RefPtrValuePeeker<P> PeekInType;
-        typedef RefPtr<P>* IteratorGetType;
-        typedef const RefPtr<P>* IteratorConstGetType;
-        typedef RefPtr<P>& IteratorReferenceType;
-        typedef const RefPtr<P>& IteratorConstReferenceType;
-        static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
-        static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; }
+    typedef RefPtrValuePeeker<P> PeekInType;
+    typedef RefPtr<P>* IteratorGetType;
+    typedef const RefPtr<P>* IteratorConstGetType;
+    typedef RefPtr<P>& IteratorReferenceType;
+    typedef const RefPtr<P>& IteratorConstReferenceType;
+    static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
+    static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; }
 
-        typedef PassRefPtr<P> PassInType;
-        static void store(PassRefPtr<P> value, RefPtr<P>& storage) { storage = value; }
+    typedef PassRefPtr<P> PassInType;
+    static void store(PassRefPtr<P> value, RefPtr<P>& storage) { storage = value; }
 
-        typedef PassRefPtr<P> PassOutType;
-        static PassOutType passOut(RefPtr<P>& value) { return value.release(); }
-        static PassOutType passOut(std::nullptr_t) { return nullptr; }
+    typedef PassRefPtr<P> PassOutType;
+    static PassOutType passOut(RefPtr<P>& value) { return value.release(); }
+    static PassOutType passOut(std::nullptr_t) { return nullptr; }
 
-        typedef P* PeekOutType;
-        static PeekOutType peek(const RefPtr<P>& value) { return value.get(); }
-        static PeekOutType peek(std::nullptr_t) { return 0; }
-    };
+    typedef P* PeekOutType;
+    static PeekOutType peek(const RefPtr<P>& value) { return value.get(); }
+    static PeekOutType peek(std::nullptr_t) { return 0; }
+};
 
-    template<typename T> struct HashTraits<RawPtr<T>> : HashTraits<T*> { };
+template <typename T> struct HashTraits<RawPtr<T>> : HashTraits<T*> { };
 
-    template<> struct HashTraits<String> : SimpleClassHashTraits<String> {
-        static const bool hasIsEmptyValueFunction = true;
-        static bool isEmptyValue(const String&);
-    };
+template <> struct HashTraits<String> : SimpleClassHashTraits<String> {
+    static const bool hasIsEmptyValueFunction = true;
+    static bool isEmptyValue(const String&);
+};
 
-    // This struct template is an implementation detail of the isHashTraitsEmptyValue function,
-    // which selects either the emptyValue function or the isEmptyValue function to check for empty values.
-    template<typename Traits, bool hasEmptyValueFunction> struct HashTraitsEmptyValueChecker;
-    template<typename Traits> struct HashTraitsEmptyValueChecker<Traits, true> {
-        template<typename T> static bool isEmptyValue(const T& value) { return Traits::isEmptyValue(value); }
-    };
-    template<typename Traits> struct HashTraitsEmptyValueChecker<Traits, false> {
-        template<typename T> static bool isEmptyValue(const T& value) { return value == Traits::emptyValue(); }
-    };
-    template<typename Traits, typename T> inline bool isHashTraitsEmptyValue(const T& value)
+// This struct template is an implementation detail of the
+// isHashTraitsEmptyValue function, which selects either the emptyValue function
+// or the isEmptyValue function to check for empty values.
+template <typename Traits, bool hasEmptyValueFunction> struct HashTraitsEmptyValueChecker;
+template <typename Traits> struct HashTraitsEmptyValueChecker<Traits, true> {
+    template <typename T> static bool isEmptyValue(const T& value) { return Traits::isEmptyValue(value); }
+};
+template <typename Traits> struct HashTraitsEmptyValueChecker<Traits, false> {
+    template <typename T> static bool isEmptyValue(const T& value) { return value == Traits::emptyValue(); }
+};
+template <typename Traits, typename T> inline bool isHashTraitsEmptyValue(const T& value)
+{
+    return HashTraitsEmptyValueChecker<Traits, Traits::hasIsEmptyValueFunction>::isEmptyValue(value);
+}
+
+template <typename FirstTraitsArg, typename SecondTraitsArg>
+struct PairHashTraits : GenericHashTraits<std::pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType>> {
+    typedef FirstTraitsArg FirstTraits;
+    typedef SecondTraitsArg SecondTraits;
+    typedef std::pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
+    typedef std::pair<typename FirstTraits::EmptyValueType, typename SecondTraits::EmptyValueType> EmptyValueType;
+
+    static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
+    static EmptyValueType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
+
+    static const unsigned minimumTableSize = FirstTraits::minimumTableSize;
+
+    static void constructDeletedValue(TraitType& slot, bool zeroValue)
     {
-        return HashTraitsEmptyValueChecker<Traits, Traits::hasIsEmptyValueFunction>::isEmptyValue(value);
+        FirstTraits::constructDeletedValue(slot.first, zeroValue);
+        // For GC collections the memory for the backing is zeroed when it is
+        // allocated, and the constructors may take advantage of that,
+        // especially if a GC occurs during insertion of an entry into the
+        // table. This slot is being marked deleted, but If the slot is reused
+        // at a later point, the same assumptions around memory zeroing must
+        // hold as they did at the initial allocation.  Therefore we zero the
+        // value part of the slot here for GC collections.
+        if (zeroValue)
+            memset(reinterpret_cast<void*>(&slot.second), 0, sizeof(slot.second));
+    }
+    static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
+};
+
+template <typename First, typename Second>
+struct HashTraits<std::pair<First, Second>> : public PairHashTraits<HashTraits<First>, HashTraits<Second>> { };
+
+template <typename KeyTypeArg, typename ValueTypeArg>
+struct KeyValuePair {
+    typedef KeyTypeArg KeyType;
+
+    KeyValuePair(const KeyTypeArg& _key, const ValueTypeArg& _value)
+        : key(_key)
+        , value(_value)
+    {
     }
 
-    template<typename FirstTraitsArg, typename SecondTraitsArg>
-    struct PairHashTraits : GenericHashTraits<std::pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType>> {
-        typedef FirstTraitsArg FirstTraits;
-        typedef SecondTraitsArg SecondTraits;
-        typedef std::pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
-        typedef std::pair<typename FirstTraits::EmptyValueType, typename SecondTraits::EmptyValueType> EmptyValueType;
+    template <typename OtherKeyType, typename OtherValueType>
+    KeyValuePair(const KeyValuePair<OtherKeyType, OtherValueType>& other)
+        : key(other.key)
+        , value(other.value)
+    {
+    }
 
-        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-        static EmptyValueType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
+    KeyTypeArg key;
+    ValueTypeArg value;
+};
 
-        static const unsigned minimumTableSize = FirstTraits::minimumTableSize;
+template <typename KeyTraitsArg, typename ValueTraitsArg>
+struct KeyValuePairHashTraits : GenericHashTraits<KeyValuePair<typename KeyTraitsArg::TraitType, typename ValueTraitsArg::TraitType>> {
+    typedef KeyTraitsArg KeyTraits;
+    typedef ValueTraitsArg ValueTraits;
+    typedef KeyValuePair<typename KeyTraits::TraitType, typename ValueTraits::TraitType> TraitType;
+    typedef KeyValuePair<typename KeyTraits::EmptyValueType, typename ValueTraits::EmptyValueType> EmptyValueType;
 
-        static void constructDeletedValue(TraitType& slot, bool zeroValue)
-        {
-            FirstTraits::constructDeletedValue(slot.first, zeroValue);
-            // For GC collections the memory for the backing is zeroed when it
-            // is allocated, and the constructors may take advantage of that,
-            // especially if a GC occurs during insertion of an entry into the
-            // table. This slot is being marked deleted, but If the slot is
-            // reused at a later point, the same assumptions around memory
-            // zeroing must hold as they did at the initial allocation.
-            // Therefore we zero the value part of the slot here for GC
-            // collections.
-            if (zeroValue)
-                memset(reinterpret_cast<void*>(&slot.second), 0, sizeof(slot.second));
-        }
-        static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
+    static const bool emptyValueIsZero = KeyTraits::emptyValueIsZero && ValueTraits::emptyValueIsZero;
+    static EmptyValueType emptyValue() { return KeyValuePair<typename KeyTraits::EmptyValueType, typename ValueTraits::EmptyValueType>(KeyTraits::emptyValue(), ValueTraits::emptyValue()); }
+
+    template <typename U = void>
+    struct NeedsTracingLazily {
+        static const bool value = ShouldBeTraced<KeyTraits>::value || ShouldBeTraced<ValueTraits>::value;
     };
+    static const WeakHandlingFlag weakHandlingFlag = (KeyTraits::weakHandlingFlag == WeakHandlingInCollections || ValueTraits::weakHandlingFlag == WeakHandlingInCollections) ? WeakHandlingInCollections : NoWeakHandlingInCollections;
 
-    template<typename First, typename Second>
-    struct HashTraits<std::pair<First, Second>> : public PairHashTraits<HashTraits<First>, HashTraits<Second>> { };
+    static const unsigned minimumTableSize = KeyTraits::minimumTableSize;
 
-    template<typename KeyTypeArg, typename ValueTypeArg>
-    struct KeyValuePair {
-        typedef KeyTypeArg KeyType;
+    static void constructDeletedValue(TraitType& slot, bool zeroValue)
+    {
+        KeyTraits::constructDeletedValue(slot.key, zeroValue);
+        // See similar code in this file for why we need to do this.
+        if (zeroValue)
+            memset(reinterpret_cast<void*>(&slot.value), 0, sizeof(slot.value));
+    }
+    static bool isDeletedValue(const TraitType& value) { return KeyTraits::isDeletedValue(value.key); }
+};
 
-        KeyValuePair(const KeyTypeArg& _key, const ValueTypeArg& _value)
-            : key(_key)
-            , value(_value)
-        {
-        }
+template <typename Key, typename Value>
+struct HashTraits<KeyValuePair<Key, Value>> : public KeyValuePairHashTraits<HashTraits<Key>, HashTraits<Value>> { };
 
-        template <typename OtherKeyType, typename OtherValueType>
-        KeyValuePair(const KeyValuePair<OtherKeyType, OtherValueType>& other)
-            : key(other.key)
-            , value(other.value)
-        {
-        }
+template <typename T>
+struct NullableHashTraits : public HashTraits<T> {
+    static const bool emptyValueIsZero = false;
+    static T emptyValue() { return reinterpret_cast<T>(1); }
+};
 
-        KeyTypeArg key;
-        ValueTypeArg value;
-    };
-
-    template<typename KeyTraitsArg, typename ValueTraitsArg>
-    struct KeyValuePairHashTraits : GenericHashTraits<KeyValuePair<typename KeyTraitsArg::TraitType, typename ValueTraitsArg::TraitType>> {
-        typedef KeyTraitsArg KeyTraits;
-        typedef ValueTraitsArg ValueTraits;
-        typedef KeyValuePair<typename KeyTraits::TraitType, typename ValueTraits::TraitType> TraitType;
-        typedef KeyValuePair<typename KeyTraits::EmptyValueType, typename ValueTraits::EmptyValueType> EmptyValueType;
-
-        static const bool emptyValueIsZero = KeyTraits::emptyValueIsZero && ValueTraits::emptyValueIsZero;
-        static EmptyValueType emptyValue() { return KeyValuePair<typename KeyTraits::EmptyValueType, typename ValueTraits::EmptyValueType>(KeyTraits::emptyValue(), ValueTraits::emptyValue()); }
-
-        template<typename U = void>
-        struct NeedsTracingLazily {
-            static const bool value = ShouldBeTraced<KeyTraits>::value || ShouldBeTraced<ValueTraits>::value;
-        };
-        static const WeakHandlingFlag weakHandlingFlag = (KeyTraits::weakHandlingFlag == WeakHandlingInCollections || ValueTraits::weakHandlingFlag == WeakHandlingInCollections) ? WeakHandlingInCollections : NoWeakHandlingInCollections;
-
-        static const unsigned minimumTableSize = KeyTraits::minimumTableSize;
-
-        static void constructDeletedValue(TraitType& slot, bool zeroValue)
-        {
-            KeyTraits::constructDeletedValue(slot.key, zeroValue);
-            // See similar code in this file for why we need to do this.
-            if (zeroValue)
-                memset(reinterpret_cast<void*>(&slot.value), 0, sizeof(slot.value));
-        }
-        static bool isDeletedValue(const TraitType& value) { return KeyTraits::isDeletedValue(value.key); }
-    };
-
-    template<typename Key, typename Value>
-    struct HashTraits<KeyValuePair<Key, Value>> : public KeyValuePairHashTraits<HashTraits<Key>, HashTraits<Value>> { };
-
-    template<typename T>
-    struct NullableHashTraits : public HashTraits<T> {
-        static const bool emptyValueIsZero = false;
-        static T emptyValue() { return reinterpret_cast<T>(1); }
-    };
-
-    // This is for tracing inside collections that have special support for weak
-    // pointers. The trait has a trace method which returns true if there are weak
-    // pointers to things that have not (yet) been marked live. Returning true
-    // indicates that the entry in the collection may yet be removed by weak
-    // handling. Default implementation for non-weak types is to use the regular
-    // non-weak TraceTrait. Default implementation for types with weakness is to
-    // call traceInCollection on the type's trait.
-    template<WeakHandlingFlag weakHandlingFlag, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
-    struct TraceInCollectionTrait;
+// This is for tracing inside collections that have special support for weak
+// pointers. The trait has a trace method which returns true if there are weak
+// pointers to things that have not (yet) been marked live. Returning true
+// indicates that the entry in the collection may yet be removed by weak
+// handling. Default implementation for non-weak types is to use the regular
+// non-weak TraceTrait. Default implementation for types with weakness is to
+// call traceInCollection on the type's trait.
+template <WeakHandlingFlag weakHandlingFlag, ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename Traits>
+struct TraceInCollectionTrait;
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/Int16Array.h b/third_party/WebKit/Source/wtf/Int16Array.h
index 9409ec3..6ecfb9ca 100644
--- a/third_party/WebKit/Source/wtf/Int16Array.h
+++ b/third_party/WebKit/Source/wtf/Int16Array.h
@@ -47,9 +47,7 @@
     }
 
 private:
-    inline Int16Array(PassRefPtr<ArrayBuffer>,
-                    unsigned byteOffset,
-                    unsigned length);
+    inline Int16Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<short>;
 };
diff --git a/third_party/WebKit/Source/wtf/Int32Array.h b/third_party/WebKit/Source/wtf/Int32Array.h
index 151400be..39b98e65 100644
--- a/third_party/WebKit/Source/wtf/Int32Array.h
+++ b/third_party/WebKit/Source/wtf/Int32Array.h
@@ -46,9 +46,7 @@
     }
 
 private:
-    inline Int32Array(PassRefPtr<ArrayBuffer>,
-                  unsigned byteOffset,
-                  unsigned length);
+    inline Int32Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<int>;
 };
diff --git a/third_party/WebKit/Source/wtf/Int8Array.h b/third_party/WebKit/Source/wtf/Int8Array.h
index ac500206..698504f 100644
--- a/third_party/WebKit/Source/wtf/Int8Array.h
+++ b/third_party/WebKit/Source/wtf/Int8Array.h
@@ -48,9 +48,7 @@
     }
 
 private:
-    inline Int8Array(PassRefPtr<ArrayBuffer>,
-                   unsigned byteOffset,
-                   unsigned length);
+    inline Int8Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<signed char>;
 };
diff --git a/third_party/WebKit/Source/wtf/IntegralTypedArrayBase.h b/third_party/WebKit/Source/wtf/IntegralTypedArrayBase.h
index 2d635d8c..f5ba614 100644
--- a/third_party/WebKit/Source/wtf/IntegralTypedArrayBase.h
+++ b/third_party/WebKit/Source/wtf/IntegralTypedArrayBase.h
@@ -27,18 +27,17 @@
 #ifndef IntegralTypedArrayBase_h
 #define IntegralTypedArrayBase_h
 
+#include "wtf/MathExtras.h"
 #include "wtf/TypedArrayBase.h"
 #include <limits>
-#include "wtf/MathExtras.h"
-
-// Base class for all WebGL<T>Array types holding integral
-// (non-floating-point) values.
 
 namespace WTF {
 
+// Base class for all WebGL<T>Array types holding integral
+// (non-floating-point) values.
 template <typename T>
 class IntegralTypedArrayBase : public TypedArrayBase<T> {
-  public:
+public:
     void set(unsigned index, double value)
     {
         if (index >= TypedArrayBase<T>::m_length)
@@ -50,7 +49,7 @@
         TypedArrayBase<T>::data()[index] = static_cast<T>(static_cast<int64_t>(value));
     }
 
-  protected:
+protected:
     IntegralTypedArrayBase(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
         : TypedArrayBase<T>(buffer, byteOffset, length)
     {
diff --git a/third_party/WebKit/Source/wtf/LeakAnnotations.h b/third_party/WebKit/Source/wtf/LeakAnnotations.h
index ec90b8d..f330e170 100644
--- a/third_party/WebKit/Source/wtf/LeakAnnotations.h
+++ b/third_party/WebKit/Source/wtf/LeakAnnotations.h
@@ -55,7 +55,7 @@
 extern "C" {
 void __lsan_disable();
 void __lsan_enable();
-void __lsan_ignore_object(const void *p);
+void __lsan_ignore_object(const void* p);
 } // extern "C"
 
 class LeakSanitizerDisabler {
diff --git a/third_party/WebKit/Source/wtf/ListHashSet.h b/third_party/WebKit/Source/wtf/ListHashSet.h
index 55afc61..8bc3232 100644
--- a/third_party/WebKit/Source/wtf/ListHashSet.h
+++ b/third_party/WebKit/Source/wtf/ListHashSet.h
@@ -29,989 +29,987 @@
 
 namespace WTF {
 
-    // ListHashSet: Just like HashSet, this class provides a Set
-    // interface - a collection of unique objects with O(1) insertion,
-    // removal and test for containership. However, it also has an
-    // order - iterating it will always give back values in the order
-    // in which they are added.
+// ListHashSet: Just like HashSet, this class provides a Set interface - a
+// collection of unique objects with O(1) insertion, removal and test for
+// containership. However, it also has an order - iterating it will always give
+// back values in the order in which they are added.
 
-    // Unlike iteration of most WTF Hash data structures, iteration is
-    // guaranteed safe against mutation of the ListHashSet, except for
-    // removal of the item currently pointed to by a given iterator.
+// Unlike iteration of most WTF Hash data structures, iteration is guaranteed
+// safe against mutation of the ListHashSet, except for removal of the item
+// currently pointed to by a given iterator.
 
-    template<typename Value, size_t inlineCapacity, typename HashFunctions, typename Allocator> class ListHashSet;
+template <typename Value, size_t inlineCapacity, typename HashFunctions, typename Allocator> class ListHashSet;
 
-    template<typename Set> class ListHashSetIterator;
-    template<typename Set> class ListHashSetConstIterator;
-    template<typename Set> class ListHashSetReverseIterator;
-    template<typename Set> class ListHashSetConstReverseIterator;
+template <typename Set> class ListHashSetIterator;
+template <typename Set> class ListHashSetConstIterator;
+template <typename Set> class ListHashSetReverseIterator;
+template <typename Set> class ListHashSetConstReverseIterator;
 
-    template<typename ValueArg> class ListHashSetNodeBase;
-    template<typename ValueArg, typename Allocator> class ListHashSetNode;
-    template<typename ValueArg, size_t inlineCapacity> struct ListHashSetAllocator;
+template <typename ValueArg> class ListHashSetNodeBase;
+template <typename ValueArg, typename Allocator> class ListHashSetNode;
+template <typename ValueArg, size_t inlineCapacity> struct ListHashSetAllocator;
 
-    template<typename HashArg> struct ListHashSetNodeHashFunctions;
-    template<typename HashArg> struct ListHashSetTranslator;
+template <typename HashArg> struct ListHashSetNodeHashFunctions;
+template <typename HashArg> struct ListHashSetTranslator;
 
-    // Note that for a ListHashSet you cannot specify the HashTraits as a
-    // template argument. It uses the default hash traits for the ValueArg
-    // type.
-    template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash, typename AllocatorArg = ListHashSetAllocator<ValueArg, inlineCapacity>> class ListHashSet
-        : public ConditionalDestructor<ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>, AllocatorArg::isGarbageCollected> {
-        typedef AllocatorArg Allocator;
-        WTF_USE_ALLOCATOR(ListHashSet, Allocator);
+// Note that for a ListHashSet you cannot specify the HashTraits as a template
+// argument. It uses the default hash traits for the ValueArg type.
+template <typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash, typename AllocatorArg = ListHashSetAllocator<ValueArg, inlineCapacity>>
+class ListHashSet : public ConditionalDestructor<ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>, AllocatorArg::isGarbageCollected> {
+    typedef AllocatorArg Allocator;
+    WTF_USE_ALLOCATOR(ListHashSet, Allocator);
 
-        typedef ListHashSetNode<ValueArg, Allocator> Node;
-        typedef HashTraits<Node*> NodeTraits;
-        typedef ListHashSetNodeHashFunctions<HashArg> NodeHash;
-        typedef ListHashSetTranslator<HashArg> BaseTranslator;
+    typedef ListHashSetNode<ValueArg, Allocator> Node;
+    typedef HashTraits<Node*> NodeTraits;
+    typedef ListHashSetNodeHashFunctions<HashArg> NodeHash;
+    typedef ListHashSetTranslator<HashArg> BaseTranslator;
 
-        typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplType;
-        typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeIterator;
-        typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeConstIterator;
+    typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplType;
+    typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeIterator;
+    typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits, typename Allocator::TableAllocator> ImplTypeConstIterator;
 
-        typedef HashArg HashFunctions;
+    typedef HashArg HashFunctions;
 
-    public:
-        typedef ValueArg ValueType;
-        typedef HashTraits<ValueType> ValueTraits;
-        typedef typename ValueTraits::PeekInType ValuePeekInType;
-        typedef typename ValueTraits::PassInType ValuePassInType;
-        typedef typename ValueTraits::PassOutType ValuePassOutType;
+public:
+    typedef ValueArg ValueType;
+    typedef HashTraits<ValueType> ValueTraits;
+    typedef typename ValueTraits::PeekInType ValuePeekInType;
+    typedef typename ValueTraits::PassInType ValuePassInType;
+    typedef typename ValueTraits::PassOutType ValuePassOutType;
 
-        typedef ListHashSetIterator<ListHashSet> iterator;
-        typedef ListHashSetConstIterator<ListHashSet> const_iterator;
-        friend class ListHashSetIterator<ListHashSet>;
-        friend class ListHashSetConstIterator<ListHashSet>;
+    typedef ListHashSetIterator<ListHashSet> iterator;
+    typedef ListHashSetConstIterator<ListHashSet> const_iterator;
+    friend class ListHashSetIterator<ListHashSet>;
+    friend class ListHashSetConstIterator<ListHashSet>;
 
-        typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator;
-        typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator;
-        friend class ListHashSetReverseIterator<ListHashSet>;
-        friend class ListHashSetConstReverseIterator<ListHashSet>;
+    typedef ListHashSetReverseIterator<ListHashSet> reverse_iterator;
+    typedef ListHashSetConstReverseIterator<ListHashSet> const_reverse_iterator;
+    friend class ListHashSetReverseIterator<ListHashSet>;
+    friend class ListHashSetConstReverseIterator<ListHashSet>;
 
-        template<typename ValueType> struct HashTableAddResult {
+    template <typename ValueType> struct HashTableAddResult {
         HashTableAddResult(Node* storedValue, bool isNewEntry) : storedValue(storedValue), isNewEntry(isNewEntry) { }
-            Node* storedValue;
-            bool isNewEntry;
-        };
-        typedef HashTableAddResult<ValueType> AddResult;
-
-        ListHashSet();
-        ListHashSet(const ListHashSet&);
-        ListHashSet& operator=(const ListHashSet&);
-        void finalize();
-
-        void swap(ListHashSet&);
-
-        unsigned size() const { return m_impl.size(); }
-        unsigned capacity() const { return m_impl.capacity(); }
-        bool isEmpty() const { return m_impl.isEmpty(); }
-
-        iterator begin() { return makeIterator(m_head); }
-        iterator end() { return makeIterator(0); }
-        const_iterator begin() const { return makeConstIterator(m_head); }
-        const_iterator end() const { return makeConstIterator(0); }
-
-        reverse_iterator rbegin() { return makeReverseIterator(m_tail); }
-        reverse_iterator rend() { return makeReverseIterator(0); }
-        const_reverse_iterator rbegin() const { return makeConstReverseIterator(m_tail); }
-        const_reverse_iterator rend() const { return makeConstReverseIterator(0); }
-
-        ValueType& first();
-        const ValueType& first() const;
-        void removeFirst();
-
-        ValueType& last();
-        const ValueType& last() const;
-        void removeLast();
-
-        iterator find(ValuePeekInType);
-        const_iterator find(ValuePeekInType) const;
-        bool contains(ValuePeekInType) const;
-
-        // An alternate version of find() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion.
-        // The HashTranslator interface is defined in HashSet.
-        template<typename HashTranslator, typename T> iterator find(const T&);
-        template<typename HashTranslator, typename T> const_iterator find(const T&) const;
-        template<typename HashTranslator, typename T> bool contains(const T&) const;
-
-        // The return value of add is a pair of a pointer to the stored value,
-        // and a bool that is true if an new entry was added.
-        AddResult add(ValuePassInType);
-
-        // Same as add() except that the return value is an
-        // iterator. Useful in cases where it's needed to have the
-        // same return value as find() and where it's not possible to
-        // use a pointer to the storedValue.
-        iterator addReturnIterator(ValuePassInType);
-
-        // Add the value to the end of the collection. If the value was already in
-        // the list, it is moved to the end.
-        AddResult appendOrMoveToLast(ValuePassInType);
-
-        // Add the value to the beginning of the collection. If the value was already in
-        // the list, it is moved to the beginning.
-        AddResult prependOrMoveToFirst(ValuePassInType);
-
-        AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue);
-        AddResult insertBefore(iterator, ValuePassInType);
-
-        void remove(ValuePeekInType value) { return remove(find(value)); }
-        void remove(iterator);
-        void clear();
-        template<typename Collection>
-        void removeAll(const Collection& other) { WTF::removeAll(*this, other); }
-
-        ValuePassOutType take(iterator);
-        ValuePassOutType take(ValuePeekInType);
-        ValuePassOutType takeFirst();
-
-        template<typename VisitorDispatcher>
-        void trace(VisitorDispatcher);
-
-    private:
-        void unlink(Node*);
-        void unlinkAndDelete(Node*);
-        void appendNode(Node*);
-        void prependNode(Node*);
-        void insertNodeBefore(Node* beforeNode, Node* newNode);
-        void deleteAllNodes();
-        Allocator* allocator() const { return m_allocatorProvider.get(); }
-        void createAllocatorIfNeeded() { m_allocatorProvider.createAllocatorIfNeeded(); }
-        void deallocate(Node* node) const { m_allocatorProvider.deallocate(node); }
-
-        iterator makeIterator(Node* position) { return iterator(this, position); }
-        const_iterator makeConstIterator(Node* position) const { return const_iterator(this, position); }
-        reverse_iterator makeReverseIterator(Node* position) { return reverse_iterator(this, position); }
-        const_reverse_iterator makeConstReverseIterator(Node* position) const { return const_reverse_iterator(this, position); }
-
-        ImplType m_impl;
-        Node* m_head;
-        Node* m_tail;
-        typename Allocator::AllocatorProvider m_allocatorProvider;
+        Node* storedValue;
+        bool isNewEntry;
     };
+    typedef HashTableAddResult<ValueType> AddResult;
 
-    // ListHashSetNode has this base class to hold the members because the MSVC
-    // compiler otherwise gets into circular template dependencies when trying
-    // to do sizeof on a node.
-    template<typename ValueArg> class ListHashSetNodeBase {
-    protected:
-        ListHashSetNodeBase(const ValueArg& value)
-            : m_value(value)
-            , m_prev(0)
-            , m_next(0)
+    ListHashSet();
+    ListHashSet(const ListHashSet&);
+    ListHashSet& operator=(const ListHashSet&);
+    void finalize();
+
+    void swap(ListHashSet&);
+
+    unsigned size() const { return m_impl.size(); }
+    unsigned capacity() const { return m_impl.capacity(); }
+    bool isEmpty() const { return m_impl.isEmpty(); }
+
+    iterator begin() { return makeIterator(m_head); }
+    iterator end() { return makeIterator(0); }
+    const_iterator begin() const { return makeConstIterator(m_head); }
+    const_iterator end() const { return makeConstIterator(0); }
+
+    reverse_iterator rbegin() { return makeReverseIterator(m_tail); }
+    reverse_iterator rend() { return makeReverseIterator(0); }
+    const_reverse_iterator rbegin() const { return makeConstReverseIterator(m_tail); }
+    const_reverse_iterator rend() const { return makeConstReverseIterator(0); }
+
+    ValueType& first();
+    const ValueType& first() const;
+    void removeFirst();
+
+    ValueType& last();
+    const ValueType& last() const;
+    void removeLast();
+
+    iterator find(ValuePeekInType);
+    const_iterator find(ValuePeekInType) const;
+    bool contains(ValuePeekInType) const;
+
+    // An alternate version of find() that finds the object by hashing and
+    // comparing with some other type, to avoid the cost of type conversion.
+    // The HashTranslator interface is defined in HashSet.
+    template <typename HashTranslator, typename T> iterator find(const T&);
+    template <typename HashTranslator, typename T> const_iterator find(const T&) const;
+    template <typename HashTranslator, typename T> bool contains(const T&) const;
+
+    // The return value of add is a pair of a pointer to the stored value, and a
+    // bool that is true if an new entry was added.
+    AddResult add(ValuePassInType);
+
+    // Same as add() except that the return value is an iterator. Useful in
+    // cases where it's needed to have the same return value as find() and where
+    // it's not possible to use a pointer to the storedValue.
+    iterator addReturnIterator(ValuePassInType);
+
+    // Add the value to the end of the collection. If the value was already in
+    // the list, it is moved to the end.
+    AddResult appendOrMoveToLast(ValuePassInType);
+
+    // Add the value to the beginning of the collection. If the value was
+    // already in the list, it is moved to the beginning.
+    AddResult prependOrMoveToFirst(ValuePassInType);
+
+    AddResult insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue);
+    AddResult insertBefore(iterator, ValuePassInType);
+
+    void remove(ValuePeekInType value) { return remove(find(value)); }
+    void remove(iterator);
+    void clear();
+    template <typename Collection>
+    void removeAll(const Collection& other) { WTF::removeAll(*this, other); }
+
+    ValuePassOutType take(iterator);
+    ValuePassOutType take(ValuePeekInType);
+    ValuePassOutType takeFirst();
+
+    template <typename VisitorDispatcher>
+    void trace(VisitorDispatcher);
+
+private:
+    void unlink(Node*);
+    void unlinkAndDelete(Node*);
+    void appendNode(Node*);
+    void prependNode(Node*);
+    void insertNodeBefore(Node* beforeNode, Node* newNode);
+    void deleteAllNodes();
+    Allocator* allocator() const { return m_allocatorProvider.get(); }
+    void createAllocatorIfNeeded() { m_allocatorProvider.createAllocatorIfNeeded(); }
+    void deallocate(Node* node) const { m_allocatorProvider.deallocate(node); }
+
+    iterator makeIterator(Node* position) { return iterator(this, position); }
+    const_iterator makeConstIterator(Node* position) const { return const_iterator(this, position); }
+    reverse_iterator makeReverseIterator(Node* position) { return reverse_iterator(this, position); }
+    const_reverse_iterator makeConstReverseIterator(Node* position) const { return const_reverse_iterator(this, position); }
+
+    ImplType m_impl;
+    Node* m_head;
+    Node* m_tail;
+    typename Allocator::AllocatorProvider m_allocatorProvider;
+};
+
+// ListHashSetNode has this base class to hold the members because the MSVC
+// compiler otherwise gets into circular template dependencies when trying to do
+// sizeof on a node.
+template <typename ValueArg> class ListHashSetNodeBase {
+protected:
+    ListHashSetNodeBase(const ValueArg& value)
+        : m_value(value)
+        , m_prev(nullptr)
+        , m_next(nullptr)
 #if ENABLE(ASSERT)
-            , m_isAllocated(true)
+        , m_isAllocated(true)
 #endif
-        {
-        }
+    {
+    }
 
-        template <typename U>
-        ListHashSetNodeBase(const U& value)
-            : m_value(value)
-            , m_prev(0)
-            , m_next(0)
+    template <typename U>
+    ListHashSetNodeBase(const U& value)
+        : m_value(value)
+        , m_prev(nullptr)
+        , m_next(nullptr)
 #if ENABLE(ASSERT)
-            , m_isAllocated(true)
+        , m_isAllocated(true)
 #endif
-        {
-        }
+    {
+    }
 
+public:
+    ValueArg m_value;
+    ListHashSetNodeBase* m_prev;
+    ListHashSetNodeBase* m_next;
+#if ENABLE(ASSERT)
+    bool m_isAllocated;
+#endif
+};
+
+// This allocator is only used for non-Heap ListHashSets.
+template <typename ValueArg, size_t inlineCapacity>
+struct ListHashSetAllocator : public DefaultAllocator {
+    typedef DefaultAllocator TableAllocator;
+    typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node;
+    typedef ListHashSetNodeBase<ValueArg> NodeBase;
+
+    class AllocatorProvider {
     public:
-        ValueArg m_value;
-        ListHashSetNodeBase* m_prev;
-        ListHashSetNodeBase* m_next;
-#if ENABLE(ASSERT)
-        bool m_isAllocated;
-#endif
-    };
-
-    // This allocator is only used for non-Heap ListHashSets.
-    template<typename ValueArg, size_t inlineCapacity>
-    struct ListHashSetAllocator : public DefaultAllocator {
-        typedef DefaultAllocator TableAllocator;
-        typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node;
-        typedef ListHashSetNodeBase<ValueArg> NodeBase;
-        class AllocatorProvider {
-        public:
-            AllocatorProvider() : m_allocator(nullptr) { }
-            void createAllocatorIfNeeded()
-            {
-                if (!m_allocator)
-                    m_allocator = new ListHashSetAllocator;
-            }
-
-            void releaseAllocator()
-            {
-                delete m_allocator;
-                m_allocator = nullptr;
-            }
-
-            void swap(AllocatorProvider& other)
-            {
-                std::swap(m_allocator, other.m_allocator);
-            }
-
-            void deallocate(Node* node) const
-            {
-                ASSERT(m_allocator);
-                m_allocator->deallocate(node);
-            }
-
-            ListHashSetAllocator* get() const
-            {
-                ASSERT(m_allocator);
-                return m_allocator;
-            }
-
-        private:
-            // Not using OwnPtr as this pointer should be deleted at
-            // releaseAllocator() method rather than at destructor.
-            ListHashSetAllocator* m_allocator;
-        };
-
-        ListHashSetAllocator()
-            : m_freeList(pool())
-            , m_isDoneWithInitialFreeList(false)
+        AllocatorProvider() : m_allocator(nullptr) {}
+        void createAllocatorIfNeeded()
         {
-            memset(m_pool.buffer, 0, sizeof(m_pool.buffer));
+            if (!m_allocator)
+                m_allocator = new ListHashSetAllocator;
         }
 
-        Node* allocateNode()
+        void releaseAllocator()
         {
-            Node* result = m_freeList;
-
-            if (!result)
-                return static_cast<Node*>(fastMalloc(sizeof(NodeBase)));
-
-            ASSERT(!result->m_isAllocated);
-
-            Node* next = result->next();
-            ASSERT(!next || !next->m_isAllocated);
-            if (!next && !m_isDoneWithInitialFreeList) {
-                next = result + 1;
-                if (next == pastPool()) {
-                    m_isDoneWithInitialFreeList = true;
-                    next = 0;
-                } else {
-                    ASSERT(inPool(next));
-                    ASSERT(!next->m_isAllocated);
-                }
-            }
-            m_freeList = next;
-
-            return result;
+            delete m_allocator;
+            m_allocator = nullptr;
         }
 
-        void deallocate(Node* node)
+        void swap(AllocatorProvider& other)
         {
-            if (inPool(node)) {
-#if ENABLE(ASSERT)
-                node->m_isAllocated = false;
-#endif
-                node->m_next = m_freeList;
-                m_freeList = node;
-                return;
-            }
-
-            fastFree(node);
+            std::swap(m_allocator, other.m_allocator);
         }
 
-        bool inPool(Node* node)
+        void deallocate(Node* node) const
         {
-            return node >= pool() && node < pastPool();
+            ASSERT(m_allocator);
+            m_allocator->deallocate(node);
         }
 
-        static void traceValue(typename DefaultAllocator::Visitor* visitor, Node* node) { }
+        ListHashSetAllocator* get() const
+        {
+            ASSERT(m_allocator);
+            return m_allocator;
+        }
 
     private:
-        Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); }
-        Node* pastPool() { return pool() + m_poolSize; }
+        // Not using OwnPtr as this pointer should be deleted at
+        // releaseAllocator() method rather than at destructor.
+        ListHashSetAllocator* m_allocator;
+    };
 
-        Node* m_freeList;
-        bool m_isDoneWithInitialFreeList;
+    ListHashSetAllocator()
+        : m_freeList(pool())
+        , m_isDoneWithInitialFreeList(false)
+    {
+        memset(m_pool.buffer, 0, sizeof(m_pool.buffer));
+    }
+
+    Node* allocateNode()
+    {
+        Node* result = m_freeList;
+
+        if (!result)
+            return static_cast<Node*>(fastMalloc(sizeof(NodeBase)));
+
+        ASSERT(!result->m_isAllocated);
+
+        Node* next = result->next();
+        ASSERT(!next || !next->m_isAllocated);
+        if (!next && !m_isDoneWithInitialFreeList) {
+            next = result + 1;
+            if (next == pastPool()) {
+                m_isDoneWithInitialFreeList = true;
+                next = nullptr;
+            } else {
+                ASSERT(inPool(next));
+                ASSERT(!next->m_isAllocated);
+            }
+        }
+        m_freeList = next;
+
+        return result;
+    }
+
+    void deallocate(Node* node)
+    {
+        if (inPool(node)) {
+#if ENABLE(ASSERT)
+            node->m_isAllocated = false;
+#endif
+            node->m_next = m_freeList;
+            m_freeList = node;
+            return;
+        }
+
+        fastFree(node);
+    }
+
+    bool inPool(Node* node)
+    {
+        return node >= pool() && node < pastPool();
+    }
+
+    static void traceValue(typename DefaultAllocator::Visitor* visitor, Node* node) {}
+
+private:
+    Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.buffer); }
+    Node* pastPool() { return pool() + m_poolSize; }
+
+    Node* m_freeList;
+    bool m_isDoneWithInitialFreeList;
 #if defined(MEMORY_SANITIZER_INITIAL_SIZE)
-        // The allocation pool for nodes is one big chunk that ASAN has no
-        // insight into, so it can cloak errors. Make it as small as possible
-        // to force nodes to be allocated individually where ASAN can see them.
-        static const size_t m_poolSize = 1;
+    // The allocation pool for nodes is one big chunk that ASAN has no insight
+    // into, so it can cloak errors. Make it as small as possible to force nodes
+    // to be allocated individually where ASAN can see them.
+    static const size_t m_poolSize = 1;
 #else
-        static const size_t m_poolSize = inlineCapacity;
+    static const size_t m_poolSize = inlineCapacity;
 #endif
-        AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool;
-    };
+    AlignedBuffer<sizeof(NodeBase) * m_poolSize, WTF_ALIGN_OF(NodeBase)> m_pool;
+};
 
-    template<typename ValueArg, typename AllocatorArg> class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
-    public:
-        typedef AllocatorArg NodeAllocator;
-        typedef ValueArg Value;
+template <typename ValueArg, typename AllocatorArg> class ListHashSetNode : public ListHashSetNodeBase<ValueArg> {
+public:
+    typedef AllocatorArg NodeAllocator;
+    typedef ValueArg Value;
 
-        template <typename U>
-        ListHashSetNode(U value)
-            : ListHashSetNodeBase<ValueArg>(value) { }
+    template <typename U>
+    ListHashSetNode(U value)
+        : ListHashSetNodeBase<ValueArg>(value) {}
 
-        void* operator new(size_t, NodeAllocator* allocator)
-        {
-            static_assert(sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>), "please add any fields to the base");
-            return allocator->allocateNode();
-        }
+    void* operator new(size_t, NodeAllocator* allocator)
+    {
+        static_assert(sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>), "please add any fields to the base");
+        return allocator->allocateNode();
+    }
 
-        void setWasAlreadyDestructed()
-        {
-            if (NodeAllocator::isGarbageCollected && !IsTriviallyDestructible<ValueArg>::value)
-                this->m_prev = unlinkedNodePointer();
-        }
+    void setWasAlreadyDestructed()
+    {
+        if (NodeAllocator::isGarbageCollected && !IsTriviallyDestructible<ValueArg>::value)
+            this->m_prev = unlinkedNodePointer();
+    }
 
-        bool wasAlreadyDestructed() const
-        {
-            ASSERT(NodeAllocator::isGarbageCollected);
-            return this->m_prev == unlinkedNodePointer();
-        }
+    bool wasAlreadyDestructed() const
+    {
+        ASSERT(NodeAllocator::isGarbageCollected);
+        return this->m_prev == unlinkedNodePointer();
+    }
 
-        static void finalize(void* pointer)
-        {
-            ASSERT(!IsTriviallyDestructible<ValueArg>::value); // No need to waste time calling finalize if it's not needed.
-            ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer);
+    static void finalize(void* pointer)
+    {
+        ASSERT(!IsTriviallyDestructible<ValueArg>::value); // No need to waste time calling finalize if it's not needed.
+        ListHashSetNode* self = reinterpret_cast_ptr<ListHashSetNode*>(pointer);
 
-            // Check whether this node was already destructed before being
-            // unlinked from the collection.
-            if (self->wasAlreadyDestructed())
-                return;
+        // Check whether this node was already destructed before being unlinked
+        // from the collection.
+        if (self->wasAlreadyDestructed())
+            return;
 
-            self->m_value.~ValueArg();
-        }
-        void finalizeGarbageCollectedObject()
-        {
-            finalize(this);
-        }
+        self->m_value.~ValueArg();
+    }
+    void finalizeGarbageCollectedObject()
+    {
+        finalize(this);
+    }
 
-        void destroy(NodeAllocator* allocator)
-        {
-            this->~ListHashSetNode();
-            setWasAlreadyDestructed();
-            allocator->deallocate(this);
-        }
+    void destroy(NodeAllocator* allocator)
+    {
+        this->~ListHashSetNode();
+        setWasAlreadyDestructed();
+        allocator->deallocate(this);
+    }
 
-        // This is not called in normal tracing, but it is called if we find a
-        // pointer to a node on the stack using conservative scanning. Since
-        // the original ListHashSet may no longer exist we make sure to mark
-        // the neighbours in the chain too.
-        template<typename VisitorDispatcher>
-        void trace(VisitorDispatcher visitor)
-        {
-            // The conservative stack scan can find nodes that have been
-            // removed from the set and destructed. We don't need to trace
-            // these, and it would be wrong to do so, because the class will
-            // not expect the trace method to be called after the destructor.
-            // It's an error to remove a node from the ListHashSet while an
-            // iterator is positioned at that node, so there should be no valid
-            // pointers from the stack to a destructed node.
-            if (wasAlreadyDestructed())
-                return;
-            NodeAllocator::traceValue(visitor, this);
-            visitor->mark(next());
-            visitor->mark(prev());
-        }
+    // This is not called in normal tracing, but it is called if we find a
+    // pointer to a node on the stack using conservative scanning. Since the
+    // original ListHashSet may no longer exist we make sure to mark the
+    // neighbours in the chain too.
+    template <typename VisitorDispatcher>
+    void trace(VisitorDispatcher visitor)
+    {
+        // The conservative stack scan can find nodes that have been removed
+        // from the set and destructed. We don't need to trace these, and it
+        // would be wrong to do so, because the class will not expect the trace
+        // method to be called after the destructor.  It's an error to remove a
+        // node from the ListHashSet while an iterator is positioned at that
+        // node, so there should be no valid pointers from the stack to a
+        // destructed node.
+        if (wasAlreadyDestructed())
+            return;
+        NodeAllocator::traceValue(visitor, this);
+        visitor->mark(next());
+        visitor->mark(prev());
+    }
 
-        ListHashSetNode* next() const { return reinterpret_cast<ListHashSetNode*>(this->m_next); }
-        ListHashSetNode* prev() const { return reinterpret_cast<ListHashSetNode*>(this->m_prev); }
+    ListHashSetNode* next() const { return reinterpret_cast<ListHashSetNode*>(this->m_next); }
+    ListHashSetNode* prev() const { return reinterpret_cast<ListHashSetNode*>(this->m_prev); }
 
-        // Don't add fields here, the ListHashSetNodeBase and this should have
-        // the same size.
+    // Don't add fields here, the ListHashSetNodeBase and this should have the
+    // same size.
 
-        static ListHashSetNode* unlinkedNodePointer() { return reinterpret_cast<ListHashSetNode*>(-1); }
+    static ListHashSetNode* unlinkedNodePointer() { return reinterpret_cast<ListHashSetNode*>(-1); }
 
-        template<typename HashArg>
-        friend struct ListHashSetNodeHashFunctions;
-    };
+    template <typename HashArg>
+    friend struct ListHashSetNodeHashFunctions;
+};
 
-    template<typename HashArg> struct ListHashSetNodeHashFunctions {
-        template<typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); }
-        template<typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); }
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
+template <typename HashArg> struct ListHashSetNodeHashFunctions {
+    template <typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); }
+    template <typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); }
+    static const bool safeToCompareToEmptyOrDeleted = false;
+};
 
-    template<typename Set> class ListHashSetIterator {
-    private:
-        typedef typename Set::const_iterator const_iterator;
-        typedef typename Set::Node Node;
-        typedef typename Set::ValueType ValueType;
-        typedef ValueType& ReferenceType;
-        typedef ValueType* PointerType;
+template <typename Set> class ListHashSetIterator {
+private:
+    typedef typename Set::const_iterator const_iterator;
+    typedef typename Set::Node Node;
+    typedef typename Set::ValueType ValueType;
+    typedef ValueType& ReferenceType;
+    typedef ValueType* PointerType;
 
-        ListHashSetIterator(const Set* set, Node* position) : m_iterator(set, position) { }
+    ListHashSetIterator(const Set* set, Node* position) : m_iterator(set, position) {}
 
-    public:
-        ListHashSetIterator() { }
+public:
+    ListHashSetIterator() {}
 
-        // default copy, assignment and destructor are OK
+    // default copy, assignment and destructor are OK
 
-        PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
+    PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
+    ReferenceType operator*() const { return *get(); }
+    PointerType operator->() const { return get(); }
 
-        ListHashSetIterator& operator++() { ++m_iterator; return *this; }
-        ListHashSetIterator& operator--() { --m_iterator; return *this; }
+    ListHashSetIterator& operator++() { ++m_iterator; return *this; }
+    ListHashSetIterator& operator--() { --m_iterator; return *this; }
 
-        // Postfix ++ and -- intentionally omitted.
+    // Postfix ++ and -- intentionally omitted.
 
-        // Comparison.
-        bool operator==(const ListHashSetIterator& other) const { return m_iterator == other.m_iterator; }
-        bool operator!=(const ListHashSetIterator& other) const { return m_iterator != other.m_iterator; }
+    // Comparison.
+    bool operator==(const ListHashSetIterator& other) const { return m_iterator == other.m_iterator; }
+    bool operator!=(const ListHashSetIterator& other) const { return m_iterator != other.m_iterator; }
 
-        operator const_iterator() const { return m_iterator; }
+    operator const_iterator() const { return m_iterator; }
 
-    private:
-        Node* node() { return m_iterator.node(); }
+private:
+    Node* node() { return m_iterator.node(); }
 
-        const_iterator m_iterator;
+    const_iterator m_iterator;
 
-        template<typename T, size_t inlineCapacity, typename U, typename V>
-        friend class ListHashSet;
-    };
-
-    template<typename Set>
-    class ListHashSetConstIterator {
-    private:
-        typedef typename Set::const_iterator const_iterator;
-        typedef typename Set::Node Node;
-        typedef typename Set::ValueType ValueType;
-        typedef const ValueType& ReferenceType;
-        typedef const ValueType* PointerType;
-
-        friend class ListHashSetIterator<Set>;
-
-        ListHashSetConstIterator(const Set* set, Node* position)
-            : m_set(set)
-            , m_position(position)
-        {
-        }
-
-    public:
-        ListHashSetConstIterator()
-        {
-        }
-
-        PointerType get() const
-        {
-            return &m_position->m_value;
-        }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        ListHashSetConstIterator& operator++()
-        {
-            ASSERT(m_position != 0);
-            m_position = m_position->next();
-            return *this;
-        }
-
-        ListHashSetConstIterator& operator--()
-        {
-            ASSERT(m_position != m_set->m_head);
-            if (!m_position)
-                m_position = m_set->m_tail;
-            else
-                m_position = m_position->prev();
-            return *this;
-        }
-
-        // Postfix ++ and -- intentionally omitted.
-
-        // Comparison.
-        bool operator==(const ListHashSetConstIterator& other) const
-        {
-            return m_position == other.m_position;
-        }
-        bool operator!=(const ListHashSetConstIterator& other) const
-        {
-            return m_position != other.m_position;
-        }
-
-    private:
-        Node* node() { return m_position; }
-
-        const Set* m_set;
-        Node* m_position;
-
-        template<typename T, size_t inlineCapacity, typename U, typename V>
-        friend class ListHashSet;
-    };
-
-    template<typename Set>
-    class ListHashSetReverseIterator {
-    private:
-        typedef typename Set::const_reverse_iterator const_reverse_iterator;
-        typedef typename Set::Node Node;
-        typedef typename Set::ValueType ValueType;
-        typedef ValueType& ReferenceType;
-        typedef ValueType* PointerType;
-
-        ListHashSetReverseIterator(const Set* set, Node* position) : m_iterator(set, position) { }
-
-    public:
-        ListHashSetReverseIterator() { }
-
-        // default copy, assignment and destructor are OK
-
-        PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        ListHashSetReverseIterator& operator++() { ++m_iterator; return *this; }
-        ListHashSetReverseIterator& operator--() { --m_iterator; return *this; }
-
-        // Postfix ++ and -- intentionally omitted.
-
-        // Comparison.
-        bool operator==(const ListHashSetReverseIterator& other) const { return m_iterator == other.m_iterator; }
-        bool operator!=(const ListHashSetReverseIterator& other) const { return m_iterator != other.m_iterator; }
-
-        operator const_reverse_iterator() const { return m_iterator; }
-
-    private:
-        Node* node() { return m_iterator.node(); }
-
-        const_reverse_iterator m_iterator;
-
-        template<typename T, size_t inlineCapacity, typename U, typename V>
-        friend class ListHashSet;
-    };
-
-    template<typename Set> class ListHashSetConstReverseIterator {
-    private:
-        typedef typename Set::reverse_iterator reverse_iterator;
-        typedef typename Set::Node Node;
-        typedef typename Set::ValueType ValueType;
-        typedef const ValueType& ReferenceType;
-        typedef const ValueType* PointerType;
-
-        friend class ListHashSetReverseIterator<Set>;
-
-        ListHashSetConstReverseIterator(const Set* set, Node* position)
-            : m_set(set)
-            , m_position(position)
-        {
-        }
-
-    public:
-        ListHashSetConstReverseIterator()
-        {
-        }
-
-        PointerType get() const
-        {
-            return &m_position->m_value;
-        }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        ListHashSetConstReverseIterator& operator++()
-        {
-            ASSERT(m_position != 0);
-            m_position = m_position->prev();
-            return *this;
-        }
-
-        ListHashSetConstReverseIterator& operator--()
-        {
-            ASSERT(m_position != m_set->m_tail);
-            if (!m_position)
-                m_position = m_set->m_head;
-            else
-                m_position = m_position->next();
-            return *this;
-        }
-
-        // Postfix ++ and -- intentionally omitted.
-
-        // Comparison.
-        bool operator==(const ListHashSetConstReverseIterator& other) const
-        {
-            return m_position == other.m_position;
-        }
-        bool operator!=(const ListHashSetConstReverseIterator& other) const
-        {
-            return m_position != other.m_position;
-        }
-
-    private:
-        Node* node() { return m_position; }
-
-        const Set* m_set;
-        Node* m_position;
+    template <typename T, size_t inlineCapacity, typename U, typename V>
+    friend class ListHashSet;
+};
 
-        template<typename T, size_t inlineCapacity, typename U, typename V>
-        friend class ListHashSet;
-    };
+template <typename Set>
+class ListHashSetConstIterator {
+private:
+    typedef typename Set::const_iterator const_iterator;
+    typedef typename Set::Node Node;
+    typedef typename Set::ValueType ValueType;
+    typedef const ValueType& ReferenceType;
+    typedef const ValueType* PointerType;
 
-    template<typename HashFunctions>
-    struct ListHashSetTranslator {
-        template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); }
-        template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator)
-        {
-            location = new (const_cast<V*>(&allocator)) T(key);
-        }
-    };
+    friend class ListHashSetIterator<Set>;
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet()
-        : m_head(0)
-        , m_tail(0)
+    ListHashSetConstIterator(const Set* set, Node* position)
+        : m_set(set)
+        , m_position(position)
     {
     }
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(const ListHashSet& other)
-        : m_head(0)
-        , m_tail(0)
+public:
+    ListHashSetConstIterator()
     {
-        const_iterator end = other.end();
-        for (const_iterator it = other.begin(); it != end; ++it)
-            add(*it);
     }
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline ListHashSet<T, inlineCapacity, U, V>& ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other)
+    PointerType get() const
     {
-        ListHashSet tmp(other);
-        swap(tmp);
+        return &m_position->m_value;
+    }
+    ReferenceType operator*() const { return *get(); }
+    PointerType operator->() const { return get(); }
+
+    ListHashSetConstIterator& operator++()
+    {
+        ASSERT(m_position != 0);
+        m_position = m_position->next();
         return *this;
     }
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other)
+    ListHashSetConstIterator& operator--()
     {
-        m_impl.swap(other.m_impl);
-        std::swap(m_head, other.m_head);
-        std::swap(m_tail, other.m_tail);
-        m_allocatorProvider.swap(other.m_allocatorProvider);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::finalize()
-    {
-        static_assert(!Allocator::isGarbageCollected, "heap allocated ListHashSet should never call finalize()");
-        deleteAllNodes();
-        m_allocatorProvider.releaseAllocator();
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline T& ListHashSet<T, inlineCapacity, U, V>::first()
-    {
-        ASSERT(!isEmpty());
-        return m_head->m_value;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst()
-    {
-        ASSERT(!isEmpty());
-        m_impl.remove(m_head);
-        unlinkAndDelete(m_head);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const
-    {
-        ASSERT(!isEmpty());
-        return m_head->m_value;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline T& ListHashSet<T, inlineCapacity, U, V>::last()
-    {
-        ASSERT(!isEmpty());
-        return m_tail->m_value;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const
-    {
-        ASSERT(!isEmpty());
-        return m_tail->m_value;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::removeLast()
-    {
-        ASSERT(!isEmpty());
-        m_impl.remove(m_tail);
-        unlinkAndDelete(m_tail);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value)
-    {
-        ImplTypeIterator it = m_impl.template find<BaseTranslator>(value);
-        if (it == m_impl.end())
-            return end();
-        return makeIterator(*it);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) const
-    {
-        ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value);
-        if (it == m_impl.end())
-            return end();
-        return makeConstIterator(*it);
-    }
-
-    template<typename Translator>
-    struct ListHashSetTranslatorAdapter {
-        template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
-        template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); }
-    };
-
-    template<typename ValueType, size_t inlineCapacity, typename U, typename V>
-    template<typename HashTranslator, typename T>
-    inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value)
-    {
-        ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
-        if (it == m_impl.end())
-            return end();
-        return makeIterator(*it);
-    }
-
-    template<typename ValueType, size_t inlineCapacity, typename U, typename V>
-    template<typename HashTranslator, typename T>
-    inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const
-    {
-        ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
-        if (it == m_impl.end())
-            return end();
-        return makeConstIterator(*it);
-    }
-
-    template<typename ValueType, size_t inlineCapacity, typename U, typename V>
-    template<typename HashTranslator, typename T>
-    inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(const T& value) const
-    {
-        return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator>>(value);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline bool ListHashSet<T, inlineCapacity, U, V>::contains(ValuePeekInType value) const
-    {
-        return m_impl.template contains<BaseTranslator>(value);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::add(ValuePassInType value)
-    {
-        createAllocatorIfNeeded();
-        // The second argument is a const ref. This is useful for the HashTable
-        // because it lets it take lvalues by reference, but for our purposes
-        // it's inconvenient, since it constrains us to be const, whereas the
-        // allocator actually changes when it does allocations.
-        auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
-        if (result.isNewEntry)
-            appendNode(*result.storedValue);
-        return AddResult(*result.storedValue, result.isNewEntry);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::addReturnIterator(ValuePassInType value)
-    {
-        return makeIterator(add(value).storedValue);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::appendOrMoveToLast(ValuePassInType value)
-    {
-        createAllocatorIfNeeded();
-        auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
-        Node* node = *result.storedValue;
-        if (!result.isNewEntry)
-            unlink(node);
-        appendNode(node);
-        return AddResult(*result.storedValue, result.isNewEntry);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::prependOrMoveToFirst(ValuePassInType value)
-    {
-        createAllocatorIfNeeded();
-        auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
-        Node* node = *result.storedValue;
-        if (!result.isNewEntry)
-            unlink(node);
-        prependNode(node);
-        return AddResult(*result.storedValue, result.isNewEntry);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(iterator it, ValuePassInType newValue)
-    {
-        createAllocatorIfNeeded();
-        auto result = m_impl.template add<BaseTranslator>(newValue, *this->allocator());
-        if (result.isNewEntry)
-            insertNodeBefore(it.node(), *result.storedValue);
-        return AddResult(*result.storedValue, result.isNewEntry);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue)
-    {
-        createAllocatorIfNeeded();
-        return insertBefore(find(beforeValue), newValue);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it)
-    {
-        if (it == end())
-            return;
-        m_impl.remove(it.node());
-        unlinkAndDelete(it.node());
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    inline void ListHashSet<T, inlineCapacity, U, V>::clear()
-    {
-        deleteAllNodes();
-        m_impl.clear();
-        m_head = 0;
-        m_tail = 0;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(iterator it)
-    {
-        if (it == end())
-            return ValueTraits::emptyValue();
-
-        m_impl.remove(it.node());
-        ValuePassOutType result = ValueTraits::passOut(it.node()->m_value);
-        unlinkAndDelete(it.node());
-
-        return result;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(ValuePeekInType value)
-    {
-        return take(find(value));
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::takeFirst()
-    {
-        ASSERT(!isEmpty());
-        m_impl.remove(m_head);
-        ValuePassOutType result = ValueTraits::passOut(m_head->m_value);
-        unlinkAndDelete(m_head);
-
-        return result;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename Allocator>
-    void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node)
-    {
-        if (!node->m_prev) {
-            ASSERT(node == m_head);
-            m_head = node->next();
-        } else {
-            ASSERT(node != m_head);
-            node->m_prev->m_next = node->m_next;
-        }
-
-        if (!node->m_next) {
-            ASSERT(node == m_tail);
-            m_tail = node->prev();
-        } else {
-            ASSERT(node != m_tail);
-            node->m_next->m_prev = node->m_prev;
-        }
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node)
-    {
-        unlink(node);
-        node->destroy(this->allocator());
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node)
-    {
-        node->m_prev = m_tail;
-        node->m_next = 0;
-
-        if (m_tail) {
-            ASSERT(m_head);
-            m_tail->m_next = node;
-        } else {
-            ASSERT(!m_head);
-            m_head = node;
-        }
-
-        m_tail = node;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node)
-    {
-        node->m_prev = 0;
-        node->m_next = m_head;
-
-        if (m_head)
-            m_head->m_prev = node;
+        ASSERT(m_position != m_set->m_head);
+        if (!m_position)
+            m_position = m_set->m_tail;
         else
-            m_tail = node;
+            m_position = m_position->prev();
+        return *this;
+    }
 
+    // Postfix ++ and -- intentionally omitted.
+
+    // Comparison.
+    bool operator==(const ListHashSetConstIterator& other) const
+    {
+        return m_position == other.m_position;
+    }
+    bool operator!=(const ListHashSetConstIterator& other) const
+    {
+        return m_position != other.m_position;
+    }
+
+private:
+    Node* node() { return m_position; }
+
+    const Set* m_set;
+    Node* m_position;
+
+    template <typename T, size_t inlineCapacity, typename U, typename V>
+    friend class ListHashSet;
+};
+
+template <typename Set>
+class ListHashSetReverseIterator {
+private:
+    typedef typename Set::const_reverse_iterator const_reverse_iterator;
+    typedef typename Set::Node Node;
+    typedef typename Set::ValueType ValueType;
+    typedef ValueType& ReferenceType;
+    typedef ValueType* PointerType;
+
+    ListHashSetReverseIterator(const Set* set, Node* position) : m_iterator(set, position) {}
+
+public:
+    ListHashSetReverseIterator() {}
+
+    // default copy, assignment and destructor are OK
+
+    PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
+    ReferenceType operator*() const { return *get(); }
+    PointerType operator->() const { return get(); }
+
+    ListHashSetReverseIterator& operator++() { ++m_iterator; return *this; }
+    ListHashSetReverseIterator& operator--() { --m_iterator; return *this; }
+
+    // Postfix ++ and -- intentionally omitted.
+
+    // Comparison.
+    bool operator==(const ListHashSetReverseIterator& other) const { return m_iterator == other.m_iterator; }
+    bool operator!=(const ListHashSetReverseIterator& other) const { return m_iterator != other.m_iterator; }
+
+    operator const_reverse_iterator() const { return m_iterator; }
+
+private:
+    Node* node() { return m_iterator.node(); }
+
+    const_reverse_iterator m_iterator;
+
+    template <typename T, size_t inlineCapacity, typename U, typename V>
+    friend class ListHashSet;
+};
+
+template <typename Set> class ListHashSetConstReverseIterator {
+private:
+    typedef typename Set::reverse_iterator reverse_iterator;
+    typedef typename Set::Node Node;
+    typedef typename Set::ValueType ValueType;
+    typedef const ValueType& ReferenceType;
+    typedef const ValueType* PointerType;
+
+    friend class ListHashSetReverseIterator<Set>;
+
+    ListHashSetConstReverseIterator(const Set* set, Node* position)
+        : m_set(set)
+        , m_position(position)
+    {
+    }
+
+public:
+    ListHashSetConstReverseIterator()
+    {
+    }
+
+    PointerType get() const
+    {
+        return &m_position->m_value;
+    }
+    ReferenceType operator*() const { return *get(); }
+    PointerType operator->() const { return get(); }
+
+    ListHashSetConstReverseIterator& operator++()
+    {
+        ASSERT(m_position != 0);
+        m_position = m_position->prev();
+        return *this;
+    }
+
+    ListHashSetConstReverseIterator& operator--()
+    {
+        ASSERT(m_position != m_set->m_tail);
+        if (!m_position)
+            m_position = m_set->m_head;
+        else
+            m_position = m_position->next();
+        return *this;
+    }
+
+    // Postfix ++ and -- intentionally omitted.
+
+    // Comparison.
+    bool operator==(const ListHashSetConstReverseIterator& other) const
+    {
+        return m_position == other.m_position;
+    }
+    bool operator!=(const ListHashSetConstReverseIterator& other) const
+    {
+        return m_position != other.m_position;
+    }
+
+private:
+    Node* node() { return m_position; }
+
+    const Set* m_set;
+    Node* m_position;
+
+    template <typename T, size_t inlineCapacity, typename U, typename V>
+    friend class ListHashSet;
+};
+
+template <typename HashFunctions>
+struct ListHashSetTranslator {
+    template <typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); }
+    template <typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator)
+    {
+        location = new (const_cast<V*>(&allocator)) T(key);
+    }
+};
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet()
+    : m_head(nullptr)
+    , m_tail(nullptr)
+{
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(const ListHashSet& other)
+    : m_head(nullptr)
+    , m_tail(nullptr)
+{
+    const_iterator end = other.end();
+    for (const_iterator it = other.begin(); it != end; ++it)
+        add(*it);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline ListHashSet<T, inlineCapacity, U, V>& ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other)
+{
+    ListHashSet tmp(other);
+    swap(tmp);
+    return *this;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::swap(ListHashSet& other)
+{
+    m_impl.swap(other.m_impl);
+    std::swap(m_head, other.m_head);
+    std::swap(m_tail, other.m_tail);
+    m_allocatorProvider.swap(other.m_allocatorProvider);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::finalize()
+{
+    static_assert(!Allocator::isGarbageCollected, "heap allocated ListHashSet should never call finalize()");
+    deleteAllNodes();
+    m_allocatorProvider.releaseAllocator();
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline T& ListHashSet<T, inlineCapacity, U, V>::first()
+{
+    ASSERT(!isEmpty());
+    return m_head->m_value;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::removeFirst()
+{
+    ASSERT(!isEmpty());
+    m_impl.remove(m_head);
+    unlinkAndDelete(m_head);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline const T& ListHashSet<T, inlineCapacity, U, V>::first() const
+{
+    ASSERT(!isEmpty());
+    return m_head->m_value;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline T& ListHashSet<T, inlineCapacity, U, V>::last()
+{
+    ASSERT(!isEmpty());
+    return m_tail->m_value;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline const T& ListHashSet<T, inlineCapacity, U, V>::last() const
+{
+    ASSERT(!isEmpty());
+    return m_tail->m_value;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::removeLast()
+{
+    ASSERT(!isEmpty());
+    m_impl.remove(m_tail);
+    unlinkAndDelete(m_tail);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value)
+{
+    ImplTypeIterator it = m_impl.template find<BaseTranslator>(value);
+    if (it == m_impl.end())
+        return end();
+    return makeIterator(*it);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline typename ListHashSet<T, inlineCapacity, U, V>::const_iterator ListHashSet<T, inlineCapacity, U, V>::find(ValuePeekInType value) const
+{
+    ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value);
+    if (it == m_impl.end())
+        return end();
+    return makeConstIterator(*it);
+}
+
+template <typename Translator>
+struct ListHashSetTranslatorAdapter {
+    template <typename T> static unsigned hash(const T& key) { return Translator::hash(key); }
+    template <typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); }
+};
+
+template <typename ValueType, size_t inlineCapacity, typename U, typename V>
+template <typename HashTranslator, typename T>
+inline typename ListHashSet<ValueType, inlineCapacity, U, V>::iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value)
+{
+    ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
+    if (it == m_impl.end())
+        return end();
+    return makeIterator(*it);
+}
+
+template <typename ValueType, size_t inlineCapacity, typename U, typename V>
+template <typename HashTranslator, typename T>
+inline typename ListHashSet<ValueType, inlineCapacity, U, V>::const_iterator ListHashSet<ValueType, inlineCapacity, U, V>::find(const T& value) const
+{
+    ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator>>(value);
+    if (it == m_impl.end())
+        return end();
+    return makeConstIterator(*it);
+}
+
+template <typename ValueType, size_t inlineCapacity, typename U, typename V>
+template <typename HashTranslator, typename T>
+inline bool ListHashSet<ValueType, inlineCapacity, U, V>::contains(const T& value) const
+{
+    return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator>>(value);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline bool ListHashSet<T, inlineCapacity, U, V>::contains(ValuePeekInType value) const
+{
+    return m_impl.template contains<BaseTranslator>(value);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::add(ValuePassInType value)
+{
+    createAllocatorIfNeeded();
+    // The second argument is a const ref. This is useful for the HashTable
+    // because it lets it take lvalues by reference, but for our purposes it's
+    // inconvenient, since it constrains us to be const, whereas the allocator
+    // actually changes when it does allocations.
+    auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
+    if (result.isNewEntry)
+        appendNode(*result.storedValue);
+    return AddResult(*result.storedValue, result.isNewEntry);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::iterator ListHashSet<T, inlineCapacity, U, V>::addReturnIterator(ValuePassInType value)
+{
+    return makeIterator(add(value).storedValue);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::appendOrMoveToLast(ValuePassInType value)
+{
+    createAllocatorIfNeeded();
+    auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
+    Node* node = *result.storedValue;
+    if (!result.isNewEntry)
+        unlink(node);
+    appendNode(node);
+    return AddResult(*result.storedValue, result.isNewEntry);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::prependOrMoveToFirst(ValuePassInType value)
+{
+    createAllocatorIfNeeded();
+    auto result = m_impl.template add<BaseTranslator>(value, *this->allocator());
+    Node* node = *result.storedValue;
+    if (!result.isNewEntry)
+        unlink(node);
+    prependNode(node);
+    return AddResult(*result.storedValue, result.isNewEntry);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(iterator it, ValuePassInType newValue)
+{
+    createAllocatorIfNeeded();
+    auto result = m_impl.template add<BaseTranslator>(newValue, *this->allocator());
+    if (result.isNewEntry)
+        insertNodeBefore(it.node(), *result.storedValue);
+    return AddResult(*result.storedValue, result.isNewEntry);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::AddResult ListHashSet<T, inlineCapacity, U, V>::insertBefore(ValuePeekInType beforeValue, ValuePassInType newValue)
+{
+    createAllocatorIfNeeded();
+    return insertBefore(find(beforeValue), newValue);
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::remove(iterator it)
+{
+    if (it == end())
+        return;
+    m_impl.remove(it.node());
+    unlinkAndDelete(it.node());
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+inline void ListHashSet<T, inlineCapacity, U, V>::clear()
+{
+    deleteAllNodes();
+    m_impl.clear();
+    m_head = nullptr;
+    m_tail = nullptr;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(iterator it)
+{
+    if (it == end())
+        return ValueTraits::emptyValue();
+
+    m_impl.remove(it.node());
+    ValuePassOutType result = ValueTraits::passOut(it.node()->m_value);
+    unlinkAndDelete(it.node());
+
+    return result;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::take(ValuePeekInType value)
+{
+    return take(find(value));
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+typename ListHashSet<T, inlineCapacity, U, V>::ValuePassOutType ListHashSet<T, inlineCapacity, U, V>::takeFirst()
+{
+    ASSERT(!isEmpty());
+    m_impl.remove(m_head);
+    ValuePassOutType result = ValueTraits::passOut(m_head->m_value);
+    unlinkAndDelete(m_head);
+
+    return result;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename Allocator>
+void ListHashSet<T, inlineCapacity, U, Allocator>::unlink(Node* node)
+{
+    if (!node->m_prev) {
+        ASSERT(node == m_head);
+        m_head = node->next();
+    } else {
+        ASSERT(node != m_head);
+        node->m_prev->m_next = node->m_next;
+    }
+
+    if (!node->m_next) {
+        ASSERT(node == m_tail);
+        m_tail = node->prev();
+    } else {
+        ASSERT(node != m_tail);
+        node->m_next->m_prev = node->m_prev;
+    }
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+void ListHashSet<T, inlineCapacity, U, V>::unlinkAndDelete(Node* node)
+{
+    unlink(node);
+    node->destroy(this->allocator());
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+void ListHashSet<T, inlineCapacity, U, V>::appendNode(Node* node)
+{
+    node->m_prev = m_tail;
+    node->m_next = nullptr;
+
+    if (m_tail) {
+        ASSERT(m_head);
+        m_tail->m_next = node;
+    } else {
+        ASSERT(!m_head);
         m_head = node;
     }
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode, Node* newNode)
-    {
-        if (!beforeNode)
-            return appendNode(newNode);
+    m_tail = node;
+}
 
-        newNode->m_next = beforeNode;
-        newNode->m_prev = beforeNode->m_prev;
-        if (beforeNode->m_prev)
-            beforeNode->m_prev->m_next = newNode;
-        beforeNode->m_prev = newNode;
+template <typename T, size_t inlineCapacity, typename U, typename V>
+void ListHashSet<T, inlineCapacity, U, V>::prependNode(Node* node)
+{
+    node->m_prev = nullptr;
+    node->m_next = m_head;
 
-        if (!newNode->m_prev)
-            m_head = newNode;
-    }
+    if (m_head)
+        m_head->m_prev = node;
+    else
+        m_tail = node;
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes()
-    {
-        if (!m_head)
-            return;
+    m_head = node;
+}
 
-        for (Node* node = m_head, *next = m_head->next(); node; node = next, next = node ? node->next() : 0)
-            node->destroy(this->allocator());
-    }
+template <typename T, size_t inlineCapacity, typename U, typename V>
+void ListHashSet<T, inlineCapacity, U, V>::insertNodeBefore(Node* beforeNode, Node* newNode)
+{
+    if (!beforeNode)
+        return appendNode(newNode);
 
-    template<typename T, size_t inlineCapacity, typename U, typename V>
-    template<typename VisitorDispatcher>
-    void ListHashSet<T, inlineCapacity, U, V>::trace(VisitorDispatcher visitor)
-    {
-        static_assert(HashTraits<T>::weakHandlingFlag == NoWeakHandlingInCollections, "ListHashSet does not support weakness");
-        // This marks all the nodes and their contents live that can be
-        // accessed through the HashTable. That includes m_head and m_tail
-        // so we do not have to explicitly trace them here.
-        m_impl.trace(visitor);
-    }
+    newNode->m_next = beforeNode;
+    newNode->m_prev = beforeNode->m_prev;
+    if (beforeNode->m_prev)
+        beforeNode->m_prev->m_next = newNode;
+    beforeNode->m_prev = newNode;
+
+    if (!newNode->m_prev)
+        m_head = newNode;
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+void ListHashSet<T, inlineCapacity, U, V>::deleteAllNodes()
+{
+    if (!m_head)
+        return;
+
+    for (Node* node = m_head, *next = m_head->next(); node; node = next, next = node ? node->next() : 0)
+        node->destroy(this->allocator());
+}
+
+template <typename T, size_t inlineCapacity, typename U, typename V>
+template <typename VisitorDispatcher>
+void ListHashSet<T, inlineCapacity, U, V>::trace(VisitorDispatcher visitor)
+{
+    static_assert(HashTraits<T>::weakHandlingFlag == NoWeakHandlingInCollections, "ListHashSet does not support weakness");
+    // This marks all the nodes and their contents live that can be accessed
+    // through the HashTable. That includes m_head and m_tail so we do not have
+    // to explicitly trace them here.
+    m_impl.trace(visitor);
+}
 
 #if !ENABLE(OILPAN)
-    template<typename T, size_t U, typename V>
-    struct NeedsTracing<ListHashSet<T, U, V>> {
-        static const bool value = false;
-    };
+template <typename T, size_t U, typename V>
+struct NeedsTracing<ListHashSet<T, U, V>> {
+    static const bool value = false;
+};
 #endif
 
 } // namespace WTF
 
 using WTF::ListHashSet;
 
-#endif /* WTF_ListHashSet_h */
+#endif // WTF_ListHashSet_h
diff --git a/third_party/WebKit/Source/wtf/ListHashSetTest.cpp b/third_party/WebKit/Source/wtf/ListHashSetTest.cpp
index f5c0089..12779f3 100644
--- a/third_party/WebKit/Source/wtf/ListHashSetTest.cpp
+++ b/third_party/WebKit/Source/wtf/ListHashSetTest.cpp
@@ -24,9 +24,9 @@
  */
 
 #include "config.h"
+#include "wtf/ListHashSet.h"
 
 #include "wtf/LinkedHashSet.h"
-#include "wtf/ListHashSet.h"
 #include "wtf/PassRefPtr.h"
 #include "wtf/RefCounted.h"
 #include "wtf/RefPtr.h"
@@ -36,7 +36,7 @@
 
 namespace {
 
-template<typename Set>
+template <typename Set>
 void removeFirstHelper()
 {
     Set list;
@@ -76,7 +76,7 @@
     removeFirstHelper<LinkedHashSet<int>>();
 }
 
-template<typename Set>
+template <typename Set>
 void appendOrMoveToLastNewItems()
 {
     Set list;
@@ -110,7 +110,7 @@
     appendOrMoveToLastNewItems<LinkedHashSet<int>>();
 }
 
-template<typename Set>
+template <typename Set>
 void appendOrMoveToLastWithDuplicates()
 {
     Set list;
@@ -161,7 +161,7 @@
     appendOrMoveToLastWithDuplicates<LinkedHashSet<int>>();
 }
 
-template<typename Set>
+template <typename Set>
 void prependOrMoveToFirstNewItems()
 {
     Set list;
@@ -195,7 +195,7 @@
     prependOrMoveToFirstNewItems<LinkedHashSet<int>>();
 }
 
-template<typename Set>
+template <typename Set>
 void prependOrMoveToLastWithDuplicates()
 {
     Set list;
@@ -264,7 +264,7 @@
 
 int DummyRefCounted::m_refInvokesCount = 0;
 
-template<typename Set>
+template <typename Set>
 void withRefPtr()
 {
     bool isDeleted = false;
@@ -306,7 +306,7 @@
     withRefPtr<LinkedHashSet<RefPtr<DummyRefCounted>>>();
 }
 
-template<typename Set, typename SetRef, typename Iterator>
+template <typename Set, typename SetRef, typename Iterator>
 void findHelper()
 {
     Set set;
@@ -340,7 +340,7 @@
     findHelper<LinkedHashSet<int>, LinkedHashSet<int>&, LinkedHashSet<int>::iterator>();
 }
 
-template<typename Set>
+template <typename Set>
 void insertBeforeHelper(bool canModifyWhileIterating)
 {
     Set set;
@@ -397,7 +397,7 @@
     insertBeforeHelper<LinkedHashSet<int>>(false);
 }
 
-template<typename Set>
+template <typename Set>
 void addReturnIterator(bool canModifyWhileIterating)
 {
     Set set;
@@ -455,7 +455,7 @@
     addReturnIterator<LinkedHashSet<int>>(false);
 }
 
-template<typename Set>
+template <typename Set>
 void excerciseValuePeekInType()
 {
     Set set;
@@ -537,7 +537,7 @@
     static bool equal(const Complicated& a, const Simple& b) { return a.m_simple.m_value == b.m_value; }
 };
 
-template<typename Set>
+template <typename Set>
 void translatorTest()
 {
     Set set;
@@ -658,7 +658,7 @@
     EXPECT_EQ(ptr2, ownPtr2);
 }
 
-template<typename Set>
+template <typename Set>
 void swapTestHelper()
 {
     int num = 10;
diff --git a/third_party/WebKit/Source/wtf/MainThread.cpp b/third_party/WebKit/Source/wtf/MainThread.cpp
index ec1876a..3856dbb 100644
--- a/third_party/WebKit/Source/wtf/MainThread.cpp
+++ b/third_party/WebKit/Source/wtf/MainThread.cpp
@@ -35,6 +35,7 @@
 #include "wtf/Functional.h"
 #include "wtf/Threading.h"
 #include "wtf/text/AtomicString.h"
+#include "wtf/text/StringStatics.h"
 
 namespace WTF {
 
@@ -52,6 +53,7 @@
     mainThreadIdentifier = currentThread();
 
     AtomicString::init();
+    StringStatics::init();
 }
 
 namespace internal {
diff --git a/third_party/WebKit/Source/wtf/MathExtras.h b/third_party/WebKit/Source/wtf/MathExtras.h
index bb71b26..d206f10e 100644
--- a/third_party/WebKit/Source/wtf/MathExtras.h
+++ b/third_party/WebKit/Source/wtf/MathExtras.h
@@ -36,8 +36,8 @@
 #endif
 
 #if OS(OPENBSD)
-#include <sys/types.h>
 #include <machine/ieee.h>
+#include <sys/types.h>
 #endif
 
 const double piDouble = M_PI;
@@ -299,9 +299,9 @@
 // Calculate d % 2^{64}.
 inline void doubleToInteger(double d, unsigned long long& value)
 {
-    if (std::isnan(d) || std::isinf(d))
+    if (std::isnan(d) || std::isinf(d)) {
         value = 0;
-    else {
+    } else {
         // -2^{64} < fmodValue < 2^{64}.
         double fmodValue = fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0);
         if (fmodValue >= 0) {
diff --git a/third_party/WebKit/Source/wtf/NonCopyingSort.h b/third_party/WebKit/Source/wtf/NonCopyingSort.h
index ec5c6ec1..4315429 100644
--- a/third_party/WebKit/Source/wtf/NonCopyingSort.h
+++ b/third_party/WebKit/Source/wtf/NonCopyingSort.h
@@ -31,7 +31,7 @@
 
 using std::swap;
 
-template<typename RandomAccessIterator, typename Predicate>
+template <typename RandomAccessIterator, typename Predicate>
 inline void siftDown(RandomAccessIterator array, ptrdiff_t start, ptrdiff_t end, Predicate compareLess)
 {
     ptrdiff_t root = start;
@@ -44,12 +44,13 @@
         if (compareLess(array[root], array[child])) {
             swap(array[root], array[child]);
             root = child;
-        } else
+        } else {
             return;
+        }
     }
 }
 
-template<typename RandomAccessIterator, typename Predicate>
+template <typename RandomAccessIterator, typename Predicate>
 inline void heapify(RandomAccessIterator array, ptrdiff_t count, Predicate compareLess)
 {
     ptrdiff_t start = (count - 2) / 2;
@@ -60,7 +61,7 @@
     }
 }
 
-template<typename RandomAccessIterator, typename Predicate>
+template <typename RandomAccessIterator, typename Predicate>
 void heapSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess)
 {
     ptrdiff_t count = end - start;
@@ -74,11 +75,12 @@
     }
 }
 
-template<typename RandomAccessIterator, typename Predicate>
+template <typename RandomAccessIterator, typename Predicate>
 inline void nonCopyingSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess)
 {
-    // heapsort happens to use only swaps, not copies, but the essential thing about
-    // this function is the fact that it does not copy, not the specific algorithm
+    // heapsort happens to use only swaps, not copies, but the essential thing
+    // about this function is the fact that it does not copy, not the specific
+    // algorithm
     heapSort(start, end, compareLess);
 }
 
diff --git a/third_party/WebKit/Source/wtf/OwnPtr.h b/third_party/WebKit/Source/wtf/OwnPtr.h
index 1f65b31..fa4ece7 100644
--- a/third_party/WebKit/Source/wtf/OwnPtr.h
+++ b/third_party/WebKit/Source/wtf/OwnPtr.h
@@ -31,193 +31,216 @@
 
 namespace WTF {
 
-    template<typename T> class PassOwnPtr;
+template <typename T> class PassOwnPtr;
 
-    template<typename T> class OwnPtr {
-        WTF_MAKE_NONCOPYABLE(OwnPtr);
-    public:
-        typedef typename RemoveExtent<T>::Type ValueType;
-        typedef ValueType* PtrType;
+template <typename T> class OwnPtr {
+    WTF_MAKE_NONCOPYABLE(OwnPtr);
+public:
+    typedef typename RemoveExtent<T>::Type ValueType;
+    typedef ValueType* PtrType;
 
-        OwnPtr() : m_ptr(0) { }
-        OwnPtr(std::nullptr_t) : m_ptr(0) { }
+    OwnPtr() : m_ptr(nullptr) {}
+    OwnPtr(std::nullptr_t) : m_ptr(nullptr) {}
 
-        // See comment in PassOwnPtr.h for why this takes a const reference.
-        OwnPtr(const PassOwnPtr<T>&);
-        template<typename U> OwnPtr(const PassOwnPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
+    // See comment in PassOwnPtr.h for why this takes a const reference.
+    OwnPtr(const PassOwnPtr<T>&);
+    template <typename U> OwnPtr(const PassOwnPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
 
-        // Hash table deleted values, which are only constructed and never copied or destroyed.
-        OwnPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-        bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+    // Hash table deleted values, which are only constructed and never copied or
+    // destroyed.
+    OwnPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) {}
+    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
 
-        ~OwnPtr()
-        {
-            OwnedPtrDeleter<T>::deletePtr(m_ptr);
-            m_ptr = 0;
-        }
-
-        PtrType get() const { return m_ptr; }
-
-        void clear();
-        PassOwnPtr<T> release();
-        PtrType leakPtr() WARN_UNUSED_RETURN;
-
-        ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-        PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
-
-        ValueType& operator[](std::ptrdiff_t i) const;
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef PtrType OwnPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
-
-        OwnPtr& operator=(const PassOwnPtr<T>&);
-        OwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
-        template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
-
-        OwnPtr(OwnPtr&&);
-        template<typename U> OwnPtr(OwnPtr<U>&&);
-
-        OwnPtr& operator=(OwnPtr&&);
-        template<typename U> OwnPtr& operator=(OwnPtr<U>&&);
-
-        void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
-
-        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-
-    private:
-        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
-        // double-destruction), so these equality operators should never be needed.
-        template<typename U> bool operator==(const OwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator!=(const OwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator==(const PassOwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator!=(const PassOwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-
-        PtrType m_ptr;
-    };
-
-    template<typename T> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<T>& o)
-        : m_ptr(o.leakPtr())
+    ~OwnPtr()
     {
+        OwnedPtrDeleter<T>::deletePtr(m_ptr);
+        m_ptr = nullptr;
     }
 
-    template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
-        : m_ptr(o.leakPtr())
+    PtrType get() const { return m_ptr; }
+
+    void clear();
+    PassOwnPtr<T> release();
+    PtrType leakPtr() WARN_UNUSED_RETURN;
+
+    ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+    PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
+
+    ValueType& operator[](std::ptrdiff_t i) const;
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to
+    // other integer types.
+    typedef PtrType OwnPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
+
+    OwnPtr& operator=(const PassOwnPtr<T>&);
+    OwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
+    template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
+
+    OwnPtr(OwnPtr&&);
+    template <typename U> OwnPtr(OwnPtr<U>&&);
+
+    OwnPtr& operator=(OwnPtr&&);
+    template <typename U> OwnPtr& operator=(OwnPtr<U>&&);
+
+    void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
+
+    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
+private:
+    // We should never have two OwnPtrs for the same underlying object
+    // (otherwise we'll get double-destruction), so these equality operators
+    // should never be needed.
+    template <typename U> bool operator==(const OwnPtr<U>&) const
     {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator!=(const OwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator==(const PassOwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator!=(const PassOwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
     }
 
-    template<typename T> inline void OwnPtr<T>::clear()
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        OwnedPtrDeleter<T>::deletePtr(ptr);
-    }
+    PtrType m_ptr;
+};
 
-    template<typename T> inline PassOwnPtr<T> OwnPtr<T>::release()
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        return PassOwnPtr<T>(ptr);
-    }
+template <typename T> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<T>& o)
+    : m_ptr(o.leakPtr())
+{
+}
 
-    template<typename T> inline typename OwnPtr<T>::PtrType OwnPtr<T>::leakPtr()
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
+template <typename T>
+template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
+    : m_ptr(o.leakPtr())
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+}
 
-    template<typename T> inline typename OwnPtr<T>::ValueType& OwnPtr<T>::operator[](std::ptrdiff_t i) const
-    {
-        static_assert(IsArray<T>::value, "elements access is possible for arrays only");
-        ASSERT(m_ptr);
-        ASSERT(i >= 0);
-        return m_ptr[i];
-    }
+template <typename T> inline void OwnPtr<T>::clear()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = nullptr;
+    OwnedPtrDeleter<T>::deletePtr(ptr);
+}
 
-    template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        OwnedPtrDeleter<T>::deletePtr(ptr);
-        return *this;
-    }
+template <typename T> inline PassOwnPtr<T> OwnPtr<T>::release()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = nullptr;
+    return PassOwnPtr<T>(ptr);
+}
 
-    template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
-    {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        OwnedPtrDeleter<T>::deletePtr(ptr);
-        return *this;
-    }
+template <typename T> inline typename OwnPtr<T>::PtrType OwnPtr<T>::leakPtr()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = nullptr;
+    return ptr;
+}
 
-    template<typename T> inline OwnPtr<T>::OwnPtr(OwnPtr<T>&& o)
-        : m_ptr(o.leakPtr())
-    {
-    }
+template <typename T> inline typename OwnPtr<T>::ValueType& OwnPtr<T>::operator[](std::ptrdiff_t i) const
+{
+    static_assert(IsArray<T>::value, "elements access is possible for arrays only");
+    ASSERT(m_ptr);
+    ASSERT(i >= 0);
+    return m_ptr[i];
+}
 
-    template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(OwnPtr<U>&& o)
-        : m_ptr(o.leakPtr())
-    {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
-    }
+template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    OwnedPtrDeleter<T>::deletePtr(ptr);
+    return *this;
+}
 
-    template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<T>&& o)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        OwnedPtrDeleter<T>::deletePtr(ptr);
+template <typename T>
+template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    OwnedPtrDeleter<T>::deletePtr(ptr);
+    return *this;
+}
 
-        return *this;
-    }
+template <typename T> inline OwnPtr<T>::OwnPtr(OwnPtr<T>&& o)
+    : m_ptr(o.leakPtr())
+{
+}
 
-    template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<U>&& o)
-    {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        OwnedPtrDeleter<T>::deletePtr(ptr);
+template <typename T>
+template <typename U> inline OwnPtr<T>::OwnPtr(OwnPtr<U>&& o)
+    : m_ptr(o.leakPtr())
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+}
 
-        return *this;
-    }
+template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<T>&& o)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    OwnedPtrDeleter<T>::deletePtr(ptr);
 
-    template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
-    {
-        a.swap(b);
-    }
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
-    {
-        return a.get() == b;
-    }
+template <typename T>
+template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<U>&& o)
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    OwnedPtrDeleter<T>::deletePtr(ptr);
 
-    template<typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b)
-    {
-        return a == b.get();
-    }
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
-    {
-        return a.get() != b;
-    }
+template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
+{
+    a.swap(b);
+}
 
-    template<typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
-    {
-        return a != b.get();
-    }
+template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
 
-    template<typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
-    {
-        return p.get();
-    }
+template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b)
+{
+    return a == b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
+{
+    return a != b.get();
+}
+
+template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
+{
+    return p.get();
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/PassOwnPtr.h b/third_party/WebKit/Source/wtf/PassOwnPtr.h
index c35aefe..4bc5c0ed 100644
--- a/third_party/WebKit/Source/wtf/PassOwnPtr.h
+++ b/third_party/WebKit/Source/wtf/PassOwnPtr.h
@@ -32,112 +32,136 @@
 
 namespace WTF {
 
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnPtr;
-    template<typename T> PassOwnPtr<T> adoptPtr(T*);
-    template<typename T> PassOwnPtr<T[]> adoptArrayPtr(T*);
+template <typename T> class OwnPtr;
+template <typename T> class PassOwnPtr;
+template <typename T> PassOwnPtr<T> adoptPtr(T*);
+template <typename T> PassOwnPtr<T[]> adoptArrayPtr(T*);
 
-    template<typename T> class PassOwnPtr {
-    public:
-        typedef typename RemoveExtent<T>::Type ValueType;
-        typedef ValueType* PtrType;
+template <typename T> class PassOwnPtr {
+public:
+    typedef typename RemoveExtent<T>::Type ValueType;
+    typedef ValueType* PtrType;
 
-        PassOwnPtr() : m_ptr(0) { }
-        PassOwnPtr(std::nullptr_t) : m_ptr(0) { }
+    PassOwnPtr() : m_ptr(nullptr) {}
+    PassOwnPtr(std::nullptr_t) : m_ptr(nullptr) {}
 
-        // It somewhat breaks the type system to allow transfer of ownership out of
-        // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
-        // temporaries, and we don't have a need to use real const PassOwnPtrs anyway.
-        PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { }
-        template<typename U> PassOwnPtr(const PassOwnPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
+    // It somewhat breaks the type system to allow transfer of ownership out of
+    // a const PassOwnPtr. However, it makes it much easier to work with
+    // PassOwnPtr temporaries, and we don't have a need to use real const
+    // PassOwnPtrs anyway.
+    PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) {}
+    template <typename U> PassOwnPtr(const PassOwnPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
 
-        ~PassOwnPtr() { OwnedPtrDeleter<T>::deletePtr(m_ptr); }
+    ~PassOwnPtr() { OwnedPtrDeleter<T>::deletePtr(m_ptr); }
 
-        PtrType get() const { return m_ptr; }
+    PtrType get() const { return m_ptr; }
 
-        PtrType leakPtr() const WARN_UNUSED_RETURN;
+    PtrType leakPtr() const WARN_UNUSED_RETURN;
 
-        ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-        PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
+    ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+    PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
 
-        bool operator!() const { return !m_ptr; }
+    bool operator!() const { return !m_ptr; }
 
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
+    // This conversion operator allows implicit conversion to bool but not to
+    // other integer types.
+    typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
 
-        template<typename U> friend PassOwnPtr<U> adoptPtr(U*);
-        template<typename U> friend PassOwnPtr<U[]> adoptArrayPtr(U*);
-        template<typename U> friend class OwnPtr;
+    template <typename U> friend PassOwnPtr<U> adoptPtr(U*);
+    template <typename U> friend PassOwnPtr<U[]> adoptArrayPtr(U*);
+    template <typename U> friend class OwnPtr;
 
-    private:
-        explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
+private:
+    explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) {}
 
-        PassOwnPtr& operator=(const PassOwnPtr&) { static_assert(!sizeof(T*), "PassOwnPtr should never be assigned to"); return *this; }
-
-        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
-        // double-destruction), so these equality operators should never be needed.
-        template<typename U> bool operator==(const PassOwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator!=(const PassOwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator==(const OwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-        template<typename U> bool operator!=(const OwnPtr<U>&) const { static_assert(!sizeof(U*), "OwnPtrs should never be equal"); return false; }
-
-        mutable PtrType m_ptr;
-    };
-
-    template<typename T> template<typename U> inline PassOwnPtr<T>::PassOwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
-        : m_ptr(o.leakPtr())
+    PassOwnPtr& operator=(const PassOwnPtr&)
     {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+        static_assert(!sizeof(T*), "PassOwnPtr should never be assigned to");
+        return *this;
     }
 
-    template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
+    // We should never have two OwnPtrs for the same underlying object
+    // (otherwise we'll get double-destruction), so these equality operators
+    // should never be needed.
+    template <typename U> bool operator==(const PassOwnPtr<U>&) const
     {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator!=(const PassOwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator==(const OwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
+    }
+    template <typename U> bool operator!=(const OwnPtr<U>&) const
+    {
+        static_assert(!sizeof(U*), "OwnPtrs should never be equal");
+        return false;
     }
 
-    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
-    {
-        return a.get() == b;
-    }
+    mutable PtrType m_ptr;
+};
 
-    template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
-    {
-        return a == b.get();
-    }
+template <typename T>
+template <typename U> inline PassOwnPtr<T>::PassOwnPtr(const PassOwnPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
+    : m_ptr(o.leakPtr())
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+}
 
-    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
-    {
-        return a.get() != b;
-    }
+template <typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
+{
+    PtrType ptr = m_ptr;
+    m_ptr = nullptr;
+    return ptr;
+}
 
-    template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
-    {
-        return a != b.get();
-    }
+template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
 
-    template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr)
-    {
-        return PassOwnPtr<T>(ptr);
-    }
+template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
+{
+    return a == b.get();
+}
 
-    template<typename T> inline PassOwnPtr<T[]> adoptArrayPtr(T* ptr)
-    {
-        return PassOwnPtr<T[]>(ptr);
-    }
+template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
 
-    template<typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
-    {
-        static_assert(!IsArray<T>::value, "pointers to array must never be converted");
-        return adoptPtr(static_cast<T*>(p.leakPtr()));
-    }
+template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
+{
+    return a != b.get();
+}
 
-    template<typename T> inline T* getPtr(const PassOwnPtr<T>& p)
-    {
-        return p.get();
-    }
+template <typename T> inline PassOwnPtr<T> adoptPtr(T* ptr)
+{
+    return PassOwnPtr<T>(ptr);
+}
+
+template <typename T> inline PassOwnPtr<T[]> adoptArrayPtr(T* ptr)
+{
+    return PassOwnPtr<T[]>(ptr);
+}
+
+template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
+{
+    static_assert(!IsArray<T>::value, "pointers to array must never be converted");
+    return adoptPtr(static_cast<T*>(p.leakPtr()));
+}
+
+template <typename T> inline T* getPtr(const PassOwnPtr<T>& p)
+{
+    return p.get();
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/PassRefPtr.h b/third_party/WebKit/Source/wtf/PassRefPtr.h
index 9ae81bf1..5e3a4e1 100644
--- a/third_party/WebKit/Source/wtf/PassRefPtr.h
+++ b/third_party/WebKit/Source/wtf/PassRefPtr.h
@@ -28,175 +28,181 @@
 
 namespace WTF {
 
-    template<typename T> class RefPtr;
-    template<typename T> class PassRefPtr;
-    template<typename T> PassRefPtr<T> adoptRef(T*);
+template <typename T> class RefPtr;
+template <typename T> class PassRefPtr;
+template <typename T> PassRefPtr<T> adoptRef(T*);
 
-    inline void adopted(const void*) { }
+inline void adopted(const void*) {}
 
-    // requireAdoption() is not overloaded for WTF::RefCounted, which has a
-    // built-in assumption that adoption is required. requireAdoption() is
-    // for bootstrapping alternate reference count classes that are compatible
-    // with ReftPtr/PassRefPtr but cannot have adoption checks enabled
-    // by default, such as skia's SkRefCnt. The purpose of requireAdoption()
-    // is to enable adoption checks only once it is known that the object will
-    // be used with RefPtr/PassRefPtr.
-    inline void requireAdoption(const void*) { }
+// requireAdoption() is not overloaded for WTF::RefCounted, which has a built-in
+// assumption that adoption is required. requireAdoption() is for bootstrapping
+// alternate reference count classes that are compatible with ReftPtr/PassRefPtr
+// but cannot have adoption checks enabled by default, such as skia's
+// SkRefCnt. The purpose of requireAdoption() is to enable adoption checks only
+// once it is known that the object will be used with RefPtr/PassRefPtr.
+inline void requireAdoption(const void*) {}
 
-    template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
+template <typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
+{
+    if (LIKELY(ptr != 0)) {
+        requireAdoption(ptr);
+        ptr->ref();
+    }
+}
+
+template <typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
+{
+    if (LIKELY(ptr != 0))
+        ptr->deref();
+}
+
+template <typename T> class PassRefPtr {
+public:
+    PassRefPtr() : m_ptr(nullptr) {}
+    PassRefPtr(std::nullptr_t) : m_ptr(nullptr) {}
+    PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
+    template <typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
+    explicit PassRefPtr(T& ptr) : m_ptr(&ptr) { m_ptr->ref(); }
+    // It somewhat breaks the type system to allow transfer of ownership out of
+    // a const PassRefPtr. However, it makes it much easier to work with
+    // PassRefPtr temporaries, and we don't have a need to use real const
+    // PassRefPtrs anyway.
+    PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) {}
+    template <typename U> PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) {}
+
+    ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
+
+    template <typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
+
+    T* get() const { return m_ptr; }
+
+    T* leakRef() const WARN_UNUSED_RETURN;
+
+    T& operator*() const { return *m_ptr; }
+    T* operator->() const { return m_ptr; }
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to
+    // other integer types.
+    typedef T* (PassRefPtr::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
+
+    friend PassRefPtr adoptRef<T>(T*);
+
+private:
+    enum AdoptRefTag { AdoptRef };
+    PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) {}
+
+    PassRefPtr& operator=(const PassRefPtr&)
     {
-        if (LIKELY(ptr != 0)) {
-            requireAdoption(ptr);
-            ptr->ref();
-        }
+        static_assert(!sizeof(T*), "PassRefPtr should never be assigned to");
+        return *this;
     }
 
-    template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
-    {
-        if (LIKELY(ptr != 0))
-            ptr->deref();
-    }
+    mutable T* m_ptr;
+};
 
-    template<typename T> class PassRefPtr {
-    public:
-        PassRefPtr() : m_ptr(0) { }
-        PassRefPtr(std::nullptr_t) : m_ptr(0) { }
-        PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
-        template<typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
-        explicit PassRefPtr(T& ptr) : m_ptr(&ptr) { m_ptr->ref(); }
-        // It somewhat breaks the type system to allow transfer of ownership out of
-        // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
-        // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
-        PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
-        template<typename U> PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) { }
+template <typename T>
+template <typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
+    : m_ptr(o.get())
+{
+    T* ptr = m_ptr;
+    refIfNotNull(ptr);
+}
 
-        ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
+template <typename T> inline T* PassRefPtr<T>::leakRef() const
+{
+    T* ptr = m_ptr;
+    m_ptr = nullptr;
+    return ptr;
+}
 
-        template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
+template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-        T* get() const { return m_ptr; }
+template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-        T* leakRef() const WARN_UNUSED_RETURN;
+template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-        T& operator*() const { return *m_ptr; }
-        T* operator->() const { return m_ptr; }
+template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
 
-        bool operator!() const { return !m_ptr; }
+template <typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
+{
+    return a == b.get();
+}
 
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef T* (PassRefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
+template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RawPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-        friend PassRefPtr adoptRef<T>(T*);
+template <typename T, typename U> inline bool operator==(const RawPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-    private:
-        enum AdoptRefTag { AdoptRef };
-        PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) { }
+template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-        PassRefPtr& operator=(const PassRefPtr&) { static_assert(!sizeof(T*), "PassRefPtr should never be assigned to"); return *this; }
+template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-        mutable T* m_ptr;
-    };
+template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-    template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
-        : m_ptr(o.get())
-    {
-        T* ptr = m_ptr;
-        refIfNotNull(ptr);
-    }
+template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
 
-    template<typename T> inline T* PassRefPtr<T>::leakRef() const
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
+template <typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
+{
+    return a != b.get();
+}
 
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
+template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RawPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
+template <typename T, typename U> inline bool operator!=(const RawPtr<T>& a, const PassRefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
+template <typename T> PassRefPtr<T> adoptRef(T* p)
+{
+    adopted(p);
+    return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef);
+}
 
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
-    {
-        return a.get() == b;
-    }
+template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
+{
+    return adoptRef(static_cast<T*>(p.leakRef()));
+}
 
-    template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
-    {
-        return a == b.get();
-    }
-
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RawPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
-
-    template<typename T, typename U> inline bool operator==(const RawPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
-    {
-        return a.get() != b;
-    }
-
-    template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
-    {
-        return a != b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RawPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
-
-    template<typename T, typename U> inline bool operator!=(const RawPtr<T>& a, const PassRefPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
-
-    template<typename T> PassRefPtr<T> adoptRef(T* p)
-    {
-        adopted(p);
-        return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef);
-    }
-
-    template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
-    {
-        return adoptRef(static_cast<T*>(p.leakRef()));
-    }
-
-    template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
-    {
-        return p.get();
-    }
+template <typename T> inline T* getPtr(const PassRefPtr<T>& p)
+{
+    return p.get();
+}
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/PrintStream.cpp b/third_party/WebKit/Source/wtf/PrintStream.cpp
index 09cdf386..5553c3d 100644
--- a/third_party/WebKit/Source/wtf/PrintStream.cpp
+++ b/third_party/WebKit/Source/wtf/PrintStream.cpp
@@ -24,16 +24,16 @@
  */
 
 #include "config.h"
-#include "PrintStream.h"
+#include "wtf/PrintStream.h"
 
-#include <stdio.h>
 #include "wtf/text/CString.h"
 #include "wtf/text/WTFString.h"
+#include <stdio.h>
 
 namespace WTF {
 
-PrintStream::PrintStream() { }
-PrintStream::~PrintStream() { } // Force the vtable to be in this module
+PrintStream::PrintStream() {}
+PrintStream::~PrintStream() {} // Force the vtable to be in this module
 
 void PrintStream::printf(const char* format, ...)
 {
diff --git a/third_party/WebKit/Source/wtf/PrintStream.h b/third_party/WebKit/Source/wtf/PrintStream.h
index 1386d414..6f79ccd 100644
--- a/third_party/WebKit/Source/wtf/PrintStream.h
+++ b/third_party/WebKit/Source/wtf/PrintStream.h
@@ -26,11 +26,11 @@
 #ifndef PrintStream_h
 #define PrintStream_h
 
-#include <stdarg.h>
 #include "wtf/FastAllocBase.h"
 #include "wtf/Noncopyable.h"
 #include "wtf/StdLibExtras.h"
 #include "wtf/WTFExport.h"
+#include <stdarg.h>
 
 namespace WTF {
 
@@ -50,13 +50,13 @@
     // the implementation should flush its buffers if it had not done so already.
     virtual void flush();
 
-    template<typename T>
+    template <typename T>
     void print(const T& value)
     {
         printInternal(*this, value);
     }
 
-    template<typename T1, typename... RemainingTypes>
+    template <typename T1, typename... RemainingTypes>
     void print(const T1& value1, const RemainingTypes&... values)
     {
         print(value1);
@@ -80,7 +80,7 @@
 WTF_EXPORT void printInternal(PrintStream&, float);
 WTF_EXPORT void printInternal(PrintStream&, double);
 
-template<typename T>
+template <typename T>
 void printInternal(PrintStream& out, const T& value)
 {
     value.dump(out);
@@ -126,7 +126,7 @@
 void dumpCharacter(PrintStream&, char);
 MAKE_PRINT_ADAPTOR(CharacterDump, char, dumpCharacter);
 
-template<typename T>
+template <typename T>
 class PointerDump {
 public:
     PointerDump(const T* ptr)
@@ -141,11 +141,12 @@
         else
             out.print("(null)");
     }
+
 private:
     const T* m_ptr;
 };
 
-template<typename T>
+template <typename T>
 PointerDump<T> pointerDump(const T* ptr) { return PointerDump<T>(ptr); }
 
 } // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/RefCountedLeakCounter.h b/third_party/WebKit/Source/wtf/RefCountedLeakCounter.h
index 3b49d94..6617c75 100644
--- a/third_party/WebKit/Source/wtf/RefCountedLeakCounter.h
+++ b/third_party/WebKit/Source/wtf/RefCountedLeakCounter.h
@@ -26,20 +26,20 @@
 
 namespace WTF {
 
-    struct WTF_EXPORT RefCountedLeakCounter {
-        explicit RefCountedLeakCounter(const char* description);
-        ~RefCountedLeakCounter();
+struct WTF_EXPORT RefCountedLeakCounter {
+    explicit RefCountedLeakCounter(const char* description);
+    ~RefCountedLeakCounter();
 
-        void increment();
-        void decrement();
+    void increment();
+    void decrement();
 
 #if ENABLE(ASSERT)
-    private:
-        volatile int m_count;
-        const char* m_description;
+private:
+    volatile int m_count;
+    const char* m_description;
 #endif
-    };
+};
 
-}  // namespace WTF
+} // namespace WTF
 
 #endif
diff --git a/third_party/WebKit/Source/wtf/RefPtr.h b/third_party/WebKit/Source/wtf/RefPtr.h
index 59690234..b935d27 100644
--- a/third_party/WebKit/Source/wtf/RefPtr.h
+++ b/third_party/WebKit/Source/wtf/RefPtr.h
@@ -31,185 +31,198 @@
 
 namespace WTF {
 
-    template<typename T> class PassRefPtr;
+template <typename T> class PassRefPtr;
 
-    template<typename T> class RefPtr {
-    public:
-        ALWAYS_INLINE RefPtr() : m_ptr(0) { }
-        ALWAYS_INLINE RefPtr(std::nullptr_t) : m_ptr(0) { }
-        ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
-        template<typename U> RefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
-        ALWAYS_INLINE explicit RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); }
-        ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
-        template<typename U> RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
+template <typename T> class RefPtr {
+public:
+    ALWAYS_INLINE RefPtr() : m_ptr(nullptr) {}
+    ALWAYS_INLINE RefPtr(std::nullptr_t) : m_ptr(nullptr) {}
+    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
+    template <typename U> RefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
+    ALWAYS_INLINE explicit RefPtr(T& ref) : m_ptr(&ref) { m_ptr->ref(); }
+    ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
+    template <typename U> RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
 
-        RefPtr(RefPtr&& o) : m_ptr(o.m_ptr) { o.m_ptr = 0; }
-        RefPtr& operator=(RefPtr&&);
+    RefPtr(RefPtr&& o) : m_ptr(o.m_ptr) { o.m_ptr = nullptr; }
+    RefPtr& operator=(RefPtr&&);
 
-        // See comments in PassRefPtr.h for an explanation of why this takes a const reference.
-        template<typename U> RefPtr(const PassRefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
+    // See comments in PassRefPtr.h for an explanation of why this takes a const
+    // reference.
+    template <typename U> RefPtr(const PassRefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
 
-        // Hash table deleted values, which are only constructed and never copied or destroyed.
-        RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-        bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+    // Hash table deleted values, which are only constructed and never copied or
+    // destroyed.
+    RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) {}
+    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
 
-        ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
+    ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
 
-        ALWAYS_INLINE T* get() const { return m_ptr; }
+    ALWAYS_INLINE T* get() const { return m_ptr; }
 
-        void clear();
-        PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
-
-        T& operator*() const { return *m_ptr; }
-        ALWAYS_INLINE T* operator->() const { return m_ptr; }
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef T* (RefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
-
-        RefPtr& operator=(const RefPtr&);
-        RefPtr& operator=(T*);
-        RefPtr& operator=(const PassRefPtr<T>&);
-        RefPtr& operator=(std::nullptr_t) { clear(); return *this; }
-
-        template<typename U> RefPtr<T>& operator=(const RefPtr<U>&);
-        template<typename U> RefPtr<T>& operator=(const PassRefPtr<U>&);
-        template<typename U> RefPtr<T>& operator=(const RawPtr<U>&);
-
-        void swap(RefPtr&);
-
-        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-
-    private:
-        T* m_ptr;
-    };
-
-    template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
-        : m_ptr(o.leakRef())
+    void clear();
+    PassRefPtr<T> release()
     {
+        PassRefPtr<T> tmp = adoptRef(m_ptr);
+        m_ptr = nullptr;
+        return tmp;
     }
 
-    template<typename T> inline void RefPtr<T>::clear()
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        derefIfNotNull(ptr);
-    }
+    T& operator*() const { return *m_ptr; }
+    ALWAYS_INLINE T* operator->() const { return m_ptr; }
 
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr& o)
-    {
-        RefPtr ptr = o;
-        swap(ptr);
-        return *this;
-    }
+    bool operator!() const { return !m_ptr; }
 
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr&& o)
-    {
-        // FIXME: Instead of explicitly casting to RefPtr&& here, we should use std::move, but that requires us to
-        // have a standard library that supports move semantics.
-        RefPtr ptr = static_cast<RefPtr&&>(o);
-        swap(ptr);
-        return *this;
-    }
+    // This conversion operator allows implicit conversion to bool but not to
+    // other integer types.
+    typedef T* (RefPtr::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
 
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
-    {
-        RefPtr ptr = o;
-        swap(ptr);
-        return *this;
-    }
+    RefPtr& operator=(const RefPtr&);
+    RefPtr& operator=(T*);
+    RefPtr& operator=(const PassRefPtr<T>&);
+    RefPtr& operator=(std::nullptr_t) { clear(); return *this; }
 
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
-    {
-        RefPtr ptr = optr;
-        swap(ptr);
-        return *this;
-    }
+    template <typename U> RefPtr<T>& operator=(const RefPtr<U>&);
+    template <typename U> RefPtr<T>& operator=(const PassRefPtr<U>&);
+    template <typename U> RefPtr<T>& operator=(const RawPtr<U>&);
 
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
-    {
-        RefPtr ptr = o;
-        swap(ptr);
-        return *this;
-    }
+    void swap(RefPtr&);
 
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
-    {
-        RefPtr ptr = o;
-        swap(ptr);
-        return *this;
-    }
+    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
 
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RawPtr<U>& o)
-    {
-        RefPtr ptr = o.get();
-        swap(ptr);
-        return *this;
-    }
+private:
+    T* m_ptr;
+};
 
-    template<class T> inline void RefPtr<T>::swap(RefPtr& o)
-    {
-        std::swap(m_ptr, o.m_ptr);
-    }
+template <typename T>
+template <typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
+    : m_ptr(o.leakRef())
+{
+}
 
-    template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
-    {
-        a.swap(b);
-    }
+template <typename T> inline void RefPtr<T>::clear()
+{
+    T* ptr = m_ptr;
+    m_ptr = nullptr;
+    derefIfNotNull(ptr);
+}
 
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
+template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr& o)
+{
+    RefPtr ptr = o;
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
-    {
-        return a.get() == b;
-    }
+template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr&& o)
+{
+    // FIXME: Instead of explicitly casting to RefPtr&& here, we should use
+    // std::move, but that requires us to have a standard library that supports
+    // move semantics.
+    RefPtr ptr = static_cast<RefPtr&&>(o);
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b)
-    {
-        return a == b.get();
-    }
+template <typename T>
+template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
+{
+    RefPtr ptr = o;
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
+template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
+{
+    RefPtr ptr = optr;
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
-    {
-        return a.get() != b;
-    }
+template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
+{
+    RefPtr ptr = o;
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
-    {
-        return a != b.get();
-    }
+template <typename T>
+template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
+{
+    RefPtr ptr = o;
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
-    {
-        return RefPtr<T>(static_cast<T*>(p.get()));
-    }
+template <typename T>
+template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RawPtr<U>& o)
+{
+    RefPtr ptr = o.get();
+    swap(ptr);
+    return *this;
+}
 
-    template<typename T> inline T* getPtr(const RefPtr<T>& p)
-    {
-        return p.get();
-    }
+template <class T> inline void RefPtr<T>::swap(RefPtr& o)
+{
+    std::swap(m_ptr, o.m_ptr);
+}
 
-    template<typename T> class RefPtrValuePeeker {
-    public:
-        ALWAYS_INLINE RefPtrValuePeeker(T* p): m_ptr(p) { }
-        ALWAYS_INLINE RefPtrValuePeeker(std::nullptr_t): m_ptr(0) { }
-        template<typename U> RefPtrValuePeeker(const RefPtr<U>& p): m_ptr(p.get()) { }
-        template<typename U> RefPtrValuePeeker(const PassRefPtr<U>& p): m_ptr(p.get()) { }
+template <class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
+{
+    a.swap(b);
+}
 
-        ALWAYS_INLINE operator T*() const { return m_ptr; }
-    private:
-        T* m_ptr;
-    };
+template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
+{
+    return a.get() == b.get();
+}
+
+template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b)
+{
+    return a == b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
+{
+    return a.get() != b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
+{
+    return a != b.get();
+}
+
+template <typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
+{
+    return RefPtr<T>(static_cast<T*>(p.get()));
+}
+
+template <typename T> inline T* getPtr(const RefPtr<T>& p)
+{
+    return p.get();
+}
+
+template <typename T> class RefPtrValuePeeker {
+public:
+    ALWAYS_INLINE RefPtrValuePeeker(T* p): m_ptr(p) {}
+    ALWAYS_INLINE RefPtrValuePeeker(std::nullptr_t): m_ptr(nullptr) {}
+    template <typename U> RefPtrValuePeeker(const RefPtr<U>& p): m_ptr(p.get()) {}
+    template <typename U> RefPtrValuePeeker(const PassRefPtr<U>& p): m_ptr(p.get()) {}
+
+    ALWAYS_INLINE operator T*() const { return m_ptr; }
+private:
+    T* m_ptr;
+};
 
 } // namespace WTF
 
diff --git a/third_party/WebKit/Source/wtf/RetainPtr.h b/third_party/WebKit/Source/wtf/RetainPtr.h
index 92d0c9b..3ba98f4f 100644
--- a/third_party/WebKit/Source/wtf/RetainPtr.h
+++ b/third_party/WebKit/Source/wtf/RetainPtr.h
@@ -46,252 +46,276 @@
 
 namespace WTF {
 
-    // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
-    // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
+// Unlike most most of our smart pointers, RetainPtr can take either the pointer
+// type or the pointed-to type, so both RetainPtr<NSDictionary> and
+// RetainPtr<CFDictionaryRef> will work.
 
-    enum AdoptCFTag { AdoptCF };
-    enum AdoptNSTag { AdoptNS };
+enum AdoptCFTag { AdoptCF };
+enum AdoptNSTag { AdoptNS };
 
 #ifdef __OBJC__
-    inline void adoptNSReference(id ptr)
-    {
-        if (ptr) {
-            CFRetain(ptr);
-            [ptr release];
-        }
+inline void adoptNSReference(id ptr)
+{
+    if (ptr) {
+        CFRetain(ptr);
+        [ptr release];
     }
+}
 #endif
 
-    template<typename T> class RetainPtr {
-    public:
-        typedef typename RemovePointer<T>::Type ValueType;
-        typedef ValueType* PtrType;
+template <typename T> class RetainPtr {
+public:
+    typedef typename RemovePointer<T>::Type ValueType;
+    typedef ValueType* PtrType;
 
-        RetainPtr() : m_ptr(0) {}
-        RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
+    RetainPtr() : m_ptr(nullptr) {}
+    RetainPtr(PtrType ptr) : m_ptr(ptr)
+    {
+        if (ptr)
+            CFRetain(ptr);
+    }
 
-        RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { }
-        RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); }
+    RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) {}
+    RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); }
 
-        RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
-
-        RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) { }
-
-        // Hash table deleted values, which are only constructed and never copied or destroyed.
-        RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-        bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
-
-        ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
-
-        template<typename U> RetainPtr(const RetainPtr<U>&);
-
-        void clear();
-        PtrType leakRef() WARN_UNUSED_RETURN;
-
-        PtrType get() const { return m_ptr; }
-        PtrType operator->() const { return m_ptr; }
-#if COMPILER_SUPPORTS(CXX_EXPLICIT_CONVERSIONS)
-        explicit operator PtrType() const { return m_ptr; }
-#endif
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef PtrType RetainPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
-
-        RetainPtr& operator=(const RetainPtr&);
-        template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
-        RetainPtr& operator=(PtrType);
-        template<typename U> RetainPtr& operator=(U*);
-
-        RetainPtr& operator=(RetainPtr&&);
-        template<typename U> RetainPtr& operator=(RetainPtr<U>&&);
-
-#if !COMPILER_SUPPORTS(CXX_NULLPTR)
-        RetainPtr& operator=(std::nullptr_t) { clear(); return *this; }
-#endif
-
-        void adoptCF(PtrType);
-        void adoptNS(PtrType);
-
-        void swap(RetainPtr&);
-
-    private:
-        static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
-
-        PtrType m_ptr;
-    };
-
-    template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
-        : m_ptr(o.get())
+    RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr)
     {
         if (PtrType ptr = m_ptr)
             CFRetain(ptr);
     }
 
-    template<typename T> inline void RetainPtr<T>::clear()
+    RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) {}
+
+    // Hash table deleted values, which are only constructed and never copied or
+    // destroyed.
+    RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
+    ~RetainPtr()
     {
-        if (PtrType ptr = m_ptr) {
-            m_ptr = 0;
+        if (PtrType ptr = m_ptr)
             CFRelease(ptr);
-        }
     }
 
-    template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef()
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
+    template <typename U> RetainPtr(const RetainPtr<U>&);
 
-    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
+    void clear();
+    PtrType leakRef() WARN_UNUSED_RETURN;
+
+    PtrType get() const { return m_ptr; }
+    PtrType operator->() const { return m_ptr; }
+#if COMPILER_SUPPORTS(CXX_EXPLICIT_CONVERSIONS)
+    explicit operator PtrType() const { return m_ptr; }
+#endif
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to
+    // other integer types.
+    typedef PtrType RetainPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
+
+    RetainPtr& operator=(const RetainPtr&);
+    template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
+    RetainPtr& operator=(PtrType);
+    template <typename U> RetainPtr& operator=(U*);
+
+    RetainPtr& operator=(RetainPtr&&);
+    template <typename U> RetainPtr& operator=(RetainPtr<U>&&);
+
+#if !COMPILER_SUPPORTS(CXX_NULLPTR)
+    RetainPtr& operator=(std::nullptr_t)
     {
-        PtrType optr = o.get();
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
+        clear();
         return *this;
     }
+#endif
 
-    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
-    {
-        PtrType optr = o.get();
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
+    void adoptCF(PtrType);
+    void adoptNS(PtrType);
+
+    void swap(RetainPtr&);
+
+private:
+    static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
+
+    PtrType m_ptr;
+};
+
+template <typename T>
+template <typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
+    : m_ptr(o.get())
+{
+    if (PtrType ptr = m_ptr)
+        CFRetain(ptr);
+}
+
+template <typename T> inline void RetainPtr<T>::clear()
+{
+    if (PtrType ptr = m_ptr) {
+        m_ptr = nullptr;
+        CFRelease(ptr);
     }
+}
 
-    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
-    {
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
+template <typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = nullptr;
+    return ptr;
+}
 
-    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
-    {
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
+template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
+{
+    PtrType optr = o.get();
+    if (optr)
+        CFRetain(optr);
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+    return *this;
+}
 
-    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o)
-    {
-        adoptCF(o.leakRef());
-        return *this;
-    }
+template <typename T>
+template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
+{
+    PtrType optr = o.get();
+    if (optr)
+        CFRetain(optr);
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+    return *this;
+}
 
-    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o)
-    {
-        adoptCF(o.leakRef());
-        return *this;
-    }
+template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
+{
+    if (optr)
+        CFRetain(optr);
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+    return *this;
+}
 
-    template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-    }
+template <typename T>
+template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
+{
+    if (optr)
+        CFRetain(optr);
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+    return *this;
+}
 
-    template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
-    {
-        adoptNSReference(optr);
+template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o)
+{
+    adoptCF(o.leakRef());
+    return *this;
+}
 
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-    }
+template <typename T>
+template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o)
+{
+    adoptCF(o.leakRef());
+    return *this;
+}
 
-    template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
-    {
-        std::swap(m_ptr, o.m_ptr);
-    }
+template <typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+}
 
-    template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
-    {
-        a.swap(b);
-    }
+template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
+{
+    adoptNSReference(optr);
 
-    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
-    {
-        return a.get() == b.get();
-    }
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    if (ptr)
+        CFRelease(ptr);
+}
 
-    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
-    {
-        return a.get() == b;
-    }
+template <typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
+{
+    std::swap(m_ptr, o.m_ptr);
+}
 
-    template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
-    {
-        return a == b.get();
-    }
+template <typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
+{
+    a.swap(b);
+}
 
-    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
-    {
-        return a.get() != b.get();
-    }
+template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
+{
+    return a.get() == b.get();
+}
 
-    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
-    {
-        return a.get() != b;
-    }
+template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
+{
+    return a.get() == b;
+}
 
-    template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
-    {
-        return a != b.get();
-    }
+template <typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
+{
+    return a == b.get();
+}
 
-    template<typename T> inline RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
-    template<typename T> inline RetainPtr<T> adoptCF(T o)
-    {
-        return RetainPtr<T>(AdoptCF, o);
-    }
+template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
+{
+    return a.get() != b.get();
+}
 
-    template<typename T> inline RetainPtr<T> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
-    template<typename T> inline RetainPtr<T> adoptNS(T o)
-    {
-        return RetainPtr<T>(AdoptNS, o);
-    }
+template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
+{
+    return a.get() != b;
+}
 
-    // Helper function for creating a RetainPtr using template argument deduction.
-    template<typename T> inline RetainPtr<T> retainPtr(T) WARN_UNUSED_RETURN;
-    template<typename T> inline RetainPtr<T> retainPtr(T o)
-    {
-        return RetainPtr<T>(o);
-    }
+template <typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
+{
+    return a != b.get();
+}
 
-    template<typename P> struct HashTraits<RetainPtr<P>> : SimpleClassHashTraits<RetainPtr<P>> { };
+template <typename T> inline RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
+template <typename T> inline RetainPtr<T> adoptCF(T o)
+{
+    return RetainPtr<T>(AdoptCF, o);
+}
 
-    template<typename P> struct PtrHash<RetainPtr<P>> : PtrHash<typename RetainPtr<P>::PtrType> {
-        using PtrHash<typename RetainPtr<P>::PtrType>::hash;
-        static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
-        using PtrHash<typename RetainPtr<P>::PtrType>::equal;
-        static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
-        static bool equal(typename RetainPtr<P>::PtrType a, const RetainPtr<P>& b) { return a == b; }
-        static bool equal(const RetainPtr<P>& a, typename RetainPtr<P>::PtrType b) { return a == b; }
-    };
+template <typename T> inline RetainPtr<T> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
+template <typename T> inline RetainPtr<T> adoptNS(T o)
+{
+    return RetainPtr<T>(AdoptNS, o);
+}
 
-    template<typename P> struct DefaultHash<RetainPtr<P>> { typedef PtrHash<RetainPtr<P>> Hash; };
+// Helper function for creating a RetainPtr using template argument deduction.
+template <typename T> inline RetainPtr<T> retainPtr(T) WARN_UNUSED_RETURN;
+template <typename T> inline RetainPtr<T> retainPtr(T o)
+{
+    return RetainPtr<T>(o);
+}
+
+template <typename P> struct HashTraits<RetainPtr<P>> : SimpleClassHashTraits<RetainPtr<P>> { };
+
+template <typename P> struct PtrHash<RetainPtr<P>> : PtrHash<typename RetainPtr<P>::PtrType> {
+    using PtrHash<typename RetainPtr<P>::PtrType>::hash;
+    static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
+    using PtrHash<typename RetainPtr<P>::PtrType>::equal;
+    static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
+    static bool equal(typename RetainPtr<P>::PtrType a, const RetainPtr<P>& b) { return a == b; }
+    static bool equal(const RetainPtr<P>& a, typename RetainPtr<P>::PtrType b) { return a == b; }
+};
+
+template <typename P> struct DefaultHash<RetainPtr<P>> { typedef PtrHash<RetainPtr<P>> Hash; };
+
 } // namespace WTF
 
 using WTF::AdoptCF;
diff --git a/third_party/WebKit/Source/wtf/SaturatedArithmeticTest.cpp b/third_party/WebKit/Source/wtf/SaturatedArithmeticTest.cpp
index 360244a0..cd94256 100644
--- a/third_party/WebKit/Source/wtf/SaturatedArithmeticTest.cpp
+++ b/third_party/WebKit/Source/wtf/SaturatedArithmeticTest.cpp
@@ -29,8 +29,8 @@
  */
 
 #include "config.h"
-
 #include "wtf/SaturatedArithmetic.h"
+
 #include <gtest/gtest.h>
 #include <limits.h>
 
diff --git a/third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp b/third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp
index 7426e0f..4d35b41 100644
--- a/third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp
+++ b/third_party/WebKit/Source/wtf/ThreadSpecificWin.cpp
@@ -64,7 +64,7 @@
 
     void callDestructor()
     {
-       if (void* data = value())
+        if (void* data = value())
             m_destructor(data);
     }
 
diff --git a/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp b/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp
index 42091057..2cd1e54c8 100644
--- a/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp
+++ b/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp
@@ -191,7 +191,7 @@
 
 ThreadCondition::ThreadCondition()
 {
-    pthread_cond_init(&m_condition, NULL);
+    pthread_cond_init(&m_condition, nullptr);
 }
 
 ThreadCondition::~ThreadCondition()
diff --git a/third_party/WebKit/Source/wtf/ThreadingWin.cpp b/third_party/WebKit/Source/wtf/ThreadingWin.cpp
index 8b72eb0..7128858 100644
--- a/third_party/WebKit/Source/wtf/ThreadingWin.cpp
+++ b/third_party/WebKit/Source/wtf/ThreadingWin.cpp
@@ -84,7 +84,7 @@
  */
 
 #include "config.h"
-#include "Threading.h"
+#include "wtf/Threading.h"
 
 #if OS(WIN)
 
@@ -186,7 +186,7 @@
     // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
     DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
 
-    if (result != 0) {       // We got the lock
+    if (result != 0) { // We got the lock
         // If this thread already had the lock, we must unlock and return
         // false since this is a non-recursive mutex. This is to mimic the
         // behavior of POSIX's pthread_mutex_trylock. We don't do this
@@ -236,12 +236,12 @@
 
     int signalsLeft = m_waitersToUnblock;
 
-    if (m_waitersToUnblock)
+    if (m_waitersToUnblock) {
         --m_waitersToUnblock;
-    else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore
-        // timeout or spurious wakeup occured, normalize the m_waitersGone count
-        // this may occur if many calls to wait with a timeout are made and
-        // no call to notify_* is made
+    } else if (++m_waitersGone == (INT_MAX / 2)) {
+        // timeout/canceled or spurious semaphore timeout or spurious wakeup
+        // occured, normalize the m_waitersGone count this may occur if many
+        // calls to wait with a timeout are made and no call to notify_* is made
         res = WaitForSingleObject(m_blockLock, INFINITE);
         ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
         m_waitersBlocked -= m_waitersGone;
@@ -258,7 +258,7 @@
         ASSERT_UNUSED(res, res);
     }
 
-    EnterCriticalSection (&mutex.m_internalMutex);
+    EnterCriticalSection(&mutex.m_internalMutex);
     ++mutex.m_recursionCount;
 
     return !timedOut;
diff --git a/third_party/WebKit/Source/wtf/TypeTraits.h b/third_party/WebKit/Source/wtf/TypeTraits.h
index aa399a4..7f78db7 100644
--- a/third_party/WebKit/Source/wtf/TypeTraits.h
+++ b/third_party/WebKit/Source/wtf/TypeTraits.h
@@ -26,276 +26,281 @@
 
 namespace WTF {
 
-    // The following are provided in this file:
-    //
-    //   IsInteger<T>::value
-    //   IsPod<T>::value
-    //   IsConvertibleToInteger<T>::value
-    //
-    //   IsArray<T>::value
-    //
-    //   IsSameType<T, U>::value
-    //
-    //   RemovePointer<T>::Type
-    //   RemoveReference<T>::Type
-    //   RemoveConst<T>::Type
-    //   RemoveVolatile<T>::Type
-    //   RemoveConstVolatile<T>::Type
-    //   RemoveExtent<T>::Type
-    //
-    //   static_assert's in TypeTraits.cpp illustrate their usage and what they do.
+// The following are provided in this file:
+//
+//   IsInteger<T>::value
+//   IsPod<T>::value
+//   IsConvertibleToInteger<T>::value
+//
+//   IsArray<T>::value
+//
+//   IsSameType<T, U>::value
+//
+//   RemovePointer<T>::Type
+//   RemoveReference<T>::Type
+//   RemoveConst<T>::Type
+//   RemoveVolatile<T>::Type
+//   RemoveConstVolatile<T>::Type
+//   RemoveExtent<T>::Type
+//
+//   static_assert's in TypeTraits.cpp illustrate their usage and what they do.
 
-    template<bool Predicate, class T = void> struct EnableIf;
-    template<class T> struct EnableIf<true, T> { typedef T Type; };
+template <bool Predicate, class T = void> struct EnableIf;
+template <class T> struct EnableIf<true, T> { typedef T Type; };
 
-    template<typename T> struct IsInteger           { static const bool value = false; };
-    template<> struct IsInteger<bool>               { static const bool value = true; };
-    template<> struct IsInteger<char>               { static const bool value = true; };
-    template<> struct IsInteger<signed char>        { static const bool value = true; };
-    template<> struct IsInteger<unsigned char>      { static const bool value = true; };
-    template<> struct IsInteger<short>              { static const bool value = true; };
-    template<> struct IsInteger<unsigned short>     { static const bool value = true; };
-    template<> struct IsInteger<int>                { static const bool value = true; };
-    template<> struct IsInteger<unsigned int>       { static const bool value = true; };
-    template<> struct IsInteger<long>               { static const bool value = true; };
-    template<> struct IsInteger<unsigned long>      { static const bool value = true; };
-    template<> struct IsInteger<long long>          { static const bool value = true; };
-    template<> struct IsInteger<unsigned long long> { static const bool value = true; };
+template <typename T> struct IsInteger           { static const bool value = false; };
+template <> struct IsInteger<bool>               { static const bool value = true; };
+template <> struct IsInteger<char>               { static const bool value = true; };
+template <> struct IsInteger<signed char>        { static const bool value = true; };
+template <> struct IsInteger<unsigned char>      { static const bool value = true; };
+template <> struct IsInteger<short>              { static const bool value = true; };
+template <> struct IsInteger<unsigned short>     { static const bool value = true; };
+template <> struct IsInteger<int>                { static const bool value = true; };
+template <> struct IsInteger<unsigned>           { static const bool value = true; };
+template <> struct IsInteger<long>               { static const bool value = true; };
+template <> struct IsInteger<unsigned long>      { static const bool value = true; };
+template <> struct IsInteger<long long>          { static const bool value = true; };
+template <> struct IsInteger<unsigned long long> { static const bool value = true; };
 #if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    template<> struct IsInteger<wchar_t>            { static const bool value = true; };
+template <> struct IsInteger<wchar_t>            { static const bool value = true; };
 #endif
 
-    template<typename T> struct IsFloatingPoint     { static const bool value = false; };
-    template<> struct IsFloatingPoint<float>        { static const bool value = true; };
-    template<> struct IsFloatingPoint<double>       { static const bool value = true; };
-    template<> struct IsFloatingPoint<long double>  { static const bool value = true; };
+template <typename T> struct IsFloatingPoint     { static const bool value = false; };
+template <> struct IsFloatingPoint<float>        { static const bool value = true; };
+template <> struct IsFloatingPoint<double>       { static const bool value = true; };
+template <> struct IsFloatingPoint<long double>  { static const bool value = true; };
 
-    template<typename T> struct IsArithmetic        { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
+template <typename T> struct IsArithmetic        { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
 
-    template<typename T> struct IsPointer {
+template <typename T> struct IsPointer {
+    static const bool value = false;
+};
+
+template <typename P> struct IsPointer<const P*> {
+    static const bool value = true;
+};
+
+template <typename P> struct IsPointer<P*> {
+    static const bool value = true;
+};
+
+template <typename T> struct IsEnum {
+    static const bool value = __is_enum(T);
+};
+
+template <typename T> struct IsScalar {
+    static const bool value = IsEnum<T>::value || IsArithmetic<T>::value || IsPointer<T>::value;
+};
+
+template <typename T> struct IsWeak {
+    static const bool value = false;
+};
+
+enum WeakHandlingFlag {
+    NoWeakHandlingInCollections,
+    WeakHandlingInCollections
+};
+
+template <typename T> struct IsPod {
+    static const bool value = __is_pod(T);
+};
+
+template <typename T> struct IsTriviallyCopyAssignable {
+    static const bool value = __has_trivial_assign(T);
+};
+
+template <typename T> struct IsTriviallyMoveAssignable {
+    static const bool value = __has_trivial_assign(T);
+};
+
+template <typename T> struct IsTriviallyDefaultConstructible {
+    static const bool value = __has_trivial_constructor(T);
+};
+
+template <typename T> struct IsTriviallyDestructible {
+    static const bool value = __has_trivial_destructor(T);
+};
+
+template <typename T> class IsConvertibleToInteger {
+    // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
+    // by not converting int's to doubles.
+    template <bool performCheck, typename U> class IsConvertibleToDouble;
+    template <typename U> class IsConvertibleToDouble<false, U> {
+    public:
         static const bool value = false;
     };
 
-    template<typename P> struct IsPointer<const P*> {
-        static const bool value = true;
-    };
-
-    template<typename P> struct IsPointer<P*> {
-        static const bool value = true;
-    };
-
-    template<typename T> struct IsEnum {
-        static const bool value = __is_enum(T);
-    };
-
-    template<typename T> struct IsScalar {
-        static const bool value = IsEnum<T>::value || IsArithmetic<T>::value || IsPointer<T>::value;
-    };
-
-    template<typename T> struct IsWeak              { static const bool value = false; };
-
-    enum WeakHandlingFlag {
-        NoWeakHandlingInCollections,
-        WeakHandlingInCollections
-    };
-
-    template <typename T> struct IsPod {
-        static const bool value = __is_pod(T);
-    };
-
-    template <typename T> struct IsTriviallyCopyAssignable {
-        static const bool value = __has_trivial_assign(T);
-    };
-
-    template <typename T> struct IsTriviallyMoveAssignable {
-        static const bool value = __has_trivial_assign(T);
-    };
-
-    template <typename T> struct IsTriviallyDefaultConstructible {
-        static const bool value = __has_trivial_constructor(T);
-    };
-
-    template <typename T> struct IsTriviallyDestructible {
-        static const bool value = __has_trivial_destructor(T);
-    };
-
-    template<typename T> class IsConvertibleToInteger {
-        // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
-        // by not converting int's to doubles.
-        template<bool performCheck, typename U> class IsConvertibleToDouble;
-        template<typename U> class IsConvertibleToDouble<false, U> {
-        public:
-            static const bool value = false;
-        };
-
-        template<typename U> class IsConvertibleToDouble<true, U> {
-            typedef char YesType;
-            struct NoType {
-                char padding[8];
-            };
-
-            static YesType floatCheck(long double);
-            static NoType floatCheck(...);
-            static T& t;
-        public:
-            static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
-        };
-
-    public:
-        static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
-    };
-
-    template<typename From, typename To> class IsPointerConvertible {
+    template <typename U> class IsConvertibleToDouble<true, U> {
         typedef char YesType;
         struct NoType {
             char padding[8];
         };
 
-        static YesType convertCheck(To* x);
-        static NoType convertCheck(...);
+        static YesType floatCheck(long double);
+        static NoType floatCheck(...);
+        static T& t;
     public:
-        enum {
-            Value = (sizeof(YesType) == sizeof(convertCheck(static_cast<From*>(0))))
-        };
+        static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
     };
 
-    template <class T> struct IsArray {
-        static const bool value = false;
+public:
+    static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
+};
+
+template <typename From, typename To> class IsPointerConvertible {
+    typedef char YesType;
+    struct NoType {
+        char padding[8];
     };
 
-    template <class T> struct IsArray<T[]> {
-        static const bool value = true;
+    static YesType convertCheck(To* x);
+    static NoType convertCheck(...);
+public:
+    enum {
+        Value = (sizeof(YesType) == sizeof(convertCheck(static_cast<From*>(0))))
+    };
+};
+
+template <class T> struct IsArray {
+    static const bool value = false;
+};
+
+template <class T> struct IsArray<T[]> {
+    static const bool value = true;
+};
+
+template <class T, size_t N> struct IsArray<T[N]> {
+    static const bool value = true;
+};
+
+template <typename T, typename U> struct IsSameType {
+    static const bool value = false;
+};
+
+template <typename T> struct IsSameType<T, T> {
+    static const bool value = true;
+};
+
+template <typename T, typename U> class IsSubclass {
+    typedef char YesType;
+    struct NoType {
+        char padding[8];
     };
 
-    template <class T, size_t N> struct IsArray<T[N]> {
-        static const bool value = true;
+    static YesType subclassCheck(U*);
+    static NoType subclassCheck(...);
+    static T* t;
+public:
+    static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+};
+
+template <typename T, template <typename... V> class U> class IsSubclassOfTemplate {
+    typedef char YesType;
+    struct NoType {
+        char padding[8];
     };
 
+    template <typename... W> static YesType subclassCheck(U<W...>*);
+    static NoType subclassCheck(...);
+    static T* t;
+public:
+    static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+};
 
-    template <typename T, typename U> struct IsSameType {
-        static const bool value = false;
+template <typename T, template <typename V, size_t W> class U>
+class IsSubclassOfTemplateTypenameSize {
+    typedef char YesType;
+    struct NoType {
+        char padding[8];
     };
 
-    template <typename T> struct IsSameType<T, T> {
-        static const bool value = true;
+    template <typename X, size_t Y> static YesType subclassCheck(U<X, Y>*);
+    static NoType subclassCheck(...);
+    static T* t;
+public:
+    static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+};
+
+template <typename T, template <typename V, size_t W, typename X> class U>
+class IsSubclassOfTemplateTypenameSizeTypename {
+    typedef char YesType;
+    struct NoType {
+        char padding[8];
     };
 
-    template <typename T, typename U> class IsSubclass {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
+    template <typename Y, size_t Z, typename A> static YesType subclassCheck(U<Y, Z, A>*);
+    static NoType subclassCheck(...);
+    static T* t;
+public:
+    static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
+};
 
-        static YesType subclassCheck(U*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
+template <typename T, template <class V> class OuterTemplate>
+struct RemoveTemplate {
+    typedef T Type;
+};
 
-    template <typename T, template<typename... V> class U> class IsSubclassOfTemplate {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
+template <typename T, template <class V> class OuterTemplate>
+struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
+    typedef T Type;
+};
 
-        template<typename... W> static YesType subclassCheck(U<W...>*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
+template <typename T> struct RemoveConst {
+    typedef T Type;
+};
 
-    template <typename T, template<typename V, size_t W> class U> class IsSubclassOfTemplateTypenameSize {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
+template <typename T> struct RemoveConst<const T> {
+    typedef T Type;
+};
 
-        template<typename X, size_t Y> static YesType subclassCheck(U<X, Y>*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
+template <typename T> struct RemoveVolatile {
+    typedef T Type;
+};
 
-    template <typename T, template<typename V, size_t W, typename X> class U> class IsSubclassOfTemplateTypenameSizeTypename {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
+template <typename T> struct RemoveVolatile<volatile T> {
+    typedef T Type;
+};
 
-        template<typename Y, size_t Z, typename A> static YesType subclassCheck(U<Y, Z, A>*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
+template <typename T> struct RemoveConstVolatile {
+    typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
+};
 
-    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate {
-        typedef T Type;
-    };
+template <typename T> struct RemovePointer {
+    typedef T Type;
+};
 
-    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
-        typedef T Type;
-    };
+template <typename T> struct RemovePointer<T*> {
+    typedef T Type;
+};
 
-    template <typename T> struct RemoveConst {
-        typedef T Type;
-    };
+template <typename T> struct RemoveReference {
+    typedef T Type;
+};
 
-    template <typename T> struct RemoveConst<const T> {
-        typedef T Type;
-    };
+template <typename T> struct RemoveReference<T&> {
+    typedef T Type;
+};
 
-    template <typename T> struct RemoveVolatile {
-        typedef T Type;
-    };
+template <typename T> struct RemoveReference<T&&> {
+    typedef T Type;
+};
 
-    template <typename T> struct RemoveVolatile<volatile T> {
-        typedef T Type;
-    };
+template <typename T> struct RemoveExtent {
+    typedef T Type;
+};
 
-    template <typename T> struct RemoveConstVolatile {
-        typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
-    };
+template <typename T> struct RemoveExtent<T[]> {
+    typedef T Type;
+};
 
-    template <typename T> struct RemovePointer {
-        typedef T Type;
-    };
+template <typename T, size_t N> struct RemoveExtent<T[N]> {
+    typedef T Type;
+};
 
-    template <typename T> struct RemovePointer<T*> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveReference {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveReference<T&> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveReference<T&&> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveExtent {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveExtent<T[]> {
-        typedef T Type;
-    };
-
-    template <typename T, size_t N> struct RemoveExtent<T[N]> {
-        typedef T Type;
-    };
-
-    // Determines whether this type has a vtable.
-    template <typename T> struct IsPolymorphic {
-        static const bool value = __is_polymorphic(T);
-    };
+// Determines whether this type has a vtable.
+template <typename T> struct IsPolymorphic {
+    static const bool value = __is_polymorphic(T);
+};
 
 #define EnsurePtrConvertibleArgDecl(From, To) \
     typename WTF::EnableIf<WTF::IsPointerConvertible<From, To>::Value, bool>::Type = true
@@ -312,7 +317,7 @@
 
 namespace WTF {
 
-template<typename T>
+template <typename T>
 class NeedsTracing {
     typedef char YesType;
     typedef struct NoType {
@@ -320,8 +325,8 @@
     } NoType;
 
     // Note that this also checks if a superclass of V has a trace method.
-    template<typename V> static YesType checkHasTraceMethod(V* v, blink::Visitor* p = 0, typename EnableIf<IsSameType<decltype(v->trace(p)), void>::value>::Type* g = 0);
-    template<typename V> static NoType checkHasTraceMethod(...);
+    template <typename V> static YesType checkHasTraceMethod(V* v, blink::Visitor* p = nullptr, typename EnableIf<IsSameType<decltype(v->trace(p)), void>::value>::Type* g = nullptr);
+    template <typename V> static NoType checkHasTraceMethod(...);
 public:
     // We add sizeof(T) to both sides here, because we want it to fail for
     // incomplete types. Otherwise it just assumes that incomplete types do not
@@ -331,13 +336,13 @@
 
 // Convenience template wrapping the NeedsTracingLazily template in
 // Collection Traits. It helps make the code more readable.
-template<typename Traits>
+template <typename Traits>
 class ShouldBeTraced {
 public:
     static const bool value = Traits::template NeedsTracingLazily<>::value;
 };
 
-template<typename T, typename U>
+template <typename T, typename U>
 struct NeedsTracing<std::pair<T, U>> {
     static const bool value = NeedsTracing<T>::value || NeedsTracing<U>::value || IsWeak<T>::value || IsWeak<U>::value;
 };
diff --git a/third_party/WebKit/Source/wtf/TypedArrayBase.h b/third_party/WebKit/Source/wtf/TypedArrayBase.h
index 43c5ccc..d1dd854 100644
--- a/third_party/WebKit/Source/wtf/TypedArrayBase.h
+++ b/third_party/WebKit/Source/wtf/TypedArrayBase.h
@@ -90,9 +90,7 @@
     }
 
     template <class Subclass>
-    static PassRefPtr<Subclass> create(PassRefPtr<ArrayBuffer> buffer,
-                                       unsigned byteOffset,
-                                       unsigned length)
+    static PassRefPtr<Subclass> create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
     {
         RefPtr<ArrayBuffer> buf(buffer);
         RELEASE_ASSERT(verifySubRange<T>(buf, byteOffset, length));
diff --git a/third_party/WebKit/Source/wtf/Uint16Array.h b/third_party/WebKit/Source/wtf/Uint16Array.h
index 56bb03a..26645fe 100644
--- a/third_party/WebKit/Source/wtf/Uint16Array.h
+++ b/third_party/WebKit/Source/wtf/Uint16Array.h
@@ -48,9 +48,7 @@
     }
 
 private:
-    inline Uint16Array(PassRefPtr<ArrayBuffer>,
-                            unsigned byteOffset,
-                            unsigned length);
+    inline Uint16Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<unsigned short>;
 };
diff --git a/third_party/WebKit/Source/wtf/Uint32Array.h b/third_party/WebKit/Source/wtf/Uint32Array.h
index 6677fa4..cd9aaa6 100644
--- a/third_party/WebKit/Source/wtf/Uint32Array.h
+++ b/third_party/WebKit/Source/wtf/Uint32Array.h
@@ -48,9 +48,7 @@
     }
 
 private:
-    inline Uint32Array(PassRefPtr<ArrayBuffer>,
-                          unsigned byteOffset,
-                          unsigned length);
+    inline Uint32Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<unsigned>;
 };
@@ -60,7 +58,7 @@
     return TypedArrayBase<unsigned>::create<Uint32Array>(length);
 }
 
-PassRefPtr<Uint32Array> Uint32Array::create(const unsigned int* array, unsigned length)
+PassRefPtr<Uint32Array> Uint32Array::create(const unsigned* array, unsigned length)
 {
     return TypedArrayBase<unsigned>::create<Uint32Array>(array, length);
 }
diff --git a/third_party/WebKit/Source/wtf/Uint8Array.h b/third_party/WebKit/Source/wtf/Uint8Array.h
index 9a683f71..1c38cc5a 100644
--- a/third_party/WebKit/Source/wtf/Uint8Array.h
+++ b/third_party/WebKit/Source/wtf/Uint8Array.h
@@ -48,9 +48,7 @@
     }
 
 protected:
-    inline Uint8Array(PassRefPtr<ArrayBuffer>,
-                           unsigned byteOffset,
-                           unsigned length);
+    inline Uint8Array(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<unsigned char>;
 };
diff --git a/third_party/WebKit/Source/wtf/Uint8ClampedArray.h b/third_party/WebKit/Source/wtf/Uint8ClampedArray.h
index 30c6d957..add0e4a 100644
--- a/third_party/WebKit/Source/wtf/Uint8ClampedArray.h
+++ b/third_party/WebKit/Source/wtf/Uint8ClampedArray.h
@@ -48,9 +48,7 @@
     }
 
 private:
-    inline Uint8ClampedArray(PassRefPtr<ArrayBuffer>,
-                             unsigned byteOffset,
-                             unsigned length);
+    inline Uint8ClampedArray(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
     // Make constructor visible to superclass.
     friend class TypedArrayBase<unsigned char>;
 };
diff --git a/third_party/WebKit/Source/wtf/Vector.h b/third_party/WebKit/Source/wtf/Vector.h
index 2503526..aabdef8 100644
--- a/third_party/WebKit/Source/wtf/Vector.h
+++ b/third_party/WebKit/Source/wtf/Vector.h
@@ -53,1291 +53,1294 @@
 static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE;
 #endif
 
-    template<typename T, size_t inlineBuffer, typename Allocator>
-    class Deque;
+template <typename T, size_t inlineBuffer, typename Allocator>
+class Deque;
 
-    template <bool needsDestruction, typename T>
-    struct VectorDestructor;
+template <bool needsDestruction, typename T>
+struct VectorDestructor;
 
-    template<typename T>
-    struct VectorDestructor<false, T>
+template <typename T>
+struct VectorDestructor<false, T> {
+    static void destruct(T*, T*) {}
+};
+
+template <typename T>
+struct VectorDestructor<true, T> {
+    static void destruct(T* begin, T* end)
     {
-        static void destruct(T*, T*) {}
-    };
+        for (T* cur = begin; cur != end; ++cur)
+            cur->~T();
+    }
+};
 
-    template<typename T>
-    struct VectorDestructor<true, T>
-    {
-        static void destruct(T* begin, T* end)
-        {
-            for (T* cur = begin; cur != end; ++cur)
-                cur->~T();
-        }
-    };
+template <bool unusedSlotsMustBeZeroed, typename T>
+struct VectorUnusedSlotClearer;
 
-    template <bool unusedSlotsMustBeZeroed, typename T>
-    struct VectorUnusedSlotClearer;
-
-    template<typename T>
-    struct VectorUnusedSlotClearer<false, T> {
-        static void clear(T*, T*) { }
+template <typename T>
+struct VectorUnusedSlotClearer<false, T> {
+    static void clear(T*, T*) {}
 #if ENABLE(ASSERT)
-        static void checkCleared(const T*, const T*) { }
+    static void checkCleared(const T*, const T*) {}
 #endif
-    };
+};
 
-    template<typename T>
-    struct VectorUnusedSlotClearer<true, T> {
-        static void clear(T* begin, T* end)
-        {
-            memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin));
-        }
+template <typename T>
+struct VectorUnusedSlotClearer<true, T> {
+    static void clear(T* begin, T* end)
+    {
+        memset(reinterpret_cast<void*>(begin), 0, sizeof(T) * (end - begin));
+    }
 
 #if ENABLE(ASSERT)
-        static void checkCleared(const T* begin, const T* end)
-        {
-            const unsigned char* unusedArea = reinterpret_cast<const unsigned char*>(begin);
-            const unsigned char* endAddress = reinterpret_cast<const unsigned char*>(end);
-            ASSERT(endAddress >= unusedArea);
-            for (int i = 0; i < endAddress - unusedArea; ++i)
-                ASSERT(!unusedArea[i]);
-        }
+    static void checkCleared(const T* begin, const T* end)
+    {
+        const unsigned char* unusedArea = reinterpret_cast<const unsigned char*>(begin);
+        const unsigned char* endAddress = reinterpret_cast<const unsigned char*>(end);
+        ASSERT(endAddress >= unusedArea);
+        for (int i = 0; i < endAddress - unusedArea; ++i)
+            ASSERT(!unusedArea[i]);
+    }
 #endif
-    };
+};
 
-    template <bool canInitializeWithMemset, typename T>
-    struct VectorInitializer;
+template <bool canInitializeWithMemset, typename T>
+struct VectorInitializer;
 
-    template<typename T>
-    struct VectorInitializer<false, T>
+template <typename T>
+struct VectorInitializer<false, T> {
+    static void initialize(T* begin, T* end)
     {
-        static void initialize(T* begin, T* end)
-        {
-            for (T* cur = begin; cur != end; ++cur)
-                new (NotNull, cur) T;
+        for (T* cur = begin; cur != end; ++cur)
+            new (NotNull, cur) T;
+    }
+};
+
+template <typename T>
+struct VectorInitializer<true, T> {
+    static void initialize(T* begin, T* end)
+    {
+        memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
+    }
+};
+
+template <bool canMoveWithMemcpy, typename T>
+struct VectorMover;
+
+template <typename T>
+struct VectorMover<false, T> {
+    static void move(const T* src, const T* srcEnd, T* dst)
+    {
+        while (src != srcEnd) {
+            new (NotNull, dst) T(*src);
+            src->~T();
+            ++dst;
+            ++src;
         }
-    };
-
-    template<typename T>
-    struct VectorInitializer<true, T>
+    }
+    static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
     {
-        static void initialize(T* begin, T* end)
-        {
-            memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
-        }
-    };
-
-    template <bool canMoveWithMemcpy, typename T>
-    struct VectorMover;
-
-    template<typename T>
-    struct VectorMover<false, T>
-    {
-        static void move(const T* src, const T* srcEnd, T* dst)
-        {
+        if (src > dst) {
+            move(src, srcEnd, dst);
+        } else {
+            T* dstEnd = dst + (srcEnd - src);
             while (src != srcEnd) {
-                new (NotNull, dst) T(*src);
-                src->~T();
-                ++dst;
-                ++src;
+                --srcEnd;
+                --dstEnd;
+                new (NotNull, dstEnd) T(*srcEnd);
+                srcEnd->~T();
             }
         }
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
-        {
-            if (src > dst)
-                move(src, srcEnd, dst);
-            else {
-                T* dstEnd = dst + (srcEnd - src);
-                while (src != srcEnd) {
-                    --srcEnd;
-                    --dstEnd;
-                    new (NotNull, dstEnd) T(*srcEnd);
-                    srcEnd->~T();
-                }
-            }
-        }
-        static void swap(T* src, T* srcEnd, T* dst)
-        {
-            std::swap_ranges(src, srcEnd, dst);
-        }
-    };
-
-    template<typename T>
-    struct VectorMover<true, T>
+    }
+    static void swap(T* src, T* srcEnd, T* dst) 
     {
-        static void move(const T* src, const T* srcEnd, T* dst)
-        {
-            if (LIKELY(dst && src))
-                memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
-        {
-            if (LIKELY(dst && src))
-                memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-        static void swap(T* src, T* srcEnd, T* dst)
-        {
-            std::swap_ranges(reinterpret_cast<char*>(src), reinterpret_cast<char*>(srcEnd), reinterpret_cast<char*>(dst));
-        }
-    };
+        std::swap_ranges(src, srcEnd, dst);
+    }
+};
 
-    template <bool canCopyWithMemcpy, typename T>
-    struct VectorCopier;
-
-    template<typename T>
-    struct VectorCopier<false, T>
+template <typename T>
+struct VectorMover<true, T> {
+    static void move(const T* src, const T* srcEnd, T* dst)
     {
-        template<typename U>
-        static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
-        {
-            while (src != srcEnd) {
-                new (NotNull, dst) T(*src);
-                ++dst;
-                ++src;
-            }
-        }
-    };
-
-    template<typename T>
-    struct VectorCopier<true, T>
+        if (LIKELY(dst && src))
+            memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
+    }
+    static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
     {
-        static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
-        {
-            if (LIKELY(dst && src))
-                memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-        template<typename U>
-        static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
-        {
-            VectorCopier<false, T>::uninitializedCopy(src, srcEnd, dst);
-        }
-    };
-
-    template <bool canFillWithMemset, typename T>
-    struct VectorFiller;
-
-    template<typename T>
-    struct VectorFiller<false, T>
+        if (LIKELY(dst && src))
+            memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
+    }
+    static void swap(T* src, T* srcEnd, T* dst)
     {
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val)
-        {
-            while (dst != dstEnd) {
-                new (NotNull, dst) T(val);
-                ++dst;
-            }
-        }
-    };
+        std::swap_ranges(reinterpret_cast<char*>(src), reinterpret_cast<char*>(srcEnd), reinterpret_cast<char*>(dst));
+    }
+};
 
-    template<typename T>
-    struct VectorFiller<true, T>
+template <bool canCopyWithMemcpy, typename T>
+struct VectorCopier;
+
+template <typename T>
+struct VectorCopier<false, T> {
+    template <typename U>
+    static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
     {
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val)
-        {
-            static_assert(sizeof(T) == sizeof(char), "size of type should be one");
+        while (src != srcEnd) {
+            new (NotNull, dst) T(*src);
+            ++dst;
+            ++src;
+        }
+    }
+};
+
+template <typename T>
+struct VectorCopier<true, T> {
+    static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
+    {
+        if (LIKELY(dst && src))
+            memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
+    }
+    template <typename U>
+    static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
+    {
+        VectorCopier<false, T>::uninitializedCopy(src, srcEnd, dst);
+    }
+};
+
+template <bool canFillWithMemset, typename T>
+struct VectorFiller;
+
+template <typename T>
+struct VectorFiller<false, T> {
+    static void uninitializedFill(T* dst, T* dstEnd, const T& val)
+    {
+        while (dst != dstEnd) {
+            new (NotNull, dst) T(val);
+            ++dst;
+        }
+    }
+};
+
+template <typename T>
+struct VectorFiller<true, T> {
+    static void uninitializedFill(T* dst, T* dstEnd, const T& val)
+    {
+        static_assert(sizeof(T) == sizeof(char), "size of type should be one");
 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE)
-            if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst)))
+        if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst)))
+            memset(dst, val, dstEnd - dst);
+#else
+        memset(dst, val, dstEnd - dst);
 #endif
-                memset(dst, val, dstEnd - dst);
-        }
-    };
+    }
+};
 
-    template<bool canCompareWithMemcmp, typename T>
-    struct VectorComparer;
+template <bool canCompareWithMemcmp, typename T>
+struct VectorComparer;
 
-    template<typename T>
-    struct VectorComparer<false, T>
+template <typename T>
+struct VectorComparer<false, T> {
+    static bool compare(const T* a, const T* b, size_t size)
     {
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            ASSERT(a);
-            ASSERT(b);
-            return std::equal(a, a + size, b);
-        }
-    };
+        ASSERT(a);
+        ASSERT(b);
+        return std::equal(a, a + size, b);
+    }
+};
 
-    template<typename T>
-    struct VectorComparer<true, T>
+template <typename T>
+struct VectorComparer<true, T> {
+    static bool compare(const T* a, const T* b, size_t size)
     {
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            ASSERT(a);
-            ASSERT(b);
-            return memcmp(a, b, sizeof(T) * size) == 0;
-        }
-    };
+        ASSERT(a);
+        ASSERT(b);
+        return memcmp(a, b, sizeof(T) * size) == 0;
+    }
+};
 
-    template<typename T>
-    struct VectorTypeOperations
+template <typename T>
+struct VectorTypeOperations {
+    static void destruct(T* begin, T* end)
     {
-        static void destruct(T* begin, T* end)
-        {
-            VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
-        }
+        VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
+    }
 
-        static void initialize(T* begin, T* end)
-        {
-            VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
-        }
+    static void initialize(T* begin, T* end)
+    {
+        VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
+    }
 
-        static void move(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
-        }
+    static void move(const T* src, const T* srcEnd, T* dst)
+    {
+        VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
+    }
 
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
-        }
+    static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
+    {
+        VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
+    }
 
-        static void swap(T* src, T* srcEnd, T* dst)
-        {
-            VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::swap(src, srcEnd, dst);
-        }
+    static void swap(T* src, T* srcEnd, T* dst)
+    {
+        VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::swap(src, srcEnd, dst);
+    }
 
-        static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
-        }
+    static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
+    {
+        VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
+    }
+    
+    static void uninitializedFill(T* dst, T* dstEnd, const T& val)
+    {
+        VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
+    }
 
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val)
-        {
-            VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
-        }
+    static bool compare(const T* a, const T* b, size_t size)
+    {
+        return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
+    }
+};
 
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
-        }
-    };
+template <typename T, bool hasInlineCapacity, typename Allocator>
+class VectorBufferBase {
+    WTF_MAKE_NONCOPYABLE(VectorBufferBase);
+public:
+    void allocateBuffer(size_t newCapacity)
+    {
+        ASSERT(newCapacity);
+        size_t sizeToAllocate = allocationSize(newCapacity);
+        if (hasInlineCapacity)
+            m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate);
+        else
+            m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAllocate);
+        m_capacity = sizeToAllocate / sizeof(T);
+    }
 
-    template<typename T, bool hasInlineCapacity, typename Allocator>
-    class VectorBufferBase {
-        WTF_MAKE_NONCOPYABLE(VectorBufferBase);
-    public:
-        void allocateBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity);
-            size_t sizeToAllocate = allocationSize(newCapacity);
-            if (hasInlineCapacity)
-                m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate);
-            else
-                m_buffer = Allocator::template allocateVectorBacking<T>(sizeToAllocate);
-            m_capacity = sizeToAllocate / sizeof(T);
-        }
+    void allocateExpandedBuffer(size_t newCapacity)
+    {
+        ASSERT(newCapacity);
+        size_t sizeToAllocate = allocationSize(newCapacity);
+        if (hasInlineCapacity)
+            m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate);
+        else
+            m_buffer = Allocator::template allocateExpandedVectorBacking<T>(sizeToAllocate);
+        m_capacity = sizeToAllocate / sizeof(T);
+    }
 
-        void allocateExpandedBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity);
-            size_t sizeToAllocate = allocationSize(newCapacity);
-            if (hasInlineCapacity)
-                m_buffer = Allocator::template allocateInlineVectorBacking<T>(sizeToAllocate);
-            else
-                m_buffer = Allocator::template allocateExpandedVectorBacking<T>(sizeToAllocate);
-            m_capacity = sizeToAllocate / sizeof(T);
-        }
+    size_t allocationSize(size_t capacity) const
+    {
+        return Allocator::template quantizedSize<T>(capacity);
+    }
 
-        size_t allocationSize(size_t capacity) const
-        {
-            return Allocator::template quantizedSize<T>(capacity);
-        }
+    T* buffer() { return m_buffer; }
+    const T* buffer() const { return m_buffer; }
+    size_t capacity() const { return m_capacity; }
 
-        T* buffer() { return m_buffer; }
-        const T* buffer() const { return m_buffer; }
-        size_t capacity() const { return m_capacity; }
+    void clearUnusedSlots(T* from, T* to)
+    {
+        // If the vector backing is garbage-collected and needs tracing or
+        // finalizing, we clear out the unused slots so that the visitor or the
+        // finalizer does not cause a problem when visiting the unused slots.
+        VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::clear(from, to);
+    }
 
-        void clearUnusedSlots(T* from, T* to)
-        {
-            // If the vector backing is garbage-collected and needs tracing
-            // or finalizing, we clear out the unused slots so that the visitor
-            // or the finalizer does not cause a problem when visiting the
-            // unused slots.
-            VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::clear(from, to);
-        }
-
-        void checkUnusedSlots(const T* from, const T* to)
-        {
+    void checkUnusedSlots(const T* from, const T* to)
+    {
 #if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER)
-            VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::checkCleared(from, to);
+        VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::checkCleared(from, to);
 #endif
+    }
+
+protected:
+    VectorBufferBase()
+        : m_buffer(nullptr)
+        , m_capacity(0)
+    {
+    }
+
+    VectorBufferBase(T* buffer, size_t capacity)
+        : m_buffer(buffer)
+        , m_capacity(capacity)
+    {
+    }
+
+    T* m_buffer;
+    unsigned m_capacity;
+    unsigned m_size;
+};
+
+template <typename T, size_t inlineCapacity, typename Allocator = DefaultAllocator>
+class VectorBuffer;
+
+template <typename T, typename Allocator>
+class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, false, Allocator> {
+private:
+    typedef VectorBufferBase<T, false, Allocator> Base;
+public:
+    VectorBuffer()
+    {
+    }
+
+    VectorBuffer(size_t capacity)
+    {
+        // Calling malloc(0) might take a lock and may actually do an allocation
+        // on some systems.
+        if (capacity)
+            allocateBuffer(capacity);
+    }
+
+    void destruct()
+    {
+        deallocateBuffer(m_buffer);
+        m_buffer = nullptr;
+    }
+
+    void deallocateBuffer(T* bufferToDeallocate)
+    {
+        Allocator::freeVectorBacking(bufferToDeallocate);
+    }
+
+    bool expandBuffer(size_t newCapacity)
+    {
+        size_t sizeToAllocate = allocationSize(newCapacity);
+        if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) {
+            m_capacity = sizeToAllocate / sizeof(T);
+            return true;
         }
+        return false;
+    }
 
-    protected:
-        VectorBufferBase()
-            : m_buffer(0)
-            , m_capacity(0)
-        {
+    inline bool shrinkBuffer(size_t newCapacity)
+    {
+        ASSERT(newCapacity < capacity());
+        size_t sizeToAllocate = allocationSize(newCapacity);
+        if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()), sizeToAllocate)) {
+            m_capacity = sizeToAllocate / sizeof(T);
+            return true;
         }
+        return false;
+    }
 
-        VectorBufferBase(T* buffer, size_t capacity)
-            : m_buffer(buffer)
-            , m_capacity(capacity)
-        {
+    void resetBufferPointer()
+    {
+        m_buffer = nullptr;
+        m_capacity = 0;
+    }
+
+    void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other)
+    {
+        std::swap(m_buffer, other.m_buffer);
+        std::swap(m_capacity, other.m_capacity);
+    }
+
+    using Base::allocateBuffer;
+    using Base::allocationSize;
+
+    using Base::buffer;
+    using Base::capacity;
+
+    using Base::clearUnusedSlots;
+    using Base::checkUnusedSlots;
+
+    bool hasOutOfLineBuffer() const
+    {
+        // When inlineCapacity is 0 we have an out of line buffer if we have a
+        // buffer.
+        return buffer();
+    }
+
+protected:
+    using Base::m_size;
+
+private:
+    using Base::m_buffer;
+    using Base::m_capacity;
+};
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+class VectorBuffer : protected VectorBufferBase<T, true, Allocator> {
+    WTF_MAKE_NONCOPYABLE(VectorBuffer);
+    typedef VectorBufferBase<T, true, Allocator> Base;
+
+public:
+    VectorBuffer()
+        : Base(inlineBuffer(), inlineCapacity)
+    {
+    }
+
+    VectorBuffer(size_t capacity)
+        : Base(inlineBuffer(), inlineCapacity)
+    {
+        if (capacity > inlineCapacity)
+            Base::allocateBuffer(capacity);
+    }
+
+    void destruct()
+    {
+        deallocateBuffer(m_buffer);
+        m_buffer = nullptr;
+    }
+
+    NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate)
+    {
+        Allocator::freeInlineVectorBacking(bufferToDeallocate);
+    }
+
+    void deallocateBuffer(T* bufferToDeallocate)
+    {
+        if (UNLIKELY(bufferToDeallocate != inlineBuffer()))
+            reallyDeallocateBuffer(bufferToDeallocate);
+    }
+
+    bool expandBuffer(size_t newCapacity)
+    {
+        ASSERT(newCapacity > inlineCapacity);
+        if (m_buffer == inlineBuffer())
+            return false;
+
+        size_t sizeToAllocate = allocationSize(newCapacity);
+        if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) {
+            m_capacity = sizeToAllocate / sizeof(T);
+            return true;
         }
+        return false;
+    }
 
-        T* m_buffer;
-        unsigned m_capacity;
-        unsigned m_size;
-    };
-
-    template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllocator>
-    class VectorBuffer;
-
-    template<typename T, typename Allocator>
-    class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, false, Allocator> {
-    private:
-        typedef VectorBufferBase<T, false, Allocator> Base;
-    public:
-        VectorBuffer()
-        {
-        }
-
-        VectorBuffer(size_t capacity)
-        {
-            // Calling malloc(0) might take a lock and may actually do an
-            // allocation on some systems.
-            if (capacity)
-                allocateBuffer(capacity);
-        }
-
-        void destruct()
-        {
-            deallocateBuffer(m_buffer);
-            m_buffer = 0;
-        }
-
-        void deallocateBuffer(T* bufferToDeallocate)
-        {
-            Allocator::freeVectorBacking(bufferToDeallocate);
-        }
-
-        bool expandBuffer(size_t newCapacity)
-        {
-            size_t sizeToAllocate = allocationSize(newCapacity);
-            if (Allocator::expandVectorBacking(m_buffer, sizeToAllocate)) {
-                m_capacity = sizeToAllocate / sizeof(T);
-                return true;
-            }
+    inline bool shrinkBuffer(size_t newCapacity)
+    {
+        ASSERT(newCapacity < capacity());
+        if (newCapacity <= inlineCapacity) {
+            // We need to switch to inlineBuffer.  Vector::shrinkCapacity will
+            // handle it.
             return false;
         }
-
-        inline bool shrinkBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity < capacity());
-            size_t sizeToAllocate = allocationSize(newCapacity);
-            if (Allocator::shrinkVectorBacking(m_buffer, allocationSize(capacity()), sizeToAllocate)) {
-                m_capacity = sizeToAllocate / sizeof(T);
-                return true;
-            }
+        ASSERT(m_buffer != inlineBuffer());
+        size_t newSize = allocationSize(newCapacity);
+        if (!Allocator::shrinkInlineVectorBacking(m_buffer, allocationSize(capacity()), newSize))
             return false;
-        }
+        m_capacity = newSize / sizeof(T);
+        return true;
+    }
 
-        void resetBufferPointer()
-        {
-            m_buffer = 0;
-            m_capacity = 0;
-        }
+    void resetBufferPointer()
+    {
+        m_buffer = inlineBuffer();
+        m_capacity = inlineCapacity;
+    }
 
-        void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other)
-        {
+    void allocateBuffer(size_t newCapacity)
+    {
+        // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
+        if (newCapacity > inlineCapacity)
+            Base::allocateBuffer(newCapacity);
+        else
+            resetBufferPointer();
+    }
+
+    void allocateExpandedBuffer(size_t newCapacity)
+    {
+        if (newCapacity > inlineCapacity)
+            Base::allocateExpandedBuffer(newCapacity);
+        else
+            resetBufferPointer();
+    }
+
+    size_t allocationSize(size_t capacity) const
+    {
+        if (capacity <= inlineCapacity)
+            return m_inlineBufferSize;
+        return Base::allocationSize(capacity);
+    }
+
+    void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other)
+    {
+        typedef VectorTypeOperations<T> TypeOperations;
+
+        if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
+            ASSERT(m_capacity == other.m_capacity);
+            if (m_size > other.m_size) {
+                ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size);
+                TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_size, other.inlineBuffer());
+                TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer() + m_size, other.inlineBuffer() + other.m_size);
+                Base::clearUnusedSlots(inlineBuffer() + other.m_size, inlineBuffer() + m_size);
+                ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size);
+            } else {
+                ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size);
+                TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
+                TypeOperations::move(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size, inlineBuffer() + m_size);
+                Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size);
+                ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size);
+            }
+        } else if (buffer() == inlineBuffer()) {
+            ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size);
+            m_buffer = other.m_buffer;
+            other.m_buffer = other.inlineBuffer();
+            ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size);
+            TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
+            Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size);
+            std::swap(m_capacity, other.m_capacity);
+        } else if (other.buffer() == other.inlineBuffer()) {
+            ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size);
+            other.m_buffer = m_buffer;
+            m_buffer = inlineBuffer();
+            ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size);
+            TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer());
+            Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer() + other.m_size);
+            std::swap(m_capacity, other.m_capacity);
+        } else {
             std::swap(m_buffer, other.m_buffer);
             std::swap(m_capacity, other.m_capacity);
         }
+    }
 
-        using Base::allocateBuffer;
-        using Base::allocationSize;
+    using Base::buffer;
+    using Base::capacity;
 
-        using Base::buffer;
-        using Base::capacity;
+    bool hasOutOfLineBuffer() const
+    {
+        return buffer() && buffer() != inlineBuffer();
+    }
 
-        using Base::clearUnusedSlots;
-        using Base::checkUnusedSlots;
+protected:
+    using Base::m_size;
 
-        bool hasOutOfLineBuffer() const
-        {
-            // When inlineCapacity is 0 we have an out of line buffer if we have a buffer.
-            return buffer();
-        }
+private:
+    using Base::m_buffer;
+    using Base::m_capacity;
 
-    protected:
-        using Base::m_size;
+    static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
+    T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
+    const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inlineBuffer.buffer); }
 
-    private:
-        using Base::m_buffer;
-        using Base::m_capacity;
-    };
+    AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
+    template <typename U, size_t inlineBuffer, typename V>
+    friend class Deque;
+};
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    class VectorBuffer : protected VectorBufferBase<T, true, Allocator> {
-        WTF_MAKE_NONCOPYABLE(VectorBuffer);
-    private:
-        typedef VectorBufferBase<T, true, Allocator> Base;
-    public:
-        VectorBuffer()
-            : Base(inlineBuffer(), inlineCapacity)
-        {
-        }
+template <typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> // Heap-allocated vectors with no inlineCapacity never need a destructor.
+class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator>, public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> {
+    WTF_USE_ALLOCATOR(Vector, Allocator);
+    typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Base;
+    typedef VectorTypeOperations<T> TypeOperations;
 
-        VectorBuffer(size_t capacity)
-            : Base(inlineBuffer(), inlineCapacity)
-        {
-            if (capacity > inlineCapacity)
-                Base::allocateBuffer(capacity);
-        }
+public:
+    typedef T ValueType;
 
-        void destruct()
-        {
-            deallocateBuffer(m_buffer);
-            m_buffer = 0;
-        }
+    typedef T* iterator;
+    typedef const T* const_iterator;
+    typedef std::reverse_iterator<iterator> reverse_iterator;
+    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
-        NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate)
-        {
-            Allocator::freeInlineVectorBacking(bufferToDeallocate);
-        }
-
-        void deallocateBuffer(T* bufferToDeallocate)
-        {
-            if (UNLIKELY(bufferToDeallocate != inlineBuffer()))
-                reallyDeallocateBuffer(bufferToDeallocate);
-        }
-
-        bool expandBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity > inlineCapacity);
-            if (m_buffer == inlineBuffer())
-                return false;
-
-            size_t sizeToAllocate = allocationSize(newCapacity);
-            if (Allocator::expandInlineVectorBacking(m_buffer, sizeToAllocate)) {
-                m_capacity = sizeToAllocate / sizeof(T);
-                return true;
-            }
-            return false;
-        }
-
-        inline bool shrinkBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity < capacity());
-            if (newCapacity <= inlineCapacity) {
-                // We need to switch to inlineBuffer.  Vector::shrinkCapacity
-                // will handle it.
-                return false;
-            }
-            ASSERT(m_buffer != inlineBuffer());
-            size_t newSize = allocationSize(newCapacity);
-            if (!Allocator::shrinkInlineVectorBacking(m_buffer, allocationSize(capacity()), newSize))
-                return false;
-            m_capacity = newSize / sizeof(T);
-            return true;
-        }
-
-        void resetBufferPointer()
-        {
-            m_buffer = inlineBuffer();
-            m_capacity = inlineCapacity;
-        }
-
-        void allocateBuffer(size_t newCapacity)
-        {
-            // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
-            if (newCapacity > inlineCapacity)
-                Base::allocateBuffer(newCapacity);
-            else
-                resetBufferPointer();
-        }
-
-        void allocateExpandedBuffer(size_t newCapacity)
-        {
-            if (newCapacity > inlineCapacity)
-                Base::allocateExpandedBuffer(newCapacity);
-            else
-                resetBufferPointer();
-        }
-
-        size_t allocationSize(size_t capacity) const
-        {
-            if (capacity <= inlineCapacity)
-                return m_inlineBufferSize;
-            return Base::allocationSize(capacity);
-        }
-
-        void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other)
-        {
-            typedef VectorTypeOperations<T> TypeOperations;
-
-            if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
-                ASSERT(m_capacity == other.m_capacity);
-                if (m_size > other.m_size) {
-                    ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size);
-                    TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_size, other.inlineBuffer());
-                    TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer() + m_size, other.inlineBuffer() + other.m_size);
-                    Base::clearUnusedSlots(inlineBuffer() + other.m_size, inlineBuffer() + m_size);
-                    ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size);
-                } else {
-                    ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size);
-                    TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
-                    TypeOperations::move(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size, inlineBuffer() + m_size);
-                    Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size);
-                    ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size);
-                }
-            } else if (buffer() == inlineBuffer()) {
-                ANNOTATE_DELETE_BUFFER(m_buffer, inlineCapacity, m_size);
-                m_buffer = other.m_buffer;
-                other.m_buffer = other.inlineBuffer();
-                ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size);
-                TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
-                Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size);
-                std::swap(m_capacity, other.m_capacity);
-            } else if (other.buffer() == other.inlineBuffer()) {
-                ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size);
-                other.m_buffer = m_buffer;
-                m_buffer = inlineBuffer();
-                ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size);
-                TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer());
-                Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer() + other.m_size);
-                std::swap(m_capacity, other.m_capacity);
-            } else {
-                std::swap(m_buffer, other.m_buffer);
-                std::swap(m_capacity, other.m_capacity);
-            }
-        }
-
-        using Base::buffer;
-        using Base::capacity;
-
-        bool hasOutOfLineBuffer() const
-        {
-            return buffer() && buffer() != inlineBuffer();
-        }
-
-    protected:
-        using Base::m_size;
-
-    private:
-        using Base::m_buffer;
-        using Base::m_capacity;
-
-        static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
-        T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
-        const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inlineBuffer.buffer); }
-
-        AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
-        template<typename U, size_t inlineBuffer, typename V>
-        friend class Deque;
-    };
-
-    template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> // Heap-allocated vectors with no inlineCapacity never need a destructor.
-    class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator>, public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>, (INLINE_CAPACITY == 0) && Allocator::isGarbageCollected> {
-        WTF_USE_ALLOCATOR(Vector, Allocator);
-    private:
-        typedef VectorBuffer<T, INLINE_CAPACITY, Allocator> Base;
-        typedef VectorTypeOperations<T> TypeOperations;
-
-    public:
-        typedef T ValueType;
-
-        typedef T* iterator;
-        typedef const T* const_iterator;
-        typedef std::reverse_iterator<iterator> reverse_iterator;
-        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
-        Vector()
-        {
-            static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
+    Vector()
+    {
+        static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
 #if ENABLE(OILPAN)
-            static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Vector");
+        static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Vector");
 #endif
-            ANNOTATE_NEW_BUFFER(begin(), capacity(), 0);
-            m_size = 0;
-        }
-
-        explicit Vector(size_t size)
-            : Base(size)
-        {
-            static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
-#if ENABLE(OILPAN)
-            static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Vector");
-#endif
-            ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
-            m_size = size;
-            TypeOperations::initialize(begin(), end());
-        }
-
-        // Off-GC-heap vectors: Destructor should be called.
-        // On-GC-heap vectors: Destructor should be called for inline buffers
-        // (if any) but destructor shouldn't be called for vector backing since
-        // it is managed by the traced GC heap.
-        void finalize()
-        {
-            if (!INLINE_CAPACITY) {
-                if (LIKELY(!Base::buffer()))
-                    return;
-            }
-            ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
-            if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
-                TypeOperations::destruct(begin(), end());
-                m_size = 0; // Partial protection against use-after-free.
-            }
-
-            Base::destruct();
-        }
-
-        void finalizeGarbageCollectedObject()
-        {
-            finalize();
-        }
-
-        Vector(const Vector&);
-        template<size_t otherCapacity>
-        explicit Vector(const Vector<T, otherCapacity, Allocator>&);
-
-        Vector& operator=(const Vector&);
-        template<size_t otherCapacity>
-        Vector& operator=(const Vector<T, otherCapacity, Allocator>&);
-
-        Vector(Vector&&);
-        Vector& operator=(Vector&&);
-
-        size_t size() const { return m_size; }
-        size_t capacity() const { return Base::capacity(); }
-        bool isEmpty() const { return !size(); }
-
-        T& at(size_t i)
-        {
-            RELEASE_ASSERT(i < size());
-            return Base::buffer()[i];
-        }
-        const T& at(size_t i) const
-        {
-            RELEASE_ASSERT(i < size());
-            return Base::buffer()[i];
-        }
-
-        T& operator[](size_t i) { return at(i); }
-        const T& operator[](size_t i) const { return at(i); }
-
-        T* data() { return Base::buffer(); }
-        const T* data() const { return Base::buffer(); }
-
-        iterator begin() { return data(); }
-        iterator end() { return begin() + m_size; }
-        const_iterator begin() const { return data(); }
-        const_iterator end() const { return begin() + m_size; }
-
-        reverse_iterator rbegin() { return reverse_iterator(end()); }
-        reverse_iterator rend() { return reverse_iterator(begin()); }
-        const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
-        const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
-
-        T& first() { return at(0); }
-        const T& first() const { return at(0); }
-        T& last() { return at(size() - 1); }
-        const T& last() const { return at(size() - 1); }
-
-        template<typename U> bool contains(const U&) const;
-        template<typename U> size_t find(const U&) const;
-        template<typename U> size_t reverseFind(const U&) const;
-
-        void shrink(size_t size);
-        void grow(size_t size);
-        void resize(size_t size);
-        void reserveCapacity(size_t newCapacity);
-        void reserveInitialCapacity(size_t initialCapacity);
-        void shrinkToFit() { shrinkCapacity(size()); }
-        void shrinkToReasonableCapacity()
-        {
-            if (size() * 2 < capacity())
-                shrinkCapacity(size() + size() / 4 + 1);
-        }
-
-        void clear() { shrinkCapacity(0); }
-
-        template<typename U> void append(const U*, size_t);
-        template<typename U> void append(const U&);
-        template<typename U> void uncheckedAppend(const U& val);
-        template<typename U, size_t otherCapacity, typename V> void appendVector(const Vector<U, otherCapacity, V>&);
-
-        template<typename U> void insert(size_t position, const U*, size_t);
-        template<typename U> void insert(size_t position, const U&);
-        template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&);
-
-        template<typename U> void prepend(const U*, size_t);
-        template<typename U> void prepend(const U&);
-        template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&);
-
-        void remove(size_t position);
-        void remove(size_t position, size_t length);
-
-        void removeLast()
-        {
-            ASSERT(!isEmpty());
-            shrink(size() - 1);
-        }
-
-        Vector(size_t size, const T& val)
-            : Base(size)
-        {
-            ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
-            m_size = size;
-            TypeOperations::uninitializedFill(begin(), end(), val);
-        }
-
-        void fill(const T&, size_t);
-        void fill(const T& val) { fill(val, size()); }
-
-        template<typename Iterator> void appendRange(Iterator start, Iterator end);
-
-        void swap(Vector& other)
-        {
-            Base::swapVectorBuffer(other);
-            std::swap(m_size, other.m_size);
-        }
-
-        void reverse();
-
-        template<typename VisitorDispatcher> void trace(VisitorDispatcher);
-
-    private:
-        void expandCapacity(size_t newMinCapacity);
-        const T* expandCapacity(size_t newMinCapacity, const T*);
-        template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
-        void shrinkCapacity(size_t newCapacity);
-        template<typename U> void appendSlowCase(const U&);
-
-        using Base::m_size;
-        using Base::buffer;
-        using Base::capacity;
-        using Base::swapVectorBuffer;
-        using Base::allocateBuffer;
-        using Base::allocationSize;
-        using Base::clearUnusedSlots;
-        using Base::checkUnusedSlots;
-    };
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other)
-        : Base(other.capacity())
-    {
-        ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
-        m_size = other.size();
-        TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<size_t otherCapacity>
-    Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other)
-        : Base(other.capacity())
-    {
-        ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
-        m_size = other.size();
-        TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, inlineCapacity, Allocator>& other)
-    {
-        if (UNLIKELY(&other == this))
-            return *this;
-
-        if (size() > other.size())
-            shrink(other.size());
-        else if (other.size() > capacity()) {
-            clear();
-            reserveCapacity(other.size());
-            ASSERT(begin());
-        }
-
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size());
-        std::copy(other.begin(), other.begin() + size(), begin());
-        TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
-        m_size = other.size();
-
-        return *this;
-    }
-
-    inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<size_t otherCapacity>
-    Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, otherCapacity, Allocator>& other)
-    {
-        // If the inline capacities match, we should call the more specific
-        // template.  If the inline capacities don't match, the two objects
-        // shouldn't be allocated the same address.
-        ASSERT(!typelessPointersAreEqual(&other, this));
-
-        if (size() > other.size())
-            shrink(other.size());
-        else if (other.size() > capacity()) {
-            clear();
-            reserveCapacity(other.size());
-            ASSERT(begin());
-        }
-
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size());
-        std::copy(other.begin(), other.begin() + size(), begin());
-        TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
-        m_size = other.size();
-
-        return *this;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Allocator>&& other)
-    {
+        ANNOTATE_NEW_BUFFER(begin(), capacity(), 0);
         m_size = 0;
-        // It's a little weird to implement a move constructor using swap but this way we
-        // don't have to add a move constructor to VectorBuffer.
-        swap(other);
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(Vector<T, inlineCapacity, Allocator>&& other)
+    explicit Vector(size_t size)
+        : Base(size)
     {
-        swap(other);
+        static_assert(!IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, "Cannot initialize with memset if there is a vtable");
+#if ENABLE(OILPAN)
+        static_assert(Allocator::isGarbageCollected || !IsAllowOnlyInlineAllocation<T>::value || !NeedsTracing<T>::value, "Cannot put ALLOW_ONLY_INLINE_ALLOCATION objects that have trace methods into an off-heap Vector");
+#endif
+        ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
+        m_size = size;
+        TypeOperations::initialize(begin(), end());
+    }
+
+    // Off-GC-heap vectors: Destructor should be called.
+    // On-GC-heap vectors: Destructor should be called for inline buffers (if
+    // any) but destructor shouldn't be called for vector backing since it is
+    // managed by the traced GC heap.
+    void finalize()
+    {
+        if (!INLINE_CAPACITY) {
+            if (LIKELY(!Base::buffer()))
+                return;
+        }
+        ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
+        if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
+            TypeOperations::destruct(begin(), end());
+            m_size = 0; // Partial protection against use-after-free.
+        }
+
+        Base::destruct();
+    }
+
+    void finalizeGarbageCollectedObject()
+    {
+        finalize();
+    }
+
+    Vector(const Vector&);
+    template <size_t otherCapacity>
+    explicit Vector(const Vector<T, otherCapacity, Allocator>&);
+
+    Vector& operator=(const Vector&);
+    template <size_t otherCapacity>
+    Vector& operator=(const Vector<T, otherCapacity, Allocator>&);
+
+    Vector(Vector&&);
+    Vector& operator=(Vector&&);
+
+    size_t size() const { return m_size; }
+    size_t capacity() const { return Base::capacity(); }
+    bool isEmpty() const { return !size(); }
+
+    T& at(size_t i)
+    {
+        RELEASE_ASSERT(i < size());
+        return Base::buffer()[i];
+    }
+    const T& at(size_t i) const
+    {
+        RELEASE_ASSERT(i < size());
+        return Base::buffer()[i];
+    }
+
+    T& operator[](size_t i) { return at(i); }
+    const T& operator[](size_t i) const { return at(i); }
+
+    T* data() { return Base::buffer(); }
+    const T* data() const { return Base::buffer(); }
+
+    iterator begin() { return data(); }
+    iterator end() { return begin() + m_size; }
+    const_iterator begin() const { return data(); }
+    const_iterator end() const { return begin() + m_size; }
+
+    reverse_iterator rbegin() { return reverse_iterator(end()); }
+    reverse_iterator rend() { return reverse_iterator(begin()); }
+    const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+    const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+
+    T& first() { return at(0); }
+    const T& first() const { return at(0); }
+    T& last() { return at(size() - 1); }
+    const T& last() const { return at(size() - 1); }
+
+    template <typename U> bool contains(const U&) const;
+    template <typename U> size_t find(const U&) const;
+    template <typename U> size_t reverseFind(const U&) const;
+
+    void shrink(size_t);
+    void grow(size_t);
+    void resize(size_t);
+    void reserveCapacity(size_t newCapacity);
+    void reserveInitialCapacity(size_t initialCapacity);
+    void shrinkToFit() { shrinkCapacity(size()); }
+    void shrinkToReasonableCapacity()
+    {
+        if (size() * 2 < capacity())
+            shrinkCapacity(size() + size() / 4 + 1);
+    }
+
+    void clear() { shrinkCapacity(0); }
+
+    template <typename U> void append(const U*, size_t);
+    template <typename U> void append(const U&);
+    template <typename U> void uncheckedAppend(const U& val);
+    template <typename U, size_t otherCapacity, typename V> void appendVector(const Vector<U, otherCapacity, V>&);
+
+    template <typename U> void insert(size_t position, const U*, size_t);
+    template <typename U> void insert(size_t position, const U&);
+    template <typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&);
+
+    template <typename U> void prepend(const U*, size_t);
+    template <typename U> void prepend(const U&);
+    template <typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&);
+
+    void remove(size_t position);
+    void remove(size_t position, size_t length);
+
+    void removeLast()
+    {
+        ASSERT(!isEmpty());
+        shrink(size() - 1);
+    }
+
+    Vector(size_t size, const T& val)
+        : Base(size)
+    {
+        ANNOTATE_NEW_BUFFER(begin(), capacity(), size);
+        m_size = size;
+        TypeOperations::uninitializedFill(begin(), end(), val);
+    }
+
+    void fill(const T&, size_t);
+    void fill(const T& val) { fill(val, size()); }
+
+    template <typename Iterator> void appendRange(Iterator start, Iterator end);
+
+    void swap(Vector& other)
+    {
+        Base::swapVectorBuffer(other);
+        std::swap(m_size, other.m_size);
+    }
+
+    void reverse();
+
+    template <typename VisitorDispatcher> void trace(VisitorDispatcher);
+
+private:
+    void expandCapacity(size_t newMinCapacity);
+    const T* expandCapacity(size_t newMinCapacity, const T*);
+    template <typename U> U* expandCapacity(size_t newMinCapacity, U*);
+    void shrinkCapacity(size_t newCapacity);
+    template <typename U> void appendSlowCase(const U&);
+
+    using Base::m_size;
+    using Base::buffer;
+    using Base::capacity;
+    using Base::swapVectorBuffer;
+    using Base::allocateBuffer;
+    using Base::allocationSize;
+    using Base::clearUnusedSlots;
+    using Base::checkUnusedSlots;
+};
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other)
+    : Base(other.capacity())
+{
+    ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
+    m_size = other.size();
+    TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <size_t otherCapacity>
+Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other)
+    : Base(other.capacity())
+{
+    ANNOTATE_NEW_BUFFER(begin(), capacity(), other.size());
+    m_size = other.size();
+    TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, inlineCapacity, Allocator>& other)
+{
+    if (UNLIKELY(&other == this))
         return *this;
+
+    if (size() > other.size()) {
+        shrink(other.size());
+    } else if (other.size() > capacity()) {
+        clear();
+        reserveCapacity(other.size());
+        ASSERT(begin());
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename U>
-    bool Vector<T, inlineCapacity, Allocator>::contains(const U& value) const
-    {
-        return find(value) != kNotFound;
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size());
+    std::copy(other.begin(), other.begin() + size(), begin());
+    TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
+    m_size = other.size();
+
+    return *this;
+}
+
+inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <size_t otherCapacity>
+Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, otherCapacity, Allocator>& other)
+{
+    // If the inline capacities match, we should call the more specific
+    // template.  If the inline capacities don't match, the two objects
+    // shouldn't be allocated the same address.
+    ASSERT(!typelessPointersAreEqual(&other, this));
+
+    if (size() > other.size()) {
+        shrink(other.size());
+    } else if (other.size() > capacity()) {
+        clear();
+        reserveCapacity(other.size());
+        ASSERT(begin());
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename U>
-    size_t Vector<T, inlineCapacity, Allocator>::find(const U& value) const
-    {
-        const T* b = begin();
-        const T* e = end();
-        for (const T* iter = b; iter < e; ++iter) {
-            if (*iter == value)
-                return iter - b;
-        }
-        return kNotFound;
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, other.size());
+    std::copy(other.begin(), other.begin() + size(), begin());
+    TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
+    m_size = other.size();
+
+    return *this;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Allocator>&& other)
+{
+    m_size = 0;
+    // It's a little weird to implement a move constructor using swap but this
+    // way we don't have to add a move constructor to VectorBuffer.
+    swap(other);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(Vector<T, inlineCapacity, Allocator>&& other)
+{
+    swap(other);
+    return *this;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+bool Vector<T, inlineCapacity, Allocator>::contains(const U& value) const
+{
+    return find(value) != kNotFound;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+size_t Vector<T, inlineCapacity, Allocator>::find(const U& value) const
+{
+    const T* b = begin();
+    const T* e = end();
+    for (const T* iter = b; iter < e; ++iter) {
+        if (*iter == value)
+            return iter - b;
+    }
+    return kNotFound;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+size_t Vector<T, inlineCapacity, Allocator>::reverseFind(const U& value) const
+{
+    const T* b = begin();
+    const T* iter = end();
+    while (iter > b) {
+        --iter;
+        if (*iter == value)
+            return iter - b;
+    }
+    return kNotFound;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize)
+{
+    if (size() > newSize) {
+        shrink(newSize);
+    } else if (newSize > capacity()) {
+        clear();
+        reserveCapacity(newSize);
+        ASSERT(begin());
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename U>
-    size_t Vector<T, inlineCapacity, Allocator>::reverseFind(const U& value) const
-    {
-        const T* b = begin();
-        const T* iter = end();
-        while (iter > b) {
-            --iter;
-            if (*iter == value)
-                return iter - b;
-        }
-        return kNotFound;
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
+    std::fill(begin(), end(), val);
+    TypeOperations::uninitializedFill(end(), begin() + newSize, val);
+    m_size = newSize;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename Iterator>
+void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Iterator end)
+{
+    for (Iterator it = start; it != end; ++it)
+        append(*it);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity)
+{
+    size_t oldCapacity = capacity();
+    size_t expandedCapacity = oldCapacity;
+    // We use a more aggressive expansion strategy for Vectors with inline
+    // storage.  This is because they are more likely to be on the stack, so the
+    // risk of heap bloat is minimized.  Furthermore, exceeding the inline
+    // capacity limit is not supposed to happen in the common case and may
+    // indicate a pathological condition or microbenchmark.
+    if (INLINE_CAPACITY) {
+        expandedCapacity *= 2;
+        // Check for integer overflow, which could happen in the 32-bit build.
+        RELEASE_ASSERT(expandedCapacity > oldCapacity);
+    } else {
+        // This cannot integer overflow.
+        // On 64-bit, the "expanded" integer is 32-bit, and any encroachment
+        // above 2^32 will fail allocation in allocateBuffer().  On 32-bit,
+        // there's not enough address space to hold the old and new buffers.  In
+        // addition, our underlying allocator is supposed to always fail on >
+        // (2^31 - 1) allocations.
+        expandedCapacity += (expandedCapacity / 4) + 1;
     }
+    reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(kInitialVectorSize), expandedCapacity)));
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize)
-    {
-        if (size() > newSize)
-            shrink(newSize);
-        else if (newSize > capacity()) {
-            clear();
-            reserveCapacity(newSize);
-            ASSERT(begin());
-        }
-
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
-        std::fill(begin(), end(), val);
-        TypeOperations::uninitializedFill(end(), begin() + newSize, val);
-        m_size = newSize;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename Iterator>
-    void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Iterator end)
-    {
-        for (Iterator it = start; it != end; ++it)
-            append(*it);
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity)
-    {
-        size_t oldCapacity = capacity();
-        size_t expandedCapacity = oldCapacity;
-        // We use a more aggressive expansion strategy for Vectors with inline storage.
-        // This is because they are more likely to be on the stack, so the risk of heap bloat is minimized.
-        // Furthermore, exceeding the inline capacity limit is not supposed to happen in the common case and may indicate a pathological condition or microbenchmark.
-        if (INLINE_CAPACITY) {
-            expandedCapacity *= 2;
-            // Check for integer overflow, which could happen in the 32-bit build.
-            RELEASE_ASSERT(expandedCapacity > oldCapacity);
-        } else {
-            // This cannot integer overflow.
-            // On 64-bit, the "expanded" integer is 32-bit, and any encroachment above 2^32 will fail allocation in allocateBuffer().
-            // On 32-bit, there's not enough address space to hold the old and new buffers.
-            // In addition, our underlying allocator is supposed to always fail on > (2^31 - 1) allocations.
-            expandedCapacity += (expandedCapacity / 4) + 1;
-        }
-        reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(kInitialVectorSize), expandedCapacity)));
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, const T* ptr)
-    {
-        if (ptr < begin() || ptr >= end()) {
-            expandCapacity(newMinCapacity);
-            return ptr;
-        }
-        size_t index = ptr - begin();
-        expandCapacity(newMinCapacity);
-        return begin() + index;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, U* ptr)
-    {
+template <typename T, size_t inlineCapacity, typename Allocator>
+const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, const T* ptr)
+{
+    if (ptr < begin() || ptr >= end()) {
         expandCapacity(newMinCapacity);
         return ptr;
     }
+    size_t index = ptr - begin();
+    expandCapacity(newMinCapacity);
+    return begin() + index;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size)
-    {
-        if (size <= m_size) {
-            TypeOperations::destruct(begin() + size, end());
-            clearUnusedSlots(begin() + size, end());
-            ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
-        } else {
-            if (size > capacity())
-                expandCapacity(size);
-            ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
-            TypeOperations::initialize(end(), begin() + size);
-        }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, U* ptr)
+{
+    expandCapacity(newMinCapacity);
+    return ptr;
+}
 
-        m_size = size;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::shrink(size_t size)
-    {
-        ASSERT(size <= m_size);
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size)
+{
+    if (size <= m_size) {
         TypeOperations::destruct(begin() + size, end());
         clearUnusedSlots(begin() + size, end());
         ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
-        m_size = size;
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::grow(size_t size)
-    {
-        ASSERT(size >= m_size);
+    } else {
         if (size > capacity())
             expandCapacity(size);
         ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
         TypeOperations::initialize(end(), begin() + size);
-        m_size = size;
     }
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity)
-    {
-        if (UNLIKELY(newCapacity <= capacity()))
-            return;
-        T* oldBuffer = begin();
-        if (!oldBuffer) {
-            Base::allocateBuffer(newCapacity);
-            return;
-        }
+    m_size = size;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::shrink(size_t size)
+{
+    ASSERT(size <= m_size);
+    TypeOperations::destruct(begin() + size, end());
+    clearUnusedSlots(begin() + size, end());
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
+    m_size = size;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::grow(size_t size)
+{
+    ASSERT(size >= m_size);
+    if (size > capacity())
+        expandCapacity(size);
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size);
+    TypeOperations::initialize(end(), begin() + size);
+    m_size = size;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity)
+{
+    if (UNLIKELY(newCapacity <= capacity()))
+        return;
+    T* oldBuffer = begin();
+    if (!oldBuffer) {
+        Base::allocateBuffer(newCapacity);
+        return;
+    }
 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
-        size_t oldCapacity = capacity();
+    size_t oldCapacity = capacity();
 #endif
-        // The Allocator::isGarbageCollected check is not needed.
-        // The check is just a static hint for a compiler to indicate that
-        // Base::expandBuffer returns false if Allocator is a DefaultAllocator.
-        if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) {
+    // The Allocator::isGarbageCollected check is not needed.  The check is just
+    // a static hint for a compiler to indicate that Base::expandBuffer returns
+    // false if Allocator is a DefaultAllocator.
+    if (Allocator::isGarbageCollected && Base::expandBuffer(newCapacity)) {
+        ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity());
+        return;
+    }
+    T* oldEnd = end();
+    Base::allocateExpandedBuffer(newCapacity);
+    ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
+    TypeOperations::move(oldBuffer, oldEnd, begin());
+    clearUnusedSlots(oldBuffer, oldEnd);
+    ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
+    Base::deallocateBuffer(oldBuffer);
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(size_t initialCapacity)
+{
+    ASSERT(!m_size);
+    ASSERT(capacity() == INLINE_CAPACITY);
+    if (initialCapacity > INLINE_CAPACITY) {
+        ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
+        Base::allocateBuffer(initialCapacity);
+        ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
+    }
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity)
+{
+    if (newCapacity >= capacity())
+        return;
+
+    if (newCapacity < size())
+        shrink(newCapacity);
+
+    T* oldBuffer = begin();
+#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
+    size_t oldCapacity = capacity();
+#endif
+    if (newCapacity > 0) {
+        if (Base::shrinkBuffer(newCapacity)) {
             ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity());
             return;
         }
+
         T* oldEnd = end();
-        Base::allocateExpandedBuffer(newCapacity);
-        ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
-        TypeOperations::move(oldBuffer, oldEnd, begin());
-        clearUnusedSlots(oldBuffer, oldEnd);
-        ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
-        Base::deallocateBuffer(oldBuffer);
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(size_t initialCapacity)
-    {
-        ASSERT(!m_size);
-        ASSERT(capacity() == INLINE_CAPACITY);
-        if (initialCapacity > INLINE_CAPACITY) {
-            ANNOTATE_DELETE_BUFFER(begin(), capacity(), m_size);
-            Base::allocateBuffer(initialCapacity);
+        Base::allocateBuffer(newCapacity);
+        if (begin() != oldBuffer) {
             ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
+            TypeOperations::move(oldBuffer, oldEnd, begin());
+            clearUnusedSlots(oldBuffer, oldEnd);
+            ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
         }
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity)
-    {
-        if (newCapacity >= capacity())
-            return;
-
-        if (newCapacity < size())
-            shrink(newCapacity);
-
-        T* oldBuffer = begin();
+    } else {
+        Base::resetBufferPointer();
 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
-        size_t oldCapacity = capacity();
+        if (oldBuffer != begin()) {
+            ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
+            ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
+        }
 #endif
-        if (newCapacity > 0) {
-            if (Base::shrinkBuffer(newCapacity)) {
-                ANNOTATE_CHANGE_CAPACITY(begin(), oldCapacity, m_size, capacity());
-                return;
-            }
-
-            T* oldEnd = end();
-            Base::allocateBuffer(newCapacity);
-            if (begin() != oldBuffer) {
-                ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
-                TypeOperations::move(oldBuffer, oldEnd, begin());
-                clearUnusedSlots(oldBuffer, oldEnd);
-                ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
-            }
-        } else {
-            Base::resetBufferPointer();
-#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
-            if (oldBuffer != begin()) {
-                ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size);
-                ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size);
-            }
-#endif
-        }
-
-        Base::deallocateBuffer(oldBuffer);
     }
 
-    // Templatizing these is better than just letting the conversion happen implicitly,
-    // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
-    // without refcount thrash.
+    Base::deallocateBuffer(oldBuffer);
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t dataSize)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        size_t newSize = m_size + dataSize;
-        if (newSize > capacity()) {
-            data = expandCapacity(newSize, data);
-            ASSERT(begin());
-        }
-        RELEASE_ASSERT(newSize >= m_size);
-        T* dest = end();
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
-        VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], dest);
-        m_size = newSize;
-    }
+// Templatizing these is better than just letting the conversion happen
+// implicitly, because for instance it allows a PassRefPtr to be appended to a
+// RefPtr vector without refcount thrash.
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        if (LIKELY(size() != capacity())) {
-            ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-            new (NotNull, end()) T(val);
-            ++m_size;
-            return;
-        }
-
-        appendSlowCase(val);
-    }
-
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val)
-    {
-        ASSERT(size() == capacity());
-
-        const U* ptr = &val;
-        ptr = expandCapacity(size() + 1, ptr);
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t dataSize)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    size_t newSize = m_size + dataSize;
+    if (newSize > capacity()) {
+        data = expandCapacity(newSize, data);
         ASSERT(begin());
+    }
+    RELEASE_ASSERT(newSize >= m_size);
+    T* dest = end();
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
+    VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], dest);
+    m_size = newSize;
+}
 
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    if (LIKELY(size() != capacity())) {
         ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-        new (NotNull, end()) T(*ptr);
+        new (NotNull, end()) T(val);
         ++m_size;
+        return;
     }
 
-    // This version of append saves a branch in the case where you know that the
-    // vector's capacity is large enough for the append to succeed.
+    appendSlowCase(val);
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U& val)
-    {
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val)
+{
+    ASSERT(size() == capacity());
+
+    const U* ptr = &val;
+    ptr = expandCapacity(size() + 1, ptr);
+    ASSERT(begin());
+
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
+    new (NotNull, end()) T(*ptr);
+    ++m_size;
+}
+
+// This version of append saves a branch in the case where you know that the
+// vector's capacity is large enough for the append to succeed.
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U& val)
+{
 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER
-        // Vectors in ASAN builds don't have inlineCapacity.
-        append(val);
+    // Vectors in ASAN builds don't have inlineCapacity.
+    append(val);
 #else
-        ASSERT(size() < capacity());
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-        const U* ptr = &val;
-        new (NotNull, end()) T(*ptr);
-        ++m_size;
+    ASSERT(size() < capacity());
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
+    const U* ptr = &val;
+    new (NotNull, end()) T(*ptr);
+    ++m_size;
 #endif
-    }
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t otherCapacity, typename OtherAllocator>
-    inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector<U, otherCapacity, OtherAllocator>& val)
-    {
-        append(val.begin(), val.size());
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U, size_t otherCapacity, typename OtherAllocator>
+inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector<U, otherCapacity, OtherAllocator>& val)
+{
+    append(val.begin(), val.size());
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        RELEASE_ASSERT(position <= size());
-        size_t newSize = m_size + dataSize;
-        if (newSize > capacity()) {
-            data = expandCapacity(newSize, data);
-            ASSERT(begin());
-        }
-        RELEASE_ASSERT(newSize >= m_size);
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
-        T* spot = begin() + position;
-        TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
-        VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], spot);
-        m_size = newSize;
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    RELEASE_ASSERT(position <= size());
+    size_t newSize = m_size + dataSize;
+    if (newSize > capacity()) {
+        data = expandCapacity(newSize, data);
+        ASSERT(begin());
     }
+    RELEASE_ASSERT(newSize >= m_size);
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, newSize);
+    T* spot = begin() + position;
+    TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
+    VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], spot);
+    m_size = newSize;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U& val)
-    {
-        ASSERT(Allocator::isAllocationAllowed());
-        RELEASE_ASSERT(position <= size());
-        const U* data = &val;
-        if (size() == capacity()) {
-            data = expandCapacity(size() + 1, data);
-            ASSERT(begin());
-        }
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
-        T* spot = begin() + position;
-        TypeOperations::moveOverlapping(spot, end(), spot + 1);
-        new (NotNull, spot) T(*data);
-        ++m_size;
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U& val)
+{
+    ASSERT(Allocator::isAllocationAllowed());
+    RELEASE_ASSERT(position <= size());
+    const U* data = &val;
+    if (size() == capacity()) {
+        data = expandCapacity(size() + 1, data);
+        ASSERT(begin());
     }
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size + 1);
+    T* spot = begin() + position;
+    TypeOperations::moveOverlapping(spot, end(), spot + 1);
+    new (NotNull, spot) T(*data);
+    ++m_size;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t c, typename OtherAllocator>
-    inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const Vector<U, c, OtherAllocator>& val)
-    {
-        insert(position, val.begin(), val.size());
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U, size_t c, typename OtherAllocator>
+inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const Vector<U, c, OtherAllocator>& val)
+{
+    insert(position, val.begin(), val.size());
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dataSize)
-    {
-        insert(0, data, dataSize);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dataSize)
+{
+    insert(0, data, dataSize);
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
-    inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val)
-    {
-        insert(0, val);
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U>
+inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val)
+{
+    insert(0, val);
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t c, typename V>
-    inline void Vector<T, inlineCapacity, Allocator>::prepend(const Vector<U, c, V>& val)
-    {
-        insert(0, val.begin(), val.size());
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename U, size_t c, typename V>
+inline void Vector<T, inlineCapacity, Allocator>::prepend(const Vector<U, c, V>& val)
+{
+    insert(0, val.begin(), val.size());
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position)
-    {
-        RELEASE_ASSERT(position < size());
-        T* spot = begin() + position;
-        spot->~T();
-        TypeOperations::moveOverlapping(spot + 1, end(), spot);
-        clearUnusedSlots(end() - 1, end());
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - 1);
-        --m_size;
-    }
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position)
+{
+    RELEASE_ASSERT(position < size());
+    T* spot = begin() + position;
+    spot->~T();
+    TypeOperations::moveOverlapping(spot + 1, end(), spot);
+    clearUnusedSlots(end() - 1, end());
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - 1);
+    --m_size;
+}
 
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, size_t length)
-    {
-        ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
-        if (!length)
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, size_t length)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
+    if (!length)
+        return;
+    RELEASE_ASSERT(position + length <= size());
+    T* beginSpot = begin() + position;
+    T* endSpot = beginSpot + length;
+    TypeOperations::destruct(beginSpot, endSpot);
+    TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
+    clearUnusedSlots(end() - length, end());
+    ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - length);
+    m_size -= length;
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void Vector<T, inlineCapacity, Allocator>::reverse()
+{
+    for (size_t i = 0; i < m_size / 2; ++i)
+        std::swap(at(i), at(m_size - 1 - i));
+}
+
+template <typename T, size_t inlineCapacity, typename Allocator>
+inline void swap(Vector<T, inlineCapacity, Allocator>& a, Vector<T, inlineCapacity, Allocator>& b)
+{
+    a.swap(b);
+}
+
+template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
+bool operator==(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
+{
+    if (a.size() != b.size())
+        return false;
+    if (a.isEmpty())
+        return true;
+    return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
+}
+
+template <typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
+inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
+{
+    return !(a == b);
+}
+
+// This is only called if the allocator is a HeapAllocator. It is used when
+// visiting during a tracing GC.
+template <typename T, size_t inlineCapacity, typename Allocator>
+template <typename VisitorDispatcher>
+void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor)
+{
+    ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled.
+    if (!buffer())
+        return;
+    if (this->hasOutOfLineBuffer()) {
+        // This is a performance optimization for a case where the buffer has
+        // been already traced by somewhere. This can happen if the conservative
+        // scanning traced an on-stack (false-positive or real) pointer to the
+        // HeapVector, and then visitor->trace() traces the HeapVector.
+        if (Allocator::isHeapObjectAlive(buffer()))
             return;
-        RELEASE_ASSERT(position + length <= size());
-        T* beginSpot = begin() + position;
-        T* endSpot = beginSpot + length;
-        TypeOperations::destruct(beginSpot, endSpot);
-        TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
-        clearUnusedSlots(end() - length, end());
-        ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, m_size - length);
-        m_size -= length;
+        Allocator::markNoTracing(visitor, buffer());
     }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void Vector<T, inlineCapacity, Allocator>::reverse()
-    {
-        for (size_t i = 0; i < m_size / 2; ++i)
-            std::swap(at(i), at(m_size - 1 - i));
+    const T* bufferBegin = buffer();
+    const T* bufferEnd = buffer() + size();
+    if (ShouldBeTraced<VectorTraits<T>>::value) {
+        for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; bufferEntry++)
+            Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
+        checkUnusedSlots(buffer() + size(), buffer() + capacity());
     }
-
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    inline void swap(Vector<T, inlineCapacity, Allocator>& a, Vector<T, inlineCapacity, Allocator>& b)
-    {
-        a.swap(b);
-    }
-
-    template<typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
-    bool operator==(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
-    {
-        if (a.size() != b.size())
-            return false;
-        if (a.isEmpty())
-            return true;
-        return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
-    }
-
-    template<typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
-    inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
-    {
-        return !(a == b);
-    }
-
-    // This is only called if the allocator is a HeapAllocator. It is used when
-    // visiting during a tracing GC.
-    template<typename T, size_t inlineCapacity, typename Allocator>
-    template<typename VisitorDispatcher>
-    void Vector<T, inlineCapacity, Allocator>::trace(VisitorDispatcher visitor)
-    {
-        ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled.
-        if (!buffer())
-            return;
-        if (this->hasOutOfLineBuffer()) {
-            // This is a performance optimization for a case where the buffer
-            // has been already traced by somewhere. This can happen if
-            // the conservative scanning traced an on-stack (false-positive
-            // or real) pointer to the HeapVector, and then visitor->trace()
-            // traces the HeapVector.
-            if (Allocator::isHeapObjectAlive(buffer()))
-                return;
-            Allocator::markNoTracing(visitor, buffer());
-        }
-        const T* bufferBegin = buffer();
-        const T* bufferEnd = buffer() + size();
-        if (ShouldBeTraced<VectorTraits<T>>::value) {
-            for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; bufferEntry++)
-                Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry));
-            checkUnusedSlots(buffer() + size(), buffer() + capacity());
-        }
-    }
+}
 
 #if !ENABLE(OILPAN)
-    template<typename T, size_t N>
-    struct NeedsTracing<Vector<T, N>> {
-        static const bool value = false;
-    };
+template <typename T, size_t N>
+struct NeedsTracing<Vector<T, N>> {
+    static const bool value = false;
+};
 #endif
 
 } // namespace WTF
diff --git a/third_party/WebKit/Source/wtf/VectorTraits.h b/third_party/WebKit/Source/wtf/VectorTraits.h
index b5fe883..0ced420 100644
--- a/third_party/WebKit/Source/wtf/VectorTraits.h
+++ b/third_party/WebKit/Source/wtf/VectorTraits.h
@@ -26,131 +26,124 @@
 #include "wtf/TypeTraits.h"
 #include <utility>
 
-using std::pair;
-
 namespace WTF {
 
-    class AtomicString;
+class AtomicString;
 
-    template<typename T>
-    struct VectorTraitsBase
-    {
-        static const bool needsDestruction = !IsTriviallyDestructible<T>::value;
+template <typename T>
+struct VectorTraitsBase {
+    static const bool needsDestruction = !IsTriviallyDestructible<T>::value;
 
-        static const bool canInitializeWithMemset = IsTriviallyDefaultConstructible<T>::value;
-        // true iff memset(slot, 0, size) constructs an unused slot value that is valid for
-        // Oilpan to trace and if the value needs destruction, its destructor can be invoked
-        // over. The zero'ed value representing an unused slot in the vector's backing storage;
-        // it does not have to be equal to what its constructor(s) would create, only be
-        // valid for those two uses.
-        static const bool canClearUnusedSlotsWithMemset = IsTriviallyDefaultConstructible<T>::value;
+    static const bool canInitializeWithMemset = IsTriviallyDefaultConstructible<T>::value;
+    // true iff memset(slot, 0, size) constructs an unused slot value that is
+    // valid for Oilpan to trace and if the value needs destruction, its
+    // destructor can be invoked over. The zero'ed value representing an unused
+    // slot in the vector's backing storage; it does not have to be equal to
+    // what its constructor(s) would create, only be valid for those two uses.
+    static const bool canClearUnusedSlotsWithMemset = IsTriviallyDefaultConstructible<T>::value;
 
-        static const bool canMoveWithMemcpy = IsTriviallyMoveAssignable<T>::value;
-        static const bool canCopyWithMemcpy = IsTriviallyCopyAssignable<T>::value;
-        static const bool canFillWithMemset = IsTriviallyDefaultConstructible<T>::value && (sizeof(T) == sizeof(char));
-        static const bool canCompareWithMemcmp = IsScalar<T>::value; // Types without padding.
-        template<typename U = void>
+    static const bool canMoveWithMemcpy = IsTriviallyMoveAssignable<T>::value;
+    static const bool canCopyWithMemcpy = IsTriviallyCopyAssignable<T>::value;
+    static const bool canFillWithMemset = IsTriviallyDefaultConstructible<T>::value && (sizeof(T) == sizeof(char));
+    static const bool canCompareWithMemcmp = IsScalar<T>::value; // Types without padding.
+    template <typename U = void>
+    struct NeedsTracingLazily {
+        static const bool value = NeedsTracing<T>::value;
+    };
+    static const WeakHandlingFlag weakHandlingFlag = NoWeakHandlingInCollections; // We don't support weak handling in vectors.
+};
+
+template <typename T>
+struct VectorTraits : VectorTraitsBase<T> {};
+
+// Classes marked with SimpleVectorTraits will use memmov, memcpy, memcmp
+// instead of constructors, copy operators, etc for initialization, move and
+// comparison.
+template <typename T>
+struct SimpleClassVectorTraits : VectorTraitsBase<T> {
+    static const bool canInitializeWithMemset = true;
+    static const bool canClearUnusedSlotsWithMemset = true;
+    static const bool canMoveWithMemcpy = true;
+    static const bool canCompareWithMemcmp = true;
+};
+
+// We know OwnPtr and RefPtr are simple enough that initializing to 0 and moving
+// with memcpy (and then not destructing the original) will totally work.
+template <typename P>
+struct VectorTraits<RefPtr<P>> : SimpleClassVectorTraits<RefPtr<P>> {};
+
+template <typename P>
+struct VectorTraits<OwnPtr<P>> : SimpleClassVectorTraits<OwnPtr<P>> {
+    // OwnPtr -> PassOwnPtr has a very particular structure that tricks the
+    // normal type traits into thinking that the class is "trivially copyable".
+    static const bool canCopyWithMemcpy = false;
+};
+static_assert(VectorTraits<RefPtr<int>>::canInitializeWithMemset, "inefficient RefPtr Vector");
+static_assert(VectorTraits<RefPtr<int>>::canMoveWithMemcpy, "inefficient RefPtr Vector");
+static_assert(VectorTraits<RefPtr<int>>::canCompareWithMemcmp, "inefficient RefPtr Vector");
+static_assert(VectorTraits<OwnPtr<int>>::canInitializeWithMemset, "inefficient OwnPtr Vector");
+static_assert(VectorTraits<OwnPtr<int>>::canMoveWithMemcpy, "inefficient OwnPtr Vector");
+static_assert(VectorTraits<OwnPtr<int>>::canCompareWithMemcmp, "inefficient OwnPtr Vector");
+
+template <typename First, typename Second>
+struct VectorTraits<std::pair<First, Second>> {
+    typedef VectorTraits<First> FirstTraits;
+    typedef VectorTraits<Second> SecondTraits;
+
+    static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
+    static const bool canInitializeWithMemset = FirstTraits::canInitializeWithMemset && SecondTraits::canInitializeWithMemset;
+    static const bool canMoveWithMemcpy = FirstTraits::canMoveWithMemcpy && SecondTraits::canMoveWithMemcpy;
+    static const bool canCopyWithMemcpy = FirstTraits::canCopyWithMemcpy && SecondTraits::canCopyWithMemcpy;
+    static const bool canFillWithMemset = false;
+    static const bool canCompareWithMemcmp = FirstTraits::canCompareWithMemcmp && SecondTraits::canCompareWithMemcmp;
+    static const bool canClearUnusedSlotsWithMemset = FirstTraits::canClearUnusedSlotsWithMemset && SecondTraits::canClearUnusedSlotsWithMemset;
+    template <typename U = void>
         struct NeedsTracingLazily {
-            static const bool value = NeedsTracing<T>::value;
-        };
-        static const WeakHandlingFlag weakHandlingFlag = NoWeakHandlingInCollections; // We don't support weak handling in vectors.
+        static const bool value = ShouldBeTraced<FirstTraits>::value || ShouldBeTraced<SecondTraits>::value;
     };
-
-    template<typename T>
-    struct VectorTraits : VectorTraitsBase<T> { };
-
-    // Classes marked with SimpleVectorTraits will use memmov, memcpy, memcmp
-    // instead of constructors, copy operators, etc for initialization, move
-    // and comparison.
-    template<typename T>
-    struct SimpleClassVectorTraits : VectorTraitsBase<T>
-    {
-        static const bool canInitializeWithMemset = true;
-        static const bool canClearUnusedSlotsWithMemset = true;
-        static const bool canMoveWithMemcpy = true;
-        static const bool canCompareWithMemcmp = true;
-    };
-
-    // We know OwnPtr and RefPtr are simple enough that initializing to 0 and
-    // moving with memcpy (and then not destructing the original) will totally
-    // work.
-    template<typename P>
-    struct VectorTraits<RefPtr<P>> : SimpleClassVectorTraits<RefPtr<P>> { };
-
-    template<typename P>
-    struct VectorTraits<OwnPtr<P>> : SimpleClassVectorTraits<OwnPtr<P>> {
-        // OwnPtr -> PassOwnPtr has a very particular structure that
-        // tricks the normal type traits into thinking that the class
-        // is "trivially copyable".
-        static const bool canCopyWithMemcpy = false;
-    };
-    static_assert(VectorTraits<RefPtr<int>>::canInitializeWithMemset, "inefficient RefPtr Vector");
-    static_assert(VectorTraits<RefPtr<int>>::canMoveWithMemcpy, "inefficient RefPtr Vector");
-    static_assert(VectorTraits<RefPtr<int>>::canCompareWithMemcmp, "inefficient RefPtr Vector");
-    static_assert(VectorTraits<OwnPtr<int>>::canInitializeWithMemset, "inefficient OwnPtr Vector");
-    static_assert(VectorTraits<OwnPtr<int>>::canMoveWithMemcpy, "inefficient OwnPtr Vector");
-    static_assert(VectorTraits<OwnPtr<int>>::canCompareWithMemcmp, "inefficient OwnPtr Vector");
-
-    template<typename First, typename Second>
-    struct VectorTraits<pair<First, Second>>
-    {
-        typedef VectorTraits<First> FirstTraits;
-        typedef VectorTraits<Second> SecondTraits;
-
-        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
-        static const bool canInitializeWithMemset = FirstTraits::canInitializeWithMemset && SecondTraits::canInitializeWithMemset;
-        static const bool canMoveWithMemcpy = FirstTraits::canMoveWithMemcpy && SecondTraits::canMoveWithMemcpy;
-        static const bool canCopyWithMemcpy = FirstTraits::canCopyWithMemcpy && SecondTraits::canCopyWithMemcpy;
-        static const bool canFillWithMemset = false;
-        static const bool canCompareWithMemcmp = FirstTraits::canCompareWithMemcmp && SecondTraits::canCompareWithMemcmp;
-        static const bool canClearUnusedSlotsWithMemset = FirstTraits::canClearUnusedSlotsWithMemset && SecondTraits::canClearUnusedSlotsWithMemset;
-        template <typename U = void>
-        struct NeedsTracingLazily {
-            static const bool value = ShouldBeTraced<FirstTraits>::value || ShouldBeTraced<SecondTraits>::value;
-        };
-        static const WeakHandlingFlag weakHandlingFlag = NoWeakHandlingInCollections; // We don't support weak handling in vectors.
-    };
+    static const WeakHandlingFlag weakHandlingFlag = NoWeakHandlingInCollections; // We don't support weak handling in vectors.
+};
 
 } // namespace WTF
 
 #define WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(ClassName) \
 namespace WTF { \
 static_assert(!IsTriviallyDefaultConstructible<ClassName>::value || !IsTriviallyMoveAssignable<ClassName>::value || !IsScalar<ClassName>::value, "macro not needed"); \
-    template<> \
-    struct VectorTraits<ClassName> : SimpleClassVectorTraits<ClassName> { }; \
+template <> \
+struct VectorTraits<ClassName> : SimpleClassVectorTraits<ClassName> {}; \
 }
 
 #define WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(ClassName) \
 namespace WTF { \
 static_assert(!IsTriviallyDefaultConstructible<ClassName>::value || !IsTriviallyMoveAssignable<ClassName>::value, "macro not needed"); \
-    template<> \
-    struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
-    { \
-        static const bool canInitializeWithMemset = true; \
-        static const bool canClearUnusedSlotsWithMemset = true; \
-        static const bool canMoveWithMemcpy = true; \
-    }; \
+template <> \
+struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
+{ \
+    static const bool canInitializeWithMemset = true; \
+    static const bool canClearUnusedSlotsWithMemset = true; \
+    static const bool canMoveWithMemcpy = true; \
+}; \
 }
 
 #define WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(ClassName) \
 namespace WTF { \
 static_assert(!IsTriviallyDefaultConstructible<ClassName>::value, "macro not needed"); \
-    template<> \
-    struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
-    { \
-        static const bool canInitializeWithMemset = true; \
-        static const bool canClearUnusedSlotsWithMemset = true; \
-    }; \
+template <> \
+struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
+{ \
+    static const bool canInitializeWithMemset = true; \
+    static const bool canClearUnusedSlotsWithMemset = true; \
+}; \
 }
 
 #define WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(ClassName) \
 namespace WTF { \
 static_assert(!IsTriviallyDefaultConstructible<ClassName>::value, "macro not needed"); \
-    template<> \
-    struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
-    { \
-        static const bool canClearUnusedSlotsWithMemset = true; \
-    }; \
+template <> \
+struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> \
+{ \
+    static const bool canClearUnusedSlotsWithMemset = true; \
+}; \
 }
 
 using WTF::VectorTraits;
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
index 2f82c06b..38d5c59 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -397,6 +397,12 @@
     return impl;
 }
 
+void StringImpl::reserveStaticStringsCapacityForSize(unsigned size)
+{
+    ASSERT(s_allowCreationOfStaticStrings);
+    staticStrings().reserveCapacityForSize(size);
+}
+
 PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
 {
     if (!characters || !length)
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.h b/third_party/WebKit/Source/wtf/text/StringImpl.h
index eb62621..35e16023 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.h
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.h
@@ -197,6 +197,7 @@
     ~StringImpl();
 
     static StringImpl* createStatic(const char* string, unsigned length, unsigned hash);
+    static void reserveStaticStringsCapacityForSize(unsigned size);
     static void freezeStaticStrings();
     static const StaticStringsTable& allStaticStrings();
     static unsigned highestStaticStringLength() { return m_highestStaticStringLength; }
diff --git a/third_party/WebKit/Source/wtf/text/StringStatics.cpp b/third_party/WebKit/Source/wtf/text/StringStatics.cpp
index 9231216e..7a807f6 100644
--- a/third_party/WebKit/Source/wtf/text/StringStatics.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringStatics.cpp
@@ -79,15 +79,23 @@
     new (NotNull, (void*)&emptyAtom) AtomicString("");
 }
 
+template<unsigned charactersCount>
+PassRefPtr<StringImpl> addStaticASCIILiteral(const char (&characters)[charactersCount])
+{
+    unsigned length = charactersCount - 1;
+    unsigned hash = StringHasher::computeHashAndMaskTop8Bits(reinterpret_cast<const LChar*>(characters), length);
+    return adoptRef(StringImpl::createStatic(characters, length, hash));
+}
+
 void StringStatics::init()
 {
     ASSERT(isMainThread());
 
     // FIXME: These should be allocated at compile time.
     new (NotNull, (void*)&starAtom) AtomicString("*", AtomicString::ConstructFromLiteral);
-    new (NotNull, (void*)&xmlAtom) AtomicString("xml", AtomicString::ConstructFromLiteral);
-    new (NotNull, (void*)&xmlnsAtom) AtomicString("xmlns", AtomicString::ConstructFromLiteral);
-    new (NotNull, (void*)&xlinkAtom) AtomicString("xlink", AtomicString::ConstructFromLiteral);
+    new (NotNull, (void*)&xmlAtom) AtomicString(addStaticASCIILiteral("xml"));
+    new (NotNull, (void*)&xmlnsAtom) AtomicString(addStaticASCIILiteral("xmlns"));
+    new (NotNull, (void*)&xlinkAtom) AtomicString(addStaticASCIILiteral("xlink"));
     new (NotNull, (void*)&xmlnsWithColon) String("xmlns:");
 }
 
diff --git a/third_party/WebKit/public/platform/WebProcessMemoryDump.h b/third_party/WebKit/public/platform/WebProcessMemoryDump.h
index 27c6e1a..3ffb663 100644
--- a/third_party/WebKit/public/platform/WebProcessMemoryDump.h
+++ b/third_party/WebKit/public/platform/WebProcessMemoryDump.h
@@ -7,8 +7,11 @@
 
 #include "WebCommon.h"
 #include "WebMemoryAllocatorDump.h"
+#include "WebMemoryDumpProvider.h"
 #include "WebString.h"
 
+class SkTraceMemoryDump;
+
 namespace blink {
 
 // A container which holds all the dumps for the various allocators for a given
@@ -77,6 +80,29 @@
     {
         BLINK_ASSERT_NOT_REACHED();
     }
+
+    // Utility method to add a suballocation relationship with the following
+    // semantics: |source| is suballocated from |target_node_name|.
+    // This creates a child node of |target_node_name| and adds an ownership
+    // edge between |source| and the new child node. As a result, the UI will
+    // not account the memory of |source| in the target node.
+    virtual void AddSuballocation(WebMemoryAllocatorDumpGuid source, const WebString& targetNodeName)
+    {
+        BLINK_ASSERT_NOT_REACHED();
+    }
+
+    // Returns the SkTraceMemoryDump proxy interface that can be passed to Skia
+    // to dump into this WebProcessMemoryDump. Multiple SkTraceMemoryDump
+    // objects can be created using this method. The created dumpers are owned
+    // by WebProcessMemoryDump and cannot outlive the WebProcessMemoryDump
+    // object owning them. |dumpNamePrefix| is prefix appended to each dump
+    // created by the SkTraceMemoryDump implementation, if the dump should be
+    // placed under different namespace and not "skia".
+    virtual SkTraceMemoryDump* CreateDumpAdapterForSkia(const WebString& dumpNamePrefix)
+    {
+        BLINK_ASSERT_NOT_REACHED();
+        return nullptr;
+    }
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebTaskRunner.h b/third_party/WebKit/public/platform/WebTaskRunner.h
index b3e9745f..4369ad9 100644
--- a/third_party/WebKit/public/platform/WebTaskRunner.h
+++ b/third_party/WebKit/public/platform/WebTaskRunner.h
@@ -32,11 +32,6 @@
 
     // Schedule a task to be run after |delayMs| on the the associated WebThread.
     // Takes ownership of |Task|. Can be called from any thread.
-    // TODO(alexclarke): Remove this when possible.
-    virtual void postDelayedTask(const WebTraceLocation&, Task*, long long delayMs) {}
-
-    // Schedule a task to be run after |delayMs| on the the associated WebThread.
-    // Takes ownership of |Task|. Can be called from any thread.
     virtual void postDelayedTask(const WebTraceLocation&, Task*, double delayMs) {}
 
 #ifdef INSIDE_BLINK
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h
index 8966fbd..79df421 100644
--- a/third_party/WebKit/public/platform/WebURLResponse.h
+++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -31,9 +31,9 @@
 #ifndef WebURLResponse_h
 #define WebURLResponse_h
 
-#include "WebCommon.h"
-#include "WebPrivateOwnPtr.h"
-#include "WebServiceWorkerResponseType.h"
+#include "public/platform/WebCommon.h"
+#include "public/platform/WebPrivateOwnPtr.h"
+#include "public/platform/WebServiceWorkerResponseType.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h b/third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h
index 7c590cb6..5691955e 100644
--- a/third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h
+++ b/third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h
@@ -33,7 +33,7 @@
 
     // Takes ownership of the WebSyncUnregistrationCallbacks.
     // Does not take ownership of the WebServiceWorkerRegistration.
-    virtual void unregisterBackgroundSync(blink::WebSyncRegistration::Periodicity, int64_t, const WebString&, WebServiceWorkerRegistration*, WebSyncUnregistrationCallbacks*) = 0;
+    virtual void unregisterBackgroundSync(int64_t handleId, WebServiceWorkerRegistration*, WebSyncUnregistrationCallbacks*) = 0;
 
     // Takes ownership of the WebSyncRegistrationCallbacks.
     // Does not take ownership of the WebServiceWorkerRegistration.
@@ -48,9 +48,9 @@
     virtual void getPermissionStatus(blink::WebSyncRegistration::Periodicity, WebServiceWorkerRegistration*, WebSyncGetPermissionStatusCallbacks*) = 0;
 
     // Takes ownership of the WebSyncNotifyWhenDoneCallbacks.
-    virtual void notifyWhenDone(int64_t syncId, WebSyncNotifyWhenDoneCallbacks*) = 0;
+    virtual void notifyWhenDone(int64_t handleId, WebSyncNotifyWhenDoneCallbacks*) = 0;
 
-    virtual void releaseRegistration(int64_t syncId) = 0;
+    virtual void releaseRegistration(int64_t handleId) = 0;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h
index 5784873..89c53d8 100644
--- a/third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h
+++ b/third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h
@@ -47,21 +47,21 @@
     virtual ~WebIDBCallbacks() { }
 
     // Pointers transfer ownership.
-    virtual void onError(const WebIDBDatabaseError&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebVector<WebString>&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(WebIDBCursor*, const WebIDBKey&, const WebIDBKey& primaryKey, const WebData&, const WebVector<WebBlobInfo>&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(WebIDBDatabase*, const WebIDBMetadata&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebIDBKey&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebData&, const WebVector<WebBlobInfo>&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebIDBValue&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebVector<WebIDBValue>&) { BLINK_ASSERT_NOT_REACHED(); }
+    virtual void onError(const WebIDBDatabaseError&) = 0;
+    virtual void onSuccess(const WebVector<WebString>&) = 0;
+    virtual void onSuccess(WebIDBCursor*, const WebIDBKey&, const WebIDBKey& primaryKey, const WebData&, const WebVector<WebBlobInfo>&) = 0;
+    virtual void onSuccess(WebIDBDatabase*, const WebIDBMetadata&) = 0;
+    virtual void onSuccess(const WebIDBKey&) = 0;
+    virtual void onSuccess(const WebData&, const WebVector<WebBlobInfo>&) = 0;
+    virtual void onSuccess(const WebIDBValue&) = 0;
+    virtual void onSuccess(const WebVector<WebIDBValue>&) = 0;
     // TODO(cmumford): Eliminate redundant onSuccess overloads http://crbug.com/487711
-    virtual void onSuccess(const WebData&, const WebVector<WebBlobInfo>&, const WebIDBKey&, const WebIDBKeyPath&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(long long) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess() { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onSuccess(const WebIDBKey&, const WebIDBKey& primaryKey, const WebData&, const WebVector<WebBlobInfo>&) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onBlocked(long long oldVersion) { BLINK_ASSERT_NOT_REACHED(); }
-    virtual void onUpgradeNeeded(long long oldVersion, WebIDBDatabase*, const WebIDBMetadata&, unsigned short dataLoss, WebString dataLossMessage) { BLINK_ASSERT_NOT_REACHED(); }
+    virtual void onSuccess(const WebData&, const WebVector<WebBlobInfo>&, const WebIDBKey&, const WebIDBKeyPath&) = 0;
+    virtual void onSuccess(long long) = 0;
+    virtual void onSuccess() = 0;
+    virtual void onSuccess(const WebIDBKey&, const WebIDBKey& primaryKey, const WebData&, const WebVector<WebBlobInfo>&) = 0;
+    virtual void onBlocked(long long oldVersion) = 0;
+    virtual void onUpgradeNeeded(long long oldVersion, WebIDBDatabase*, const WebIDBMetadata&, unsigned short dataLoss, WebString dataLossMessage) = 0;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h b/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h
index 699b929..33c628b3 100644
--- a/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h
+++ b/third_party/WebKit/public/platform/modules/push_messaging/WebPushSubscription.h
@@ -12,15 +12,15 @@
 namespace blink {
 
 struct WebPushSubscription {
-    // The |endpoint| and |curve25519dh| must both be unique for each subscription.
-    WebPushSubscription(const WebURL& endpoint, const WebVector<unsigned char>& curve25519dh)
+    // The |endpoint| and |p256dh| must both be unique for each subscription.
+    WebPushSubscription(const WebURL& endpoint, const WebVector<unsigned char>& p256dh)
         : endpoint(endpoint)
-        , curve25519dh(curve25519dh)
+        , p256dh(p256dh)
     {
     }
 
     WebURL endpoint;
-    WebVector<unsigned char> curve25519dh;
+    WebVector<unsigned char> p256dh;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/web/WebAXEnums.h b/third_party/WebKit/public/web/WebAXEnums.h
index 9dd2122..ccfbd50 100644
--- a/third_party/WebKit/public/web/WebAXEnums.h
+++ b/third_party/WebKit/public/web/WebAXEnums.h
@@ -46,6 +46,7 @@
     WebAXEventChildrenChanged,
     WebAXEventFocus,
     WebAXEventHide,
+    WebAXEventHover,
     WebAXEventInvalidStatusChanged,
     WebAXEventLayoutComplete,
     WebAXEventLiveRegionChanged,
diff --git a/third_party/WebKit/public/web/WebDOMCustomEvent.h b/third_party/WebKit/public/web/WebDOMCustomEvent.h
index f8189634..7d0c486f7 100644
--- a/third_party/WebKit/public/web/WebDOMCustomEvent.h
+++ b/third_party/WebKit/public/web/WebDOMCustomEvent.h
@@ -31,16 +31,16 @@
 #define WebDOMCustomEvent_h
 
 #include "WebDOMEvent.h"
-#include "WebSerializedScriptValue.h"
 
 namespace blink {
 
 class WebString;
 
+// TODO(esprehn): Remove this and IPCEcho which appears to just be dead code.
 class WebDOMCustomEvent : public WebDOMEvent {
 public:
+    BLINK_EXPORT WebDOMCustomEvent(const WebString& type);
     WebDOMCustomEvent() { }
-    BLINK_EXPORT void initCustomEvent(const WebString& type, bool canBubble, bool cancelable, const WebSerializedScriptValue& messageData);
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/web/WebDOMMessageEvent.h b/third_party/WebKit/public/web/WebDOMMessageEvent.h
index d3e1ce36..71d26c0 100644
--- a/third_party/WebKit/public/web/WebDOMMessageEvent.h
+++ b/third_party/WebKit/public/web/WebDOMMessageEvent.h
@@ -30,27 +30,27 @@
 #ifndef WebDOMMessageEvent_h
 #define WebDOMMessageEvent_h
 
-#include "../platform/WebMessagePortChannel.h"
-#include "WebDOMEvent.h"
-#include "WebSerializedScriptValue.h"
+#include "public/platform/WebMessagePortChannel.h"
+#include "public/platform/WebString.h"
+#include "public/web/WebDOMEvent.h"
+#include "public/web/WebDocument.h"
+#include "public/web/WebSerializedScriptValue.h"
 
 #if BLINK_IMPLEMENTATION
-#include "core/events/Event.h"
 #include "core/events/MessageEvent.h"
 #endif
 
 namespace blink {
 
 class WebFrame;
-class WebString;
 
 // An interface for posting message events to the target frame. The message
 // events are used for communication between documents and described here:
 // http://www.w3.org/TR/2012/WD-webmessaging-20120313/#terminology
 class WebDOMMessageEvent : public WebDOMEvent {
 public:
+    BLINK_EXPORT WebDOMMessageEvent(const WebSerializedScriptValue& messageData, const WebString& origin = WebString(), const WebFrame* sourceFrame = nullptr, const WebDocument& targetDocument = WebDocument(), const WebMessagePortChannelArray& channels = WebMessagePortChannelArray());
     WebDOMMessageEvent() { }
-    BLINK_EXPORT void initMessageEvent(const WebString& type, bool canBubble, bool cancelable, const WebSerializedScriptValue& messageData, const WebString& origin, const WebFrame* sourceFrame, const WebDocument& targetDocument, const WebString& lastEventId, const WebMessagePortChannelArray& channels = WebMessagePortChannelArray());
 
     BLINK_EXPORT WebSerializedScriptValue data() const;
     BLINK_EXPORT WebString origin() const;
diff --git a/third_party/WebKit/public/web/WebDocument.h b/third_party/WebKit/public/web/WebDocument.h
index 0dfdeedd..8b415834 100644
--- a/third_party/WebKit/public/web/WebDocument.h
+++ b/third_party/WebKit/public/web/WebDocument.h
@@ -76,7 +76,7 @@
     BLINK_EXPORT WebURL url() const;
     // Note: Security checks should use the securityOrigin(), not url().
     BLINK_EXPORT WebSecurityOrigin securityOrigin() const;
-    BLINK_EXPORT bool isPrivilegedContext(WebString& errorMessage) const;
+    BLINK_EXPORT bool isSecureContext(WebString& errorMessage) const;
 
     BLINK_EXPORT WebString encoding() const;
     BLINK_EXPORT WebString contentLanguage() const;
@@ -110,7 +110,6 @@
     BLINK_EXPORT WebDocumentType doctype() const;
     BLINK_EXPORT void cancelFullScreen();
     BLINK_EXPORT WebElement fullScreenElement() const;
-    BLINK_EXPORT WebDOMEvent createEvent(const WebString& eventType);
     BLINK_EXPORT WebReferrerPolicy referrerPolicy() const;
     BLINK_EXPORT WebString outgoingReferrer();
 
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index a0ac6dd..54a8fe9 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -193,7 +193,6 @@
     virtual void loadURLExternally(
         WebLocalFrame*, const WebURLRequest&, WebNavigationPolicy, const WebString& downloadName) { }
 
-
     // Navigational queries ------------------------------------------------
 
     // The client may choose to alter the navigation policy.  Otherwise,
@@ -236,6 +235,8 @@
     // This returns such a history item if appropriate.
     virtual WebHistoryItem historyItemForNewChildFrame(WebFrame*) { return WebHistoryItem(); }
 
+    // Whether the client is handling a navigation request.
+    virtual bool hasPendingNavigation(WebLocalFrame*) { return false; }
 
     // Navigational notifications ------------------------------------------
 
diff --git a/third_party/WebKit/public/web/WebInputEvent.h b/third_party/WebKit/public/web/WebInputEvent.h
index 248e3d10..86bafa8 100644
--- a/third_party/WebKit/public/web/WebInputEvent.h
+++ b/third_party/WebKit/public/web/WebInputEvent.h
@@ -172,6 +172,11 @@
         // Left/right modifiers for keyboard events.
         IsLeft           = 1 << 11,
         IsRight          = 1 << 12,
+
+        // Indicates that an event was generated on the touch screen while
+        // touch accessibility is enabled, so the event should be handled
+        // by accessibility code first before normal input event processing.
+        IsTouchAccessibility = 1 << 13
     };
 
     // The rail mode for a wheel event specifies the axis on which scrolling is
diff --git a/third_party/WebKit/public/web/WebNavigationPolicy.h b/third_party/WebKit/public/web/WebNavigationPolicy.h
index 36be0db..616ae6e 100644
--- a/third_party/WebKit/public/web/WebNavigationPolicy.h
+++ b/third_party/WebKit/public/web/WebNavigationPolicy.h
@@ -41,6 +41,7 @@
     WebNavigationPolicyNewForegroundTab,
     WebNavigationPolicyNewWindow,
     WebNavigationPolicyNewPopup,
+    WebNavigationPolicyHandledByClient,
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/public/web/WebPageSerializer.h b/third_party/WebKit/public/web/WebPageSerializer.h
index 333e010e..f1a5f372 100644
--- a/third_party/WebKit/public/web/WebPageSerializer.h
+++ b/third_party/WebKit/public/web/WebPageSerializer.h
@@ -70,17 +70,14 @@
     // The API below is an older implementation of a pageserialization that
     // will be removed soon.
 
-
-    // This function will find out all frames and serialize them to HTML data.
+    // This function will serialize the specified frame to HTML data.
     // We have a data buffer to temporary saving generated html data. We will
     // sequentially call WebPageSeriazlierClient once the data buffer is full.
     //
-    // Return false means no available frame has been serialized, otherwise
-    // return true.
+    // Return false means if no data has been serialized (i.e. because
+    // the target frame didn't have a valid url).
     //
     // The parameter frame specifies which frame need to be serialized.
-    // The parameter recursive specifies whether we need to
-    // serialize all sub frames of the specified frame or not.
     // The parameter client specifies the pointer of interface
     // WebPageSerializerClient providing a sink interface to receive the
     // individual chunks of data to be saved.
@@ -91,7 +88,6 @@
     // contain all saved auxiliary files included all sub frames and resources.
     BLINK_EXPORT static bool serialize(
         WebLocalFrame*,
-        bool recursive,
         WebPageSerializerClient*,
         const WebVector<WebURL>& links,
         const WebVector<WebString>& localPaths,
diff --git a/third_party/WebKit/public/web/WebWidget.h b/third_party/WebKit/public/web/WebWidget.h
index 0b926bb..e9f186a8 100644
--- a/third_party/WebKit/public/web/WebWidget.h
+++ b/third_party/WebKit/public/web/WebWidget.h
@@ -194,8 +194,14 @@
     virtual bool compositionRange(size_t* location, size_t* length) { return false; }
 
     // Returns information about the current text input of this WebWidget.
+    // Note that this query can be expensive for long fields, as it returns the
+    // plain-text representation of the current editable element. Consider using
+    // the lighter-weight textInputType() when appropriate.
     virtual WebTextInputInfo textInputInfo() { return WebTextInputInfo(); }
 
+    // Returns the type of current text input of this WebWidget.
+    virtual WebTextInputType textInputType() { return WebTextInputTypeNone; }
+
     // Returns the anchor and focus bounds of the current selection.
     // If the selection range is empty, it returns the caret bounds.
     virtual bool selectionBounds(WebRect& anchor, WebRect& focus) const { return false; }
diff --git a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
index f675c4a..ced91d2 100644
--- a/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_ia32/binutils.tar.bz2.sha1
@@ -1 +1 @@
-27e33f55580447b20eac71849a04168274aab7e8
\ No newline at end of file
+a0d516b95f19512a112cdad25259dd56b369863e
\ No newline at end of file
diff --git a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1 b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
index f4c6084..769e08b 100644
--- a/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
+++ b/third_party/binutils/Linux_x64/binutils.tar.bz2.sha1
@@ -1 +1 @@
-733c355177167e11c45f7bf49f144153fda335cc
\ No newline at end of file
+3dc3f9f1ba7b3a9df28adb104b4ed37f1c26f68a
\ No newline at end of file
diff --git a/third_party/binutils/README.chromium b/third_party/binutils/README.chromium
index d20934b..8273054 100644
--- a/third_party/binutils/README.chromium
+++ b/third_party/binutils/README.chromium
@@ -1,6 +1,6 @@
 Name: binutils
 URL: http://www.gnu.org/software/binutils/
-Version: 2.24
+Version: 2.25
 License: GPL v2
 License File: NOT_SHIPPED
 Security Critical: no
@@ -9,21 +9,39 @@
 This directory contains i386 and amd64 binaries of the binutils tools
 (including gold linker).
 
-They were built from binutils-2.24 using the "build-all.sh" script on a Ubuntu
+They were built from binutils-2.25 using the "build-all.sh" script on a Ubuntu
 Precise.
 
-The script creates chroots for 32bit and 64bit Ubuntu Lucid and then builds
+The script creates chroots for 32bit and 64bit Ubuntu Precise and then builds
 binutils inside the roots.
 
-Local patches:
- * ehframe-race.patch for http://crbug.com/161942 from upstream change
-   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=635aa30e3ae9735e362cfd1cda2be9f7b65b32a2
+Version 2.25 was released on Wed, 24 Dec 2014
 
+Local patches:
  * unlock-thin.patch for http://crbug.com/453195 from upstream change
    https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=2cfbf2fece582c29df348104b28677c38a8301f4
+   (Landed upstream Wed, 4 Feb 2015 - should be in 2.26)
 
  * plugin-dso-fix.patch for http://crbug.com/453195 from upstream change
    https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=3c537f7fdb11f02f7082749f3f21dfdd2c2025e8
+   (Landed upstream Thu, 5 Feb 2015 - should be in 2.26)
 
  * (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
    binaries and uploading them to Google storage.
+
+Upgrading:
+
+To upgrade binutils, use the following steps:
+
+ * Update build-all.sh with the new binutil version.
+ * Remove any patches which have been merged upstream from build-all.sh
+ * Update this README.chromium file
+ * Run build-all.sh
+ * Run upload.sh
+ * Wait for goma to have new binutils deployed (see http://go/ma).
+    Please notify {ukai,yyanagisawa,shinyak}@chromium.org and await
+    confirmation.
+ * Commit the change
+
+See https://codereview.chromium.org/1368233002/ for an example upgrade.
+
diff --git a/third_party/binutils/build-all.sh b/third_party/binutils/build-all.sh
index a39984ca..99d1070 100755
--- a/third_party/binutils/build-all.sh
+++ b/third_party/binutils/build-all.sh
@@ -22,7 +22,7 @@
 fi
 
 # Download the source
-VERSION=2.24
+VERSION=2.25
 wget -c http://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2
 
 # Verify the signature
@@ -43,14 +43,21 @@
   # Patch the source
   (
     cd binutils-$VERSION
-    patch -p1 < ../ehframe-race.patch
+    echo "unlock-thin.patch"
+    echo "=================================="
     patch -p1 < ../unlock-thin.patch
+    echo "----------------------------------"
+    echo
+    echo "plugin-dso-fix.patch"
+    echo "=================================="
     patch -p1 < ../plugin-dso-fix.patch
+    echo "----------------------------------"
+    echo
   )
 fi
 
 for ARCH in i386 amd64; do
-  if [ ! -d lucid-chroot-$ARCH ]; then
+  if [ ! -d precise-chroot-$ARCH ]; then
     # Refresh sudo credentials
     sudo -v
 
@@ -61,11 +68,11 @@
     sudo debootstrap \
         --arch=$ARCH \
         --include=build-essential,flex,bison \
-        lucid lucid-chroot-$ARCH
+        precise precise-chroot-$ARCH
     echo "============================="
   fi
 
-  BUILDDIR=lucid-chroot-$ARCH/build
+  BUILDDIR=precise-chroot-$ARCH/build
 
   # Clean up any previous failed build attempts inside chroot
   if [ -d "$BUILDDIR" ]; then
@@ -92,7 +99,7 @@
   echo ""
   echo "Building binutils for $ARCH"
   LOGFILE="$OUTPUTDIR/build-$ARCH.log"
-  if ! sudo $PREFIX chroot lucid-chroot-$ARCH /build/build-one.sh /build/binutils-$VERSION > $LOGFILE 2>&1; then
+  if ! sudo $PREFIX chroot precise-chroot-$ARCH /build/build-one.sh /build/binutils-$VERSION > $LOGFILE 2>&1; then
     echo "Build failed! See $LOGFILE for details."
     exit 1
   fi
diff --git a/third_party/binutils/ehframe-race.patch b/third_party/binutils/ehframe-race.patch
deleted file mode 100644
index ab0d01e..0000000
--- a/third_party/binutils/ehframe-race.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-diff --git a/gold/gold.cc b/gold/gold.cc
-index 4833aec..bdfb33d 100644
---- a/gold/gold.cc
-+++ b/gold/gold.cc
-@@ -808,6 +808,8 @@ queue_final_tasks(const General_options& options,
-   if (!any_postprocessing_sections)
-     {
-       input_sections_blocker = new Task_token(true);
-+      // Write_symbols_task, Relocate_tasks.
-+      input_sections_blocker->add_blocker();
-       input_sections_blocker->add_blockers(input_objects->number_of_relobjs());
-     }
- 
-@@ -836,6 +838,7 @@ queue_final_tasks(const General_options& options,
- 
-   // Queue a task to write out the output sections.
-   workqueue->queue(new Write_sections_task(layout, of, output_sections_blocker,
-+					   input_sections_blocker,
- 					   final_blocker));
- 
-   // Queue a task to write out everything else.
-diff --git a/gold/layout.cc b/gold/layout.cc
-index 82db775..ef0a879 100644
---- a/gold/layout.cc
-+++ b/gold/layout.cc
-@@ -5532,6 +5532,8 @@ void
- Write_sections_task::locks(Task_locker* tl)
- {
-   tl->add(this, this->output_sections_blocker_);
-+  if (this->input_sections_blocker_ != NULL)
-+    tl->add(this, this->input_sections_blocker_);
-   tl->add(this, this->final_blocker_);
- }
- 
-diff --git a/gold/layout.h b/gold/layout.h
-index 7c0113c..032f5f3 100644
---- a/gold/layout.h
-+++ b/gold/layout.h
-@@ -1454,9 +1454,11 @@ class Write_sections_task : public Task
-  public:
-   Write_sections_task(const Layout* layout, Output_file* of,
- 		      Task_token* output_sections_blocker,
-+		      Task_token* input_sections_blocker,
- 		      Task_token* final_blocker)
-     : layout_(layout), of_(of),
-       output_sections_blocker_(output_sections_blocker),
-+      input_sections_blocker_(input_sections_blocker),
-       final_blocker_(final_blocker)
-   { }
- 
-@@ -1481,6 +1483,7 @@ class Write_sections_task : public Task
-   const Layout* layout_;
-   Output_file* of_;
-   Task_token* output_sections_blocker_;
-+  Task_token* input_sections_blocker_;
-   Task_token* final_blocker_;
- };
- 
-diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
-index dd06d5f..35cd013 100644
---- a/gold/testsuite/Makefile.am
-+++ b/gold/testsuite/Makefile.am
-@@ -2380,10 +2380,9 @@ endif DEFAULT_TARGET_X86_64
- if DEFAULT_TARGET_X86_64
- check_PROGRAMS += exception_x86_64_bnd_test
- exception_x86_64_bnd_test_SOURCES = exception_test_main.cc
--exception_x86_64_bnd_test_DEPENDENCIES = exception_x86_64_bnd_1.o \
--					 exception_x86_64_bnd_2.o
-+exception_x86_64_bnd_test_DEPENDENCIES = gcctestdir/ld exception_x86_64_bnd_1.o exception_x86_64_bnd_2.o
- exception_x86_64_bnd_test_LDFLAGS = $(exception_test_LDFLAGS)
--exception_x86_64_bnd_test_LDADD = $(exception_x86_64_bnd_test_DEPENDENCIES)
-+exception_x86_64_bnd_test_LDADD = exception_x86_64_bnd_1.o exception_x86_64_bnd_2.o
- exception_x86_64_bnd_1.o: exception_test_1.cc gcctestdir/as
- 	$(CXXCOMPILE) -c -fpic -Bgcctestdir/ -Wa,-madd-bnd-prefix -o $@ $<
- exception_x86_64_bnd_2.o: exception_test_2.cc gcctestdir/as
-diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
-index fed610f..8fbb644 100644
---- a/gold/testsuite/Makefile.in
-+++ b/gold/testsuite/Makefile.in
-@@ -2732,11 +2732,9 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \
- @GCC_TRUE@@NATIVE_LINKER_TRUE@ehdr_start_test_5_LDFLAGS = -Bgcctestdir/
- @GCC_TRUE@@NATIVE_LINKER_TRUE@ehdr_start_test_5_LDADD = 
- @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_SOURCES = exception_test_main.cc
--@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_DEPENDENCIES = exception_x86_64_bnd_1.o \
--@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@					 exception_x86_64_bnd_2.o
--
-+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_DEPENDENCIES = gcctestdir/ld exception_x86_64_bnd_1.o exception_x86_64_bnd_2.o
- @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_LDFLAGS = $(exception_test_LDFLAGS)
--@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_LDADD = $(exception_x86_64_bnd_test_DEPENDENCIES)
-+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_LDADD = exception_x86_64_bnd_1.o exception_x86_64_bnd_2.o
- @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
- @DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
- all: $(BUILT_SOURCES)
--- 
-1.7.1
-
diff --git a/third_party/binutils/upload.sh b/third_party/binutils/upload.sh
index 5ff10aa..31f1a06 100755
--- a/third_party/binutils/upload.sh
+++ b/third_party/binutils/upload.sh
@@ -61,5 +61,8 @@
 done
 
 echo "Please commit the new .sha1 to the Chromium repository"
-echo ""
 echo "# git commit"
+echo ""
+echo "Make sure goma is updated with the new binutils *before* landing."
+echo " Notify {ukai,yyanagisawa,shinyak}@chromium.org with the .sha1 files"
+echo " and await confirmation."
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js
index b1bdc4c..50dc6149 100644
--- a/third_party/closure_compiler/externs/networking_private.js
+++ b/third_party/closure_compiler/externs/networking_private.js
@@ -109,13 +109,13 @@
 
 /**
  * @typedef {{
- *   AutoConnect: (boolean|undefined),
- *   APN: (!chrome.networkingPrivate.APNProperties|undefined),
- *   Carrier: (string|undefined)
+ *   Name: string,
+ *   Code: string,
+ *   Country: (string|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularConfigProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularProviderProperties
  */
-chrome.networkingPrivate.CellularConfigProperties;
+chrome.networkingPrivate.CellularProviderProperties;
 
 /**
  * @typedef {{
@@ -129,15 +129,25 @@
 
 /**
  * @typedef {{
- *   ActivationState: (!chrome.networkingPrivate.ActivationStateType|undefined),
- *   NetworkTechnology: (string|undefined),
- *   RoamingState: (string|undefined),
- *   SIMPresent: (boolean|undefined),
- *   SignalStrength: (number|undefined)
+ *   CommonName: (string|undefined),
+ *   Locality: (string|undefined),
+ *   Organization: (string|undefined),
+ *   OrganizationalUnit: (string|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularStateProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-IssuerSubjectPattern
  */
-chrome.networkingPrivate.CellularStateProperties;
+chrome.networkingPrivate.IssuerSubjectPattern;
+
+/**
+ * @typedef {{
+ *   EnrollmentURI: (!Array<string>|undefined),
+ *   Issuer: (!chrome.networkingPrivate.IssuerSubjectPattern|undefined),
+ *   IssuerCARef: (!Array<string>|undefined),
+ *   Subject: (!chrome.networkingPrivate.IssuerSubjectPattern|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-CertificatePattern
+ */
+chrome.networkingPrivate.CertificatePattern;
 
 /**
  * @typedef {{
@@ -153,11 +163,34 @@
 
 /**
  * @typedef {{
- *   Authentication: string
+ *   AnonymousIdentity: (string|undefined),
+ *   ClientCertPattern: (!chrome.networkingPrivate.CertificatePattern|undefined),
+ *   ClientCertRef: (string|undefined),
+ *   ClientCertType: (string|undefined),
+ *   Identity: (string|undefined),
+ *   Inner: (string|undefined),
+ *   Outer: string,
+ *   Password: (string|undefined),
+ *   SaveCredentials: (boolean|undefined),
+ *   ServerCARefs: (!Array<string>|undefined),
+ *   UseProactiveKeyCaching: (boolean|undefined),
+ *   UseSystemCAs: (boolean|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-EthernetStateProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-EAPProperties
  */
-chrome.networkingPrivate.EthernetStateProperties;
+chrome.networkingPrivate.EAPProperties;
+
+/**
+ * @typedef {{
+ *   Status: string,
+ *   NetworkId: string,
+ *   Technology: string,
+ *   ShortName: (string|undefined),
+ *   LongName: (string|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-FoundNetworkProperties
+ */
+chrome.networkingPrivate.FoundNetworkProperties;
 
 /**
  * @typedef {{
@@ -174,7 +207,27 @@
 
 /**
  * @typedef {{
- *   AuthenticationType: string
+ *   Password: (string|undefined),
+ *   SaveCredentials: (boolean|undefined),
+ *   Username: (string|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-XAUTHProperties
+ */
+chrome.networkingPrivate.XAUTHProperties;
+
+/**
+ * @typedef {{
+ *   AuthenticationType: string,
+ *   ClientCertPattern: (!chrome.networkingPrivate.CertificatePattern|undefined),
+ *   ClientCertRef: (string|undefined),
+ *   ClientCertType: (string|undefined),
+ *   EAP: (!chrome.networkingPrivate.EAPProperties|undefined),
+ *   Group: (string|undefined),
+ *   IKEVersion: number,
+ *   PSK: (string|undefined),
+ *   SaveCredentials: (boolean|undefined),
+ *   ServerCARefs: (!Array<string>|undefined),
+ *   XAUTH: (!chrome.networkingPrivate.XAUTHProperties|undefined)
  * }}
  * @see https://developer.chrome.com/extensions/networkingPrivate#type-IPSecProperties
  */
@@ -182,6 +235,27 @@
 
 /**
  * @typedef {{
+ *   LcpEchoDisabled: (boolean|undefined),
+ *   Password: (string|undefined),
+ *   SaveCredentials: (boolean|undefined),
+ *   Username: (string|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-L2TPProperties
+ */
+chrome.networkingPrivate.L2TPProperties;
+
+/**
+ * @typedef {{
+ *   Method: string,
+ *   PostData: (string|undefined),
+ *   Url: (string|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-PaymentPortal
+ */
+chrome.networkingPrivate.PaymentPortal;
+
+/**
+ * @typedef {{
  *   Host: string,
  *   Port: number
  * }}
@@ -213,10 +287,49 @@
 
 /**
  * @typedef {{
+ *   Name: (string|undefined),
+ *   Type: (string|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-VerifyX509
+ */
+chrome.networkingPrivate.VerifyX509;
+
+/**
+ * @typedef {{
+ *   Auth: (string|undefined),
+ *   AuthRetry: (string|undefined),
+ *   AuthNoCache: (boolean|undefined),
+ *   Cipher: (string|undefined),
+ *   ClientCertRef: (string|undefined),
+ *   ClientCertPattern: (!chrome.networkingPrivate.CertificatePattern|undefined),
+ *   ClientCertType: (string|undefined),
+ *   CompLZO: (string|undefined),
+ *   CompNoAdapt: (boolean|undefined),
+ *   IgnoreDefaultRoute: (boolean|undefined),
+ *   KeyDirection: (string|undefined),
+ *   NsCertType: (string|undefined),
  *   OTP: (string|undefined),
  *   Password: (string|undefined),
+ *   Port: (number|undefined),
+ *   Proto: (string|undefined),
+ *   PushPeerInfo: (string|undefined),
+ *   RemoteCertEKU: (string|undefined),
+ *   RemoteCertKU: (!Array<string>|undefined),
+ *   RemoteCertTLS: (string|undefined),
+ *   RenegSec: (number|undefined),
+ *   SaveCredentials: (boolean|undefined),
+ *   ServerCARefs: (!Array<string>|undefined),
+ *   ServerCertRef: (string|undefined),
+ *   ServerPollTimeout: (number|undefined),
+ *   Shaper: (number|undefined),
+ *   StaticChallenge: (string|undefined),
+ *   TLSAuthContents: (string|undefined),
+ *   TLSRemote: (string|undefined),
  *   UserAuthenticationType: (string|undefined),
- *   Username: (string|undefined)
+ *   Username: (string|undefined),
+ *   Verb: (string|undefined),
+ *   VerifyHash: (string|undefined),
+ *   VerifyX509: (!chrome.networkingPrivate.VerifyX509|undefined)
  * }}
  * @see https://developer.chrome.com/extensions/networkingPrivate#type-OpenVPNProperties
  */
@@ -224,6 +337,16 @@
 
 /**
  * @typedef {{
+ *   LockType: string,
+ *   LockEnabled: boolean,
+ *   RetriesLeft: (number|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-SIMLockStatus
+ */
+chrome.networkingPrivate.SIMLockStatus;
+
+/**
+ * @typedef {{
  *   ExtensionID: string,
  *   ProviderName: (string|undefined)
  * }}
@@ -234,14 +357,82 @@
 /**
  * @typedef {{
  *   AutoConnect: (boolean|undefined),
+ *   APN: (!chrome.networkingPrivate.APNProperties|undefined),
+ *   APNList: (!Array<!chrome.networkingPrivate.APNProperties>|undefined),
+ *   ActivationType: (string|undefined),
+ *   ActivationState: (!chrome.networkingPrivate.ActivationStateType|undefined),
+ *   AllowRoaming: (boolean|undefined),
+ *   Carrier: (string|undefined),
+ *   ESN: (string|undefined),
+ *   Family: (string|undefined),
+ *   FirmwareRevision: (string|undefined),
+ *   FoundNetworks: (!Array<!chrome.networkingPrivate.FoundNetworkProperties>|undefined),
+ *   HardwareRevision: (string|undefined),
+ *   HomeProvider: (!chrome.networkingPrivate.CellularProviderProperties|undefined),
+ *   ICCID: (string|undefined),
+ *   IMEI: (string|undefined),
+ *   LastGoodAPN: (!chrome.networkingPrivate.APNProperties|undefined),
+ *   Manufacturer: (string|undefined),
+ *   MDN: (string|undefined),
+ *   MEID: (string|undefined),
+ *   MIN: (string|undefined),
+ *   ModelID: (string|undefined),
+ *   NetworkTechnology: (string|undefined),
+ *   PaymentPortal: (!chrome.networkingPrivate.PaymentPortal|undefined),
+ *   PRLVersion: (number|undefined),
+ *   RoamingState: (string|undefined),
+ *   ServingOperator: (!chrome.networkingPrivate.CellularProviderProperties|undefined),
+ *   SIMLockStatus: (!chrome.networkingPrivate.SIMLockStatus|undefined),
+ *   SIMPresent: (boolean|undefined),
+ *   SupportNetworkScan: (boolean|undefined),
+ *   SupportedCarriers: (!Array<string>|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularProperties
+ */
+chrome.networkingPrivate.CellularProperties;
+
+/**
+ * @typedef {{
+ *   ActivationState: (!chrome.networkingPrivate.ActivationStateType|undefined),
+ *   NetworkTechnology: (string|undefined),
+ *   RoamingState: (string|undefined),
+ *   SIMPresent: (boolean|undefined),
+ *   SignalStrength: (number|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-CellularStateProperties
+ */
+chrome.networkingPrivate.CellularStateProperties;
+
+/**
+ * @typedef {{
+ *   Authentication: (string|undefined),
+ *   EAP: (!chrome.networkingPrivate.EAPProperties|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-EthernetProperties
+ */
+chrome.networkingPrivate.EthernetProperties;
+
+/**
+ * @typedef {{
+ *   Authentication: string
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-EthernetStateProperties
+ */
+chrome.networkingPrivate.EthernetStateProperties;
+
+/**
+ * @typedef {{
+ *   AutoConnect: (boolean|undefined),
  *   Host: (string|undefined),
+ *   IPsec: (!chrome.networkingPrivate.IPSecProperties|undefined),
+ *   L2TP: (!chrome.networkingPrivate.L2TPProperties|undefined),
  *   OpenVPN: (!chrome.networkingPrivate.OpenVPNProperties|undefined),
  *   ThirdPartyVPN: (!chrome.networkingPrivate.ThirdPartyVPNProperties|undefined),
  *   Type: (string|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-VPNConfigProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-VPNProperties
  */
-chrome.networkingPrivate.VPNConfigProperties;
+chrome.networkingPrivate.VPNProperties;
 
 /**
  * @typedef {{
@@ -255,16 +446,23 @@
 
 /**
  * @typedef {{
+ *   AllowGatewayARPPolling: (boolean|undefined),
  *   AutoConnect: (boolean|undefined),
+ *   BSSID: (string|undefined),
+ *   EAP: (!chrome.networkingPrivate.EAPProperties|undefined),
+ *   Frequency: (number|undefined),
+ *   FrequencyList: (!Array<number>|undefined),
  *   HexSSID: (string|undefined),
  *   HiddenSSID: (boolean|undefined),
  *   Passphrase: (string|undefined),
+ *   RoamThreshold: (number|undefined),
  *   SSID: (string|undefined),
- *   Security: (string|undefined)
+ *   Security: (string|undefined),
+ *   SignalStrength: (number|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-WiFiConfigProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-WiFiProperties
  */
-chrome.networkingPrivate.WiFiConfigProperties;
+chrome.networkingPrivate.WiFiProperties;
 
 /**
  * @typedef {{
@@ -277,11 +475,13 @@
 
 /**
  * @typedef {{
- *   AutoConnect: (boolean|undefined)
+ *   AutoConnect: (boolean|undefined),
+ *   EAP: (!chrome.networkingPrivate.EAPProperties|undefined),
+ *   SignalStrength: (number|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/networkingPrivate#type-WiMaxConfigProperties
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-WiMAXProperties
  */
-chrome.networkingPrivate.WiMaxConfigProperties;
+chrome.networkingPrivate.WiMAXProperties;
 
 /**
  * @typedef {{
@@ -293,7 +493,8 @@
 
 /**
  * @typedef {{
- *   Cellular: (!chrome.networkingPrivate.CellularConfigProperties|undefined),
+ *   Cellular: (!chrome.networkingPrivate.CellularProperties|undefined),
+ *   Ethernet: (!chrome.networkingPrivate.EthernetProperties|undefined),
  *   GUID: (string|undefined),
  *   IPAddressConfigType: (!chrome.networkingPrivate.IPConfigType|undefined),
  *   Name: (string|undefined),
@@ -302,9 +503,9 @@
  *   ProxySettings: (!chrome.networkingPrivate.ProxySettings|undefined),
  *   StaticIPConfig: (!chrome.networkingPrivate.IPConfigProperties|undefined),
  *   Type: (!chrome.networkingPrivate.NetworkType|undefined),
- *   VPN: (!chrome.networkingPrivate.VPNConfigProperties|undefined),
- *   WiFi: (!chrome.networkingPrivate.WiFiConfigProperties|undefined),
- *   WiMAX: (!chrome.networkingPrivate.WiMaxConfigProperties|undefined)
+ *   VPN: (!chrome.networkingPrivate.VPNProperties|undefined),
+ *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
+ *   WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
  * }}
  * @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkConfigProperties
  */
@@ -332,6 +533,34 @@
 
 /**
  * @typedef {{
+ *   Cellular: (!chrome.networkingPrivate.CellularProperties|undefined),
+ *   Connectable: (boolean|undefined),
+ *   ConnectionState: (!chrome.networkingPrivate.ConnectionStateType|undefined),
+ *   ErrorState: (string|undefined),
+ *   Ethernet: (!chrome.networkingPrivate.EthernetProperties|undefined),
+ *   GUID: string,
+ *   IPAddressConfigType: (!chrome.networkingPrivate.IPConfigType|undefined),
+ *   IPConfigs: (!Array<!chrome.networkingPrivate.IPConfigProperties>|undefined),
+ *   MacAddress: (string|undefined),
+ *   Name: (string|undefined),
+ *   NameServersConfigType: (!chrome.networkingPrivate.IPConfigType|undefined),
+ *   Priority: (number|undefined),
+ *   ProxySettings: (!chrome.networkingPrivate.ProxySettings|undefined),
+ *   RestrictedConnectivity: (boolean|undefined),
+ *   StaticIPConfig: (!chrome.networkingPrivate.IPConfigProperties|undefined),
+ *   SavedIPConfig: (!chrome.networkingPrivate.IPConfigProperties|undefined),
+ *   Source: (string|undefined),
+ *   Type: !chrome.networkingPrivate.NetworkType,
+ *   VPN: (!chrome.networkingPrivate.VPNProperties|undefined),
+ *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
+ *   WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
+ * }}
+ * @see https://developer.chrome.com/extensions/networkingPrivate#type-NetworkProperties
+ */
+chrome.networkingPrivate.NetworkProperties;
+
+/**
+ * @typedef {{
  *   certificate: string,
  *   intermediateCertificates: (!Array<string>|undefined),
  *   publicKey: string,
@@ -360,8 +589,8 @@
  * Gets all the properties of the network with id networkGuid. Includes all
  * properties of the network (read-only and read/write values).
  * @param {string} networkGuid The GUID of the network to get properties for.
- * @param {function(Object):void} callback Called with the network properties
- *     when received.
+ * @param {function(!chrome.networkingPrivate.NetworkProperties):void} callback
+ *     Called with the network properties when received.
  * @see https://developer.chrome.com/extensions/networkingPrivate#method-getProperties
  */
 chrome.networkingPrivate.getProperties = function(networkGuid, callback) {};
@@ -660,3 +889,5 @@
  * @see https://developer.chrome.com/extensions/networkingPrivate#event-onPortalDetectionCompleted
  */
 chrome.networkingPrivate.onPortalDetectionCompleted;
+
+
diff --git a/third_party/gif_player/BUILD.gn b/third_party/gif_player/BUILD.gn
index f23f1ef..ab0cd6f2 100644
--- a/third_party/gif_player/BUILD.gn
+++ b/third_party/gif_player/BUILD.gn
@@ -10,5 +10,4 @@
     "src/jp/tomorrowkey/android/gifplayer/BaseGifImage.java",
   ]
   run_findbugs = false
-  assert(!run_findbugs)
 }
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn
index d6b5575a..f5fc4173 100644
--- a/third_party/libjingle/BUILD.gn
+++ b/third_party/libjingle/BUILD.gn
@@ -27,7 +27,7 @@
 
   include_dirs = [
     "overrides",
-    "../../third_party/webrtc/overrides",
+    "../../third_party/webrtc_overrides",
     "source",
     "../../testing/gtest/include",
     "../../third_party",
@@ -46,7 +46,7 @@
 # From third_party/libjingle/libjingle.gyp's target_defaults.
 config("jingle_public_configs") {
   include_dirs = [
-    "../../third_party/webrtc/overrides",
+    "../../third_party/webrtc_overrides",
     "overrides",
     "source",
     "../../testing/gtest/include",
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index 994a67a..e97d5dc0 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: 10081
+Revision: 10116
 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 06c8723..2e52910 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -46,7 +46,7 @@
     },
     'include_dirs': [
       './overrides',
-      '../../third_party/webrtc/overrides',
+      '../../third_party/webrtc_overrides',
       './<(libjingle_source)',
       '../..',
       '../../testing/gtest/include',
@@ -66,7 +66,7 @@
     ],
     'direct_dependent_settings': {
       'include_dirs': [
-        '../../third_party/webrtc/overrides',
+        '../../third_party/webrtc_overrides',
         './overrides',
         './<(libjingle_source)',
         '../..',
diff --git a/third_party/libjingle/libjingle_nacl.gyp b/third_party/libjingle/libjingle_nacl.gyp
index e8d8a2e..d2d7eec4 100644
--- a/third_party/libjingle/libjingle_nacl.gyp
+++ b/third_party/libjingle/libjingle_nacl.gyp
@@ -271,7 +271,7 @@
         'include_dirs': [
           './overrides',
           './<(libjingle_source)',
-          '../../third_party/webrtc/overrides',
+          '../../third_party/webrtc_overrides',
           '../../third_party',
           '../../third_party/webrtc',
         ],
diff --git a/third_party/libjingle/overrides/DEPS b/third_party/libjingle/overrides/DEPS
index e6e8c64..ca6ded77 100644
--- a/third_party/libjingle/overrides/DEPS
+++ b/third_party/libjingle/overrides/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   '+base',
   '+third_party/webrtc',
+  '+third_party/webrtc_overrides',
 ]
diff --git a/third_party/libjingle/overrides/init_webrtc.cc b/third_party/libjingle/overrides/init_webrtc.cc
index b9a8901c9..c9ac4ca 100644
--- a/third_party/libjingle/overrides/init_webrtc.cc
+++ b/third_party/libjingle/overrides/init_webrtc.cc
@@ -13,7 +13,7 @@
 #include "base/native_library.h"
 #include "base/path_service.h"
 #include "base/trace_event/trace_event.h"
-#include "third_party/webrtc/overrides/webrtc/base/logging.h"
+#include "third_party/webrtc_overrides/webrtc/base/logging.h"
 #include "third_party/webrtc/system_wrappers/interface/cpu_info.h"
 #include "third_party/webrtc/system_wrappers/interface/event_tracer.h"
 
diff --git a/third_party/libpng/LICENSE b/third_party/libpng/LICENSE
index a975864..0e80708 100644
--- a/third_party/libpng/LICENSE
+++ b/third_party/libpng/LICENSE
@@ -12,8 +12,8 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.2.45, July 7, 2011, are
-Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are
+libpng versions 1.2.6, August 15, 2004, through 1.2.52, November 20, 2014, are
+Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
 
@@ -110,4 +110,4 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-July 7, 2011
+November 20, 2014
diff --git a/third_party/libpng/README b/third_party/libpng/README
index 8d017db..4b49627b 100644
--- a/third_party/libpng/README
+++ b/third_party/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.2.45 - July 7, 2011 (shared library 12.0)
+README for libpng version 1.2.52 - November 20, 2014 (shared library 12.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
@@ -93,6 +93,12 @@
 at GO GRAPHSUP.  If you can't find it in any of those places,
 e-mail me, and I'll help you find it.
 
+I am not a lawyer, but I believe that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because it
+is open source, publicly available software, that does not contain any
+encryption software.  See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
+
 If you have any code changes, requests, problems, etc., please e-mail
 them to me.  Also, I'd appreciate any make files or project files,
 and any modifications you needed to make to get libpng to compile,
@@ -129,7 +135,7 @@
 to others, if necessary.
 
 Please do not send suggestions on how to change PNG.  We have
-been discussing PNG for twelve years now, and it is official and
+been discussing PNG for nineteen years now, and it is official and
 finished.  If you have suggestions for libpng, however, I'll
 gladly listen.  Even if your suggestion is not used immediately,
 it may be used later.
@@ -174,8 +180,7 @@
        gregbook         =>  source code for PNG reading and writing, from
                             Greg Roelofs' "PNG: The Definitive Guide",
                             O'Reilly, 1999
-       msvctest     =>  Builds and runs pngtest using a MSVC workspace
-       pngminim     =>  Simple pnm2pngm and png2pnmm programs
+       pngminim     =>  Minimal pnm2pngm and png2pnmm programs
        pngminus     =>  Simple pnm2png and png2pnm programs
        pngsuite     =>  Test images
        visupng      =>  Contains a MSVC workspace for VisualPng
@@ -184,11 +189,14 @@
        beos             =>  Contains a Beos workspace for building libpng
        c5builder        =>  Contains a Borland workspace for building
                             libpng and zlib
+       MacOSX           =>  Contains a MacOSX workspace for building libpng
        netware.txt      =>  Contains instructions for downloading a set
                             of project files for building libpng and
                             zlib on Netware.
        visualc6         =>  Contains a Microsoft Visual C++ (MSVC)
                             workspace for building libpng and zlib
+       visualc71        =>  Contains a Microsoft Visual C++ (MSVC)
+                            workspace for building libpng and zlib
        wince.txt        =>  Contains instructions for downloading a
                             Microsoft Visual C++ (Windows CD Toolkit)
                             workspace for building libpng and zlib on
@@ -199,11 +207,11 @@
        makefile.std     =>  Generic UNIX makefile (cc, creates static
                             libpng.a)
        makefile.elf     =>  Linux/ELF gcc makefile symbol versioning,
-                            creates libpng12.so.0.1.2.45)
+                            creates libpng12.so.0.1.2.52)
        makefile.linux   =>  Linux/ELF makefile (gcc, creates
-                            libpng12.so.0.1.2.45)
+                            libpng12.so.0.1.2.52)
        makefile.gcmmx   =>  Linux/ELF makefile (gcc, creates
-                            libpng12.so.0.1.2.45, previously
+                            libpng12.so.0.1.2.52, previously
                             used assembler code tuned for Intel MMX
                             platform)
        makefile.gcc     =>  Generic makefile (gcc, creates static
@@ -228,12 +236,12 @@
        makefile.openbsd =>  OpenBSD makefile
        makefile.sgi     =>  Silicon Graphics IRIX (cc, creates static lib)
        makefile.sggcc   =>  Silicon Graphics
-                            (gcc, creates libpng12.so.0.1.2.45)
+                            (gcc, creates libpng12.so.0.1.2.52)
        makefile.sunos   =>  Sun makefile
        makefile.solaris =>  Solaris 2.X makefile
-                            (gcc, creates libpng12.so.0.1.2.45)
+                            (gcc, creates libpng12.so.0.1.2.52)
        makefile.so9     =>  Solaris 9 makefile
-                            (gcc, creates libpng12.so.0.1.2.45)
+                            (gcc, creates libpng12.so.0.1.2.52)
        makefile.32sunu  =>  Sun Ultra 32-bit makefile
        makefile.64sunu  =>  Sun Ultra 64-bit makefile
        makefile.sco     =>  For SCO OSr5  ELF and Unixware 7 with Native cc
diff --git a/third_party/libpng/README.chromium b/third_party/libpng/README.chromium
index 391a25cd..1b07c78c 100644
--- a/third_party/libpng/README.chromium
+++ b/third_party/libpng/README.chromium
@@ -1,6 +1,6 @@
 Name: libpng
 URL: http://libpng.org/
-Version: 1.2.45
+Version: 1.2.52
 Security Critical: yes
 License: libpng license
 License Android Compatible: yes
@@ -10,10 +10,8 @@
 called mozpngconf.h, which was copied from Mozilla and modified by Apple (hence
 the wk_* names).
 
-Updated to 1.2.45, no changes to the source files but all unneeded files
+Updated to 1.2.52, no changes to the source files but all unneeded files
 stripped.
 
-- One custom patch for bug 112822, to be sent upstream.
-- Also a signedness condition from upstream relating to the above, bug 116162.
 - Unset PNG_NO_READ_PACK on Android in pngusr.h, required by freetype to support
   color glyphs.
diff --git a/third_party/libpng/png.c b/third_party/libpng/png.c
index babad71..2ebb6f7 100644
--- a/third_party/libpng/png.c
+++ b/third_party/libpng/png.c
@@ -1,8 +1,8 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -17,7 +17,7 @@
 #include "png.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef version_1_2_45 Your_png_h_is_not_version_1_2_45;
+typedef version_1_2_52 Your_png_h_is_not_version_1_2_52;
 
 /* Version information for C files.  This had better match the version
  * string defined in png.h.
@@ -718,20 +718,20 @@
 png_charp PNGAPI
 png_get_copyright(png_structp png_ptr)
 {
-   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
 #ifdef PNG_STRING_COPYRIGHT
       return PNG_STRING_COPYRIGHT
 #else
 #ifdef __STDC__
    return ((png_charp) PNG_STRING_NEWLINE \
-     "libpng version 1.2.45 - July 7, 2011" PNG_STRING_NEWLINE \
-     "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+     "libpng version 1.2.52 - November 20, 2014" PNG_STRING_NEWLINE \
+     "Copyright (c) 1998-2014 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE);
 #else
-      return ((png_charp) "libpng version 1.2.45 - July 7, 2011\
-      Copyright (c) 1998-2010 Glenn Randers-Pehrson\
+      return ((png_charp) "libpng version 1.2.52 - November 20, 2014\
+      Copyright (c) 1998-2014 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
 #endif
@@ -750,7 +750,7 @@
 png_get_libpng_ver(png_structp png_ptr)
 {
    /* Version of *.c files used when building libpng */
-   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
    return ((png_charp) PNG_LIBPNG_VER_STRING);
 }
 
@@ -758,7 +758,7 @@
 png_get_header_ver(png_structp png_ptr)
 {
    /* Version of *.h files used when building libpng */
-   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
    return ((png_charp) PNG_LIBPNG_VER_STRING);
 }
 
@@ -766,7 +766,7 @@
 png_get_header_version(png_structp png_ptr)
 {
    /* Returns longer string containing both version and date */
-   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+   PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
 #ifdef __STDC__
    return ((png_charp) PNG_HEADER_VERSION_STRING
 #ifndef PNG_READ_SUPPORTED
@@ -1009,14 +1009,6 @@
       error = 1;
    }
 
-   if ( width > (PNG_UINT_32_MAX
-                 >> 3)      /* 8-byte RGBA pixels */
-                 - 64       /* bigrowbuf hack */
-                 - 1        /* filter byte */
-                 - 7*8      /* rounding of width to multiple of 8 pixels */
-                 - 8)       /* extra max_pixel_depth pad */
-      png_warning(png_ptr, "Width is too large for libpng to process pixels");
-
    /* Check other values */
    if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
        bit_depth != 8 && bit_depth != 16)
diff --git a/third_party/libpng/png.h b/third_party/libpng/png.h
index 29dc52b4..ed9e429 100644
--- a/third_party/libpng/png.h
+++ b/third_party/libpng/png.h
@@ -1,7 +1,7 @@
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.2.45 - July 7, 2011
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * libpng version 1.2.52 - November 20, 2014
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -10,7 +10,7 @@
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.2.45 - July 7, 2011: Glenn
+ *  libpng versions 0.97, January 1998, through 1.2.52 - November 20, 2014: Glenn
  *  See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -263,10 +263,35 @@
  *    1.2.44rc01-03           13    10244  12.so.0.44[.0]
  *    1.2.44                  13    10244  12.so.0.44[.0]
  *    1.2.45beta01-03         13    10245  12.so.0.45[.0]
- *    1.0.55rc01              13    10055  10.so.0.55[.0]
+ *    1.0.55rc01              10    10055  10.so.0.55[.0]
  *    1.2.45rc01              13    10245  12.so.0.45[.0]
- *    1.0.55                  13    10055  10.so.0.55[.0]
+ *    1.0.55                  10    10055  10.so.0.55[.0]
  *    1.2.45                  13    10245  12.so.0.45[.0]
+ *    1.2.46rc01-02           13    10246  12.so.0.46[.0]
+ *    1.0.56                  10    10056  10.so.0.56[.0]
+ *    1.2.46                  13    10246  12.so.0.46[.0]
+ *    1.2.47beta01            13    10247  12.so.0.47[.0]
+ *    1.2.47rc01              13    10247  12.so.0.47[.0]
+ *    1.0.57rc01              10    10057  10.so.0.57[.0]
+ *    1.2.47                  13    10247  12.so.0.47[.0]
+ *    1.0.57                  10    10057  10.so.0.57[.0]
+ *    1.2.48beta01            13    10248  12.so.0.48[.0]
+ *    1.2.48rc01-02           13    10248  12.so.0.48[.0]
+ *    1.0.58                  10    10058  10.so.0.58[.0]
+ *    1.2.48                  13    10248  12.so.0.48[.0]
+ *    1.2.49rc01              13    10249  12.so.0.49[.0]
+ *    1.0.59                  10    10059  10.so.0.59[.0]
+ *    1.2.49                  13    10249  12.so.0.49[.0]
+ *    1.0.60                  10    10060  10.so.0.60[.0]
+ *    1.2.50                  13    10250  12.so.0.50[.0]
+ *    1.2.51beta01-05         13    10251  12.so.0.51[.0]
+ *    1.2.51rc01-04           13    10251  12.so.0.51[.0]
+ *    1.0.61                  10    10061  10.so.0.61[.0]
+ *    1.2.51                  13    10251  12.so.0.51[.0]
+ *    1.2.52beta01            13    10252  12.so.0.52[.0]
+ *    1.2.52rc01-02           13    10252  12.so.0.52[.0]
+ *    1.0.62                  10    10062  10.so.0.62[.0]
+ *    1.2.52                  13    10252  12.so.0.52[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
@@ -298,8 +323,8 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.2.45, July 7, 2011, are
- * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
+ * libpng versions 1.2.6, August 15, 2004, through 1.2.52, November 20, 2014, are
+ * Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
  *
@@ -410,13 +435,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    July 7, 2011
+ *    November 20, 2014
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.2.45 are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.2.52 are Y2K compliant.  It is my belief that earlier
  *    versions were also Y2K compliant.
  *
  *    Libpng only has three year fields.  One is a 2-byte unsigned integer
@@ -472,9 +497,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.2.45"
+#define PNG_LIBPNG_VER_STRING "1.2.52"
 #define PNG_HEADER_VERSION_STRING \
-   " libpng version 1.2.45 - July 7, 2011\n"
+   " libpng version 1.2.52 - November 20, 2014\n"
 
 #define PNG_LIBPNG_VER_SONUM   0
 #define PNG_LIBPNG_VER_DLLNUM  13
@@ -482,7 +507,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   2
-#define PNG_LIBPNG_VER_RELEASE 45
+#define PNG_LIBPNG_VER_RELEASE 52
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
@@ -512,7 +537,7 @@
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10245 /* 1.2.45 */
+#define PNG_LIBPNG_VER 10252 /* 1.2.52 */
 
 #ifndef PNG_VERSION_INFO_ONLY
 /* Include the compression library's header */
@@ -1552,7 +1577,7 @@
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef png_structp version_1_2_45;
+typedef png_structp version_1_2_52;
 
 typedef png_struct FAR * FAR * png_structpp;
 
@@ -2639,7 +2664,7 @@
 #      define png_debug(l,m) \
        { \
        int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
          (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
        }
 #    endif
@@ -2647,7 +2672,7 @@
 #      define png_debug1(l,m,p1) \
        { \
        int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
          (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
        }
 #    endif
@@ -2655,7 +2680,7 @@
 #      define png_debug2(l,m,p1,p2) \
        { \
        int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
          (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
        }
 #    endif
diff --git a/third_party/libpng/pngconf.h b/third_party/libpng/pngconf.h
index 6928241..008142e 100644
--- a/third_party/libpng/pngconf.h
+++ b/third_party/libpng/pngconf.h
@@ -1,8 +1,8 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.2.45 - July 7, 2011
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * libpng version 1.2.52 - November 20, 2014
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -86,6 +86,18 @@
 #endif
 /* End of material added at libpng-1.2.19/1.2.21 */
 
+/* Added at libpng-1.2.51 (ported from 1.4.6) */
+#ifndef PNG_UNUSED
+/* Unused formal parameter warnings are silenced using the following macro
+ * which is expected to have no bad effects on performance (optimizing
+ * compilers will probably remove it entirely).  Note that if you replace
+ * it with something other than whitespace, you must include the terminating
+ * semicolon.
+ */
+#  define PNG_UNUSED(param) (void)param;
+#endif
+/* End of material added to libpng-1.4.6 */
+
 /* This is the size of the compression buffer, and thus the size of
  * an IDAT chunk.  Make this whatever size you feel is best for your
  * machine.  One of these will be allocated per png_struct.  When this
@@ -868,7 +880,7 @@
  * how large, set these two limits to 0.
  */
 #ifndef PNG_USER_CHUNK_CACHE_MAX
-#  define PNG_USER_CHUNK_CACHE_MAX 0
+#  define PNG_USER_CHUNK_CACHE_MAX 32765
 #endif
 
 /* Added at libpng-1.2.43 */
diff --git a/third_party/libpng/pngerror.c b/third_party/libpng/pngerror.c
index 025d52e..d8e7928 100644
--- a/third_party/libpng/pngerror.c
+++ b/third_party/libpng/pngerror.c
@@ -1,8 +1,8 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.2.45 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -300,7 +300,7 @@
    /* Here if not setjmp support or if png_ptr is null. */
    PNG_ABORT();
 #ifndef PNG_CONSOLE_IO_SUPPORTED
-   error_message = error_message; /* Make compiler happy */
+   PNG_UNUSED(error_message) /* Make compiler happy */
 #endif
 }
 
@@ -346,9 +346,9 @@
      fprintf(stderr, PNG_STRING_NEWLINE);
    }
 #else
-   warning_message = warning_message; /* Make compiler happy */
+   PNG_UNUSED(warning_message) /* Make compiler happy */
 #endif
-   png_ptr = png_ptr; /* Make compiler happy */
+   PNG_UNUSED(png_ptr) /* Make compiler happy */
 }
 #endif /* PNG_WARNINGS_SUPPORTED */
 
diff --git a/third_party/libpng/pnggccrd.c b/third_party/libpng/pnggccrd.c
index 78b8a7e..7eb7f67 100644
--- a/third_party/libpng/pnggccrd.c
+++ b/third_party/libpng/pnggccrd.c
@@ -1,6 +1,16 @@
-/* pnggccrd.c was removed from libpng-1.2.20. */
-
-/* This code snippet is for use by configure's compilation test. */
+/* pnggccrd.c
+ *
+ * Last changed in libpng 1.2.48 [March 8, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This code snippet is for use by configure's compilation test. Most of the
+ * remainder of the file was removed from libpng-1.2.20, and all of the
+ * assembler code was removed from libpng-1.2.48.
+ */
 
 #if (!defined _MSC_VER) && \
     defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
@@ -8,96 +18,9 @@
 
 int PNGAPI png_dummy_mmx_support(void);
 
-static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested
-
-int PNGAPI
-png_dummy_mmx_support(void) __attribute__((noinline));
-
-int PNGAPI
-png_dummy_mmx_support(void)
+int PNGAPI png_dummy_mmx_support(void)
 {
-   int result;
-#ifdef PNG_MMX_CODE_SUPPORTED  // superfluous, but what the heck
-    __asm__ __volatile__ (
-#ifdef __x86_64__
-        "pushq %%rbx          \n\t"  // rbx gets clobbered by CPUID instruction
-        "pushq %%rcx          \n\t"  // so does rcx...
-        "pushq %%rdx          \n\t"  // ...and rdx (but rcx & rdx safe on Linux)
-        "pushfq               \n\t"  // save Eflag to stack
-        "popq %%rax           \n\t"  // get Eflag from stack into rax
-        "movq %%rax, %%rcx    \n\t"  // make another copy of Eflag in rcx
-        "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
-        "pushq %%rax          \n\t"  // save modified Eflag back to stack
-        "popfq                \n\t"  // restore modified value to Eflag reg
-        "pushfq               \n\t"  // save Eflag to stack
-        "popq %%rax           \n\t"  // get Eflag from stack
-        "pushq %%rcx          \n\t"  // save original Eflag to stack
-        "popfq                \n\t"  // restore original Eflag
-#else
-        "pushl %%ebx          \n\t"  // ebx gets clobbered by CPUID instruction
-        "pushl %%ecx          \n\t"  // so does ecx...
-        "pushl %%edx          \n\t"  // ...and edx (but ecx & edx safe on Linux)
-        "pushfl               \n\t"  // save Eflag to stack
-        "popl %%eax           \n\t"  // get Eflag from stack into eax
-        "movl %%eax, %%ecx    \n\t"  // make another copy of Eflag in ecx
-        "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
-        "pushl %%eax          \n\t"  // save modified Eflag back to stack
-        "popfl                \n\t"  // restore modified value to Eflag reg
-        "pushfl               \n\t"  // save Eflag to stack
-        "popl %%eax           \n\t"  // get Eflag from stack
-        "pushl %%ecx          \n\t"  // save original Eflag to stack
-        "popfl                \n\t"  // restore original Eflag
-#endif
-        "xorl %%ecx, %%eax    \n\t"  // compare new Eflag with original Eflag
-        "jz 0f                \n\t"  // if same, CPUID instr. is not supported
-
-        "xorl %%eax, %%eax    \n\t"  // set eax to zero
-//      ".byte  0x0f, 0xa2    \n\t"  // CPUID instruction (two-byte opcode)
-        "cpuid                \n\t"  // get the CPU identification info
-        "cmpl $1, %%eax       \n\t"  // make sure eax return non-zero value
-        "jl 0f                \n\t"  // if eax is zero, MMX is not supported
-
-        "xorl %%eax, %%eax    \n\t"  // set eax to zero and...
-        "incl %%eax           \n\t"  // ...increment eax to 1.  This pair is
-                                     // faster than the instruction "mov eax, 1"
-        "cpuid                \n\t"  // get the CPU identification info again
-        "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
-        "cmpl $0, %%edx       \n\t"  // 0 = MMX not supported
-        "jz 0f                \n\t"  // non-zero = yes, MMX IS supported
-
-        "movl $1, %%eax       \n\t"  // set return value to 1
-        "jmp  1f              \n\t"  // DONE:  have MMX support
-
-    "0:                       \n\t"  // .NOT_SUPPORTED: target label for jump instructions
-        "movl $0, %%eax       \n\t"  // set return value to 0
-    "1:                       \n\t"  // .RETURN: target label for jump instructions
-#ifdef __x86_64__
-        "popq %%rdx           \n\t"  // restore rdx
-        "popq %%rcx           \n\t"  // restore rcx
-        "popq %%rbx           \n\t"  // restore rbx
-#else
-        "popl %%edx           \n\t"  // restore edx
-        "popl %%ecx           \n\t"  // restore ecx
-        "popl %%ebx           \n\t"  // restore ebx
-#endif
-
-//      "ret                  \n\t"  // DONE:  no MMX support
-                                     // (fall through to standard C "ret")
-
-        : "=a" (result)              // output list
-
-        :                            // any variables used on input (none)
-
-                                     // no clobber list
-//      , "%ebx", "%ecx", "%edx"     // GRR:  we handle these manually
-//      , "memory"   // if write to a variable gcc thought was in a reg
-//      , "cc"       // "condition codes" (flag bits)
-    );
-    _mmx_supported = result;
-#else
-    _mmx_supported = 0;
-#endif /* PNG_MMX_CODE_SUPPORTED */
-
-    return _mmx_supported;
+     /* 0: no MMX; 1: MMX supported; 2: not tested */
+     return 2;
 }
 #endif
diff --git a/third_party/libpng/pngget.c b/third_party/libpng/pngget.c
index d397329..c5d6543 100644
--- a/third_party/libpng/pngget.c
+++ b/third_party/libpng/pngget.c
@@ -1,8 +1,8 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -893,7 +893,7 @@
 png_get_asm_flagmask (int flag_select)
 {
     /* Obsolete, to be removed from libpng-1.4.0 */
-    flag_select=flag_select;
+    PNG_UNUSED(flag_select)
     return 0L;
 }
 
@@ -903,7 +903,7 @@
 png_get_mmx_flagmask (int flag_select, int *compilerID)
 {
     /* Obsolete, to be removed from libpng-1.4.0 */
-    flag_select=flag_select;
+    PNG_UNUSED(flag_select)
     *compilerID = -1;   /* unknown (i.e., no asm/MMX code compiled) */
     return 0L;
 }
diff --git a/third_party/libpng/pngpread.c b/third_party/libpng/pngpread.c
index d066944..5af209d 100644
--- a/third_party/libpng/pngpread.c
+++ b/third_party/libpng/pngpread.c
@@ -71,30 +71,6 @@
          break;
       }
 
-#ifdef PNG_READ_tEXt_SUPPORTED
-      case PNG_READ_tEXt_MODE:
-      {
-         png_push_read_tEXt(png_ptr, info_ptr);
-         break;
-      }
-
-#endif
-#ifdef PNG_READ_zTXt_SUPPORTED
-      case PNG_READ_zTXt_MODE:
-      {
-         png_push_read_zTXt(png_ptr, info_ptr);
-         break;
-      }
-
-#endif
-#ifdef PNG_READ_iTXt_SUPPORTED
-      case PNG_READ_iTXt_MODE:
-      {
-         png_push_read_iTXt(png_ptr, info_ptr);
-         break;
-      }
-
-#endif
       case PNG_SKIP_MODE:
       {
          png_push_crc_finish(png_ptr);
@@ -529,7 +505,7 @@
          return;
       }
 
-      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
    }
 
 #endif
@@ -542,7 +518,7 @@
          return;
       }
 
-      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
    }
 
 #endif
@@ -555,7 +531,7 @@
          return;
       }
 
-      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
    }
 
 #endif
@@ -566,7 +542,7 @@
          png_push_save_buffer(png_ptr);
          return;
       }
-      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
    }
 
    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
@@ -1201,515 +1177,6 @@
 #endif /* PNG_READ_INTERLACING_SUPPORTED */
 }
 
-#ifdef PNG_READ_tEXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place tEXt");
-         info_ptr = info_ptr; /* To quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   png_ptr->skip_length = 0;  /* This may not be necessary */
-
-   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
-   {
-      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
-      png_ptr->skip_length = length - (png_uint_32)65535L;
-      length = (png_uint_32)65535L;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-      (png_uint_32)(length + 1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_tEXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
-{
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-
-      else
-         text_size = png_ptr->current_text_left;
-
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp text;
-      png_charp key;
-      int ret;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
-      if (png_ptr->skip_length)
-         return;
-#endif
-
-      key = png_ptr->current_text;
-
-      for (text = key; *text; text++)
-         /* Empty loop */ ;
-
-      if (text < key + png_ptr->current_text_size)
-         text++;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-         (png_uint_32)png_sizeof(png_text));
-      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
-      text_ptr->key = key;
-#ifdef PNG_iTXt_SUPPORTED
-      text_ptr->lang = NULL;
-      text_ptr->lang_key = NULL;
-#endif
-      text_ptr->text = text;
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_free(png_ptr, key);
-      png_free(png_ptr, text_ptr);
-      png_ptr->current_text = NULL;
-
-      if (ret)
-        png_warning(png_ptr, "Insufficient memory to store text chunk.");
-   }
-}
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place zTXt");
-         info_ptr = info_ptr; /* To quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   /* We can't handle zTXt chunks > 64K, since we don't have enough space
-    * to be able to store the uncompressed data.  Actually, the threshold
-    * is probably around 32K, but it isn't as definite as 64K is.
-    */
-   if (length > (png_uint_32)65535L)
-   {
-      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
-      png_push_crc_skip(png_ptr, length);
-      return;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-      (png_uint_32)(length + 1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_zTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
-{
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-
-      else
-         text_size = png_ptr->current_text_left;
-
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp text;
-      png_charp key;
-      int ret;
-      png_size_t text_size, key_size;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-      key = png_ptr->current_text;
-
-      for (text = key; *text; text++)
-         /* Empty loop */ ;
-
-      /* zTXt can't have zero text */
-      if (text >= key + png_ptr->current_text_size)
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         return;
-      }
-
-      text++;
-
-      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         return;
-      }
-
-      text++;
-
-      png_ptr->zstream.next_in = (png_bytep )text;
-      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
-         (text - key));
-      png_ptr->zstream.next_out = png_ptr->zbuf;
-      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
-      key_size = text - key;
-      text_size = 0;
-      text = NULL;
-      ret = Z_STREAM_END;
-
-      while (png_ptr->zstream.avail_in)
-      {
-         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-         if (ret != Z_OK && ret != Z_STREAM_END)
-         {
-            inflateReset(&png_ptr->zstream);
-            png_ptr->zstream.avail_in = 0;
-            png_ptr->current_text = NULL;
-            png_free(png_ptr, key);
-            png_free(png_ptr, text);
-            return;
-         }
-         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
-         {
-            if (text == NULL)
-            {
-               text = (png_charp)png_malloc(png_ptr,
-                     (png_uint_32)(png_ptr->zbuf_size
-                     - png_ptr->zstream.avail_out + key_size + 1));
-
-               png_memcpy(text + key_size, png_ptr->zbuf,
-                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
-               png_memcpy(text, key, key_size);
-
-               text_size = key_size + png_ptr->zbuf_size -
-                  png_ptr->zstream.avail_out;
-
-               *(text + text_size) = '\0';
-            }
-            else
-            {
-               png_charp tmp;
-
-               tmp = text;
-               text = (png_charp)png_malloc(png_ptr, text_size +
-                  (png_uint_32)(png_ptr->zbuf_size 
-                  - png_ptr->zstream.avail_out + 1));
-
-               png_memcpy(text, tmp, text_size);
-               png_free(png_ptr, tmp);
-
-               png_memcpy(text + text_size, png_ptr->zbuf,
-                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-
-               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
-               *(text + text_size) = '\0';
-            }
-            if (ret != Z_STREAM_END)
-            {
-               png_ptr->zstream.next_out = png_ptr->zbuf;
-               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-            }
-         }
-         else
-         {
-            break;
-         }
-
-         if (ret == Z_STREAM_END)
-            break;
-      }
-
-      inflateReset(&png_ptr->zstream);
-      png_ptr->zstream.avail_in = 0;
-
-      if (ret != Z_STREAM_END)
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         png_free(png_ptr, text);
-         return;
-      }
-
-      png_ptr->current_text = NULL;
-      png_free(png_ptr, key);
-      key = text;
-      text += key_size;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-          (png_uint_32)png_sizeof(png_text));
-      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
-      text_ptr->key = key;
-#ifdef PNG_iTXt_SUPPORTED
-      text_ptr->lang = NULL;
-      text_ptr->lang_key = NULL;
-#endif
-      text_ptr->text = text;
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_free(png_ptr, key);
-      png_free(png_ptr, text_ptr);
-
-      if (ret)
-        png_warning(png_ptr, "Insufficient memory to store text chunk.");
-   }
-}
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-void /* PRIVATE */
-png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place iTXt");
-         info_ptr = info_ptr; /* To quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   png_ptr->skip_length = 0;  /* This may not be necessary */
-
-   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
-   {
-      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
-      png_ptr->skip_length = length - (png_uint_32)65535L;
-      length = (png_uint_32)65535L;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-      (png_uint_32)(length + 1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_iTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
-{
-
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-
-      else
-         text_size = png_ptr->current_text_left;
-
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp key;
-      int comp_flag;
-      png_charp lang;
-      png_charp lang_key;
-      png_charp text;
-      int ret;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-#ifdef PNG_MAX_MALLOC_64K
-      if (png_ptr->skip_length)
-         return;
-#endif
-
-      key = png_ptr->current_text;
-
-      for (lang = key; *lang; lang++)
-         /* Empty loop */ ;
-
-      if (lang < key + png_ptr->current_text_size - 3)
-         lang++;
-
-      comp_flag = *lang++;
-      lang++;     /* Skip comp_type, always zero */
-
-      for (lang_key = lang; *lang_key; lang_key++)
-         /* Empty loop */ ;
-
-      lang_key++;        /* Skip NUL separator */
-
-      text=lang_key;
-
-      if (lang_key < key + png_ptr->current_text_size - 1)
-      {
-        for (; *text; text++)
-           /* Empty loop */ ;
-      }
-
-      if (text < key + png_ptr->current_text_size)
-         text++;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-         (png_uint_32)png_sizeof(png_text));
-
-      text_ptr->compression = comp_flag + 2;
-      text_ptr->key = key;
-      text_ptr->lang = lang;
-      text_ptr->lang_key = lang_key;
-      text_ptr->text = text;
-      text_ptr->text_length = 0;
-      text_ptr->itxt_length = png_strlen(text);
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_ptr->current_text = NULL;
-
-      png_free(png_ptr, text_ptr);
-      if (ret)
-         png_warning(png_ptr, "Insufficient memory to store iTXt chunk.");
-   }
-}
-#endif
-
-/* This function is called when we haven't found a handler for this
- * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
- * name or a critical chunk), the chunk is (currently) silently ignored.
- */
-void /* PRIVATE */
-png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   png_uint_32 skip = 0;
-
-   if (!(png_ptr->chunk_name[0] & 0x20))
-   {
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
-         PNG_HANDLE_CHUNK_ALWAYS
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-         && png_ptr->read_user_chunk_fn == NULL
-#endif
-         )
-#endif
-         png_chunk_error(png_ptr, "unknown critical chunk");
-
-      info_ptr = info_ptr; /* To quiet some compiler warnings */
-   }
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
-   {
-#ifdef PNG_MAX_MALLOC_64K
-      if (length > (png_uint_32)65535L)
-      {
-          png_warning(png_ptr, "unknown chunk too large to fit in memory");
-          skip = length - (png_uint_32)65535L;
-          length = (png_uint_32)65535L;
-      }
-#endif
-      png_memcpy((png_charp)png_ptr->unknown_chunk.name,
-                 (png_charp)png_ptr->chunk_name, 
-                 png_sizeof(png_ptr->unknown_chunk.name));
-      png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]
-        = '\0';
-
-      png_ptr->unknown_chunk.size = (png_size_t)length;
-
-      if (length == 0)
-         png_ptr->unknown_chunk.data = NULL;
-
-      else
-      {
-         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
-            (png_uint_32)length);
-         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
-      }
-
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-      if (png_ptr->read_user_chunk_fn != NULL)
-      {
-         /* Callback to user unknown chunk handler */
-         int ret;
-         ret = (*(png_ptr->read_user_chunk_fn))
-           (png_ptr, &png_ptr->unknown_chunk);
-
-         if (ret < 0)
-            png_chunk_error(png_ptr, "error in user chunk");
-
-         if (ret == 0)
-         {
-            if (!(png_ptr->chunk_name[0] & 0x20))
-               if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
-                    PNG_HANDLE_CHUNK_ALWAYS)
-                  png_chunk_error(png_ptr, "unknown critical chunk");
-            png_set_unknown_chunks(png_ptr, info_ptr,
-               &png_ptr->unknown_chunk, 1);
-         }
-      }
-
-      else
-#endif
-        png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
-      png_free(png_ptr, png_ptr->unknown_chunk.data);
-      png_ptr->unknown_chunk.data = NULL;
-   }
-
-   else
-#endif
-      skip=length;
-   png_push_crc_skip(png_ptr, skip);
-}
-
 void /* PRIVATE */
 png_push_have_info(png_structp png_ptr, png_infop info_ptr)
 {
diff --git a/third_party/libpng/pngread.c b/third_party/libpng/pngread.c
index 62076248..24277b18 100644
--- a/third_party/libpng/pngread.c
+++ b/third_party/libpng/pngread.c
@@ -1,8 +1,8 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.2.44 [June 26, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.52 [November 20, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -19,7 +19,6 @@
 #include "png.h"
 #ifdef PNG_READ_SUPPORTED
 
-
 /* Create a PNG structure for reading, and allocate any memory needed. */
 png_structp PNGAPI
 png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
@@ -69,14 +68,8 @@
 #ifdef PNG_USER_LIMITS_SUPPORTED
    png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
    png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-#  ifdef PNG_USER_CHUNK_CACHE_MAX
    /* Added at libpng-1.2.43 and 1.4.0 */
    png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
-#  endif
-#  ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
-   /* Added at libpng-1.2.43 and 1.4.1 */
-   png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
-#  endif
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
@@ -107,16 +100,22 @@
 
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
-   if (user_png_ver)
+   if (user_png_ver != NULL)
    {
-      i = 0;
+      int found_dots = 0;
+      i = -1;
+
       do
       {
-         if (user_png_ver[i] != png_libpng_ver[i])
+         i++;
+         if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
             png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-      } while (png_libpng_ver[i++]);
-    }
-    else
+         if (user_png_ver[i] == '.')
+            found_dots++;
+      } while (found_dots < 2 && user_png_ver[i] != 0 &&
+            PNG_LIBPNG_VER_STRING[i] != 0);
+   }
+   else
          png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
 
 
@@ -1307,12 +1306,6 @@
    png_free(png_ptr, png_ptr->save_buffer);
 #endif
 
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-#ifdef PNG_TEXT_SUPPORTED
-   png_free(png_ptr, png_ptr->current_text);
-#endif /* PNG_TEXT_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-
    /* Save the important info out of the png_struct, in case it is
     * being used again.
     */
@@ -1418,7 +1411,7 @@
    if (transforms & PNG_TRANSFORM_EXPAND)
       if ((png_ptr->bit_depth < 8) ||
           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
-          (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+          (info_ptr->valid & PNG_INFO_tRNS))
          png_set_expand(png_ptr);
 #endif
 
@@ -1437,14 +1430,8 @@
     * [0,65535] to the original [0,7] or [0,31], or whatever range the
     * colors were originally in:
     */
-   if ((transforms & PNG_TRANSFORM_SHIFT)
-       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
-   {
-      png_color_8p sig_bit;
-
-      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
-      png_set_shift(png_ptr, sig_bit);
-   }
+   if ((transforms & PNG_TRANSFORM_SHIFT) && (info_ptr->valid & PNG_INFO_sBIT))
+      png_set_shift(png_ptr, &info_ptr->sig_bit);
 #endif
 
 #ifdef PNG_READ_BGR_SUPPORTED
@@ -1519,8 +1506,8 @@
    /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
    png_read_end(png_ptr, info_ptr);
 
-   transforms = transforms; /* Quiet compiler warnings */
-   params = params;
+   PNG_UNUSED(transforms) /* Quiet compiler warnings */
+   PNG_UNUSED(params)
 
 }
 #endif /* PNG_INFO_IMAGE_SUPPORTED */
diff --git a/third_party/libpng/pngrtran.c b/third_party/libpng/pngrtran.c
index 33703d4..0a760cef 100644
--- a/third_party/libpng/pngrtran.c
+++ b/third_party/libpng/pngrtran.c
@@ -1,8 +1,8 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.2.45 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -917,7 +917,10 @@
     for (i=0; i<png_ptr->num_trans; i++)
     {
       if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
+      {
         k=1; /* Partial transparency is present */
+        break;
+      }
     }
     if (k == 0)
       png_ptr->transformations &= ~PNG_GAMMA;
@@ -1163,6 +1166,7 @@
 
 #ifdef PNG_READ_SHIFT_SUPPORTED
    if ((png_ptr->transformations & PNG_SHIFT) &&
+      !(png_ptr->transformations & PNG_EXPAND) &&
       (color_type == PNG_COLOR_TYPE_PALETTE))
    {
       png_uint_16 i;
@@ -1183,6 +1187,8 @@
          png_ptr->palette[i].green >>= sg;
          png_ptr->palette[i].blue >>= sb;
       }
+
+      png_ptr->transformations &= ~PNG_SHIFT;
    }
 #endif  /* PNG_READ_SHIFT_SUPPORTED */
  }
@@ -1373,6 +1379,9 @@
    {
       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
       {
+         if (png_ptr->palette == NULL)
+            png_error (png_ptr, "Palette is NULL in indexed image");
+
          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
             png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
       }
diff --git a/third_party/libpng/pngrutil.c b/third_party/libpng/pngrutil.c
index 10588c4..543b7e0 100644
--- a/third_party/libpng/pngrutil.c
+++ b/third_party/libpng/pngrutil.c
@@ -1,8 +1,8 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.2.45 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -339,15 +339,13 @@
       /* Now check the limits on this chunk - if the limit fails the
        * compressed data will be removed, the prefix will remain.
        */
-#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
-      if (png_ptr->user_chunk_malloc_max &&
-          (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
-#else
-#  ifdef PNG_USER_CHUNK_MALLOC_MAX
-      if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
+      if (prefix_size >= (~(png_size_t)0) - 1 ||
+         expanded_size >= (~(png_size_t)0) - 1 - prefix_size
+#ifdef PNG_USER_CHUNK_MALLOC_MAX
+         || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
           prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
-#  endif
 #endif
+          )
          png_warning(png_ptr, "Exceeded size limit while expanding chunk");
 
       /* If the size is zero either there was an error and a message
@@ -355,23 +353,13 @@
        * and we have nothing to do - the code will exit through the
        * error case below.
        */
-#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
-    defined(PNG_USER_CHUNK_MALLOC_MAX)
-      else
-#endif
-      if (expanded_size > 0)
+      else if (expanded_size > 0)
       {
          /* Success (maybe) - really uncompress the chunk. */
          png_size_t new_size = 0;
-         png_charp text = NULL;
-         /* Need to check for both truncation (64-bit platforms) and integer
-          * overflow.
-          */
-         if (prefix_size + expanded_size > prefix_size &&
-             prefix_size + expanded_size < 0xffffffffU)
-         {
-            text = png_malloc_warn(png_ptr, prefix_size + expanded_size + 1);
-         }
+
+         png_charp text = png_malloc_warn(png_ptr,
+             prefix_size + expanded_size + 1);
 
          if (text != NULL)
          {
@@ -671,7 +659,7 @@
    }
    png_crc_finish(png_ptr, length);
 
-   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
+   PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
 }
 
 #ifdef PNG_READ_gAMA_SUPPORTED
@@ -1542,15 +1530,16 @@
       return;
    }
 
-   num = length / 2 ;
-   if (num != (unsigned int) png_ptr->num_palette || num >
-      (unsigned int) PNG_MAX_PALETTE_LENGTH)
+   if (length > 2*PNG_MAX_PALETTE_LENGTH ||
+       length != (unsigned int) (2*png_ptr->num_palette))
    {
       png_warning(png_ptr, "Incorrect hIST chunk length");
       png_crc_finish(png_ptr, length);
       return;
    }
 
+   num = length / 2 ;
+
    for (i = 0; i < num; i++)
    {
       png_byte buf[2];
@@ -1869,11 +1858,11 @@
       png_ptr->chunkdata = NULL;
       return;
    }
-   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
+   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep) + 1);
 #endif
 #endif
 
-   for (ep = png_ptr->chunkdata; *ep; ep++)
+   for (ep = png_ptr->chunkdata + 1; *ep; ep++)
       /* Empty loop */ ;
    ep++;
 
@@ -1913,7 +1902,7 @@
 #endif
       return;
    }
-   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
+   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep) + 1);
 #endif
 #endif
 
@@ -2476,7 +2465,7 @@
    png_crc_finish(png_ptr, skip);
 
 #ifndef PNG_READ_USER_CHUNKS_SUPPORTED
-   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
+   PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
 #endif
 }
 
@@ -2932,7 +2921,7 @@
       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
    }
 #ifndef PNG_READ_PACKSWAP_SUPPORTED
-   transformations = transformations; /* Silence compiler warning */
+   PNG_UNUSED(transformations) /* Silence compiler warning */
 #endif
 }
 #endif /* PNG_READ_INTERLACING_SUPPORTED */
diff --git a/third_party/libpng/pngset.c b/third_party/libpng/pngset.c
index 717757f..fed6a55 100644
--- a/third_party/libpng/pngset.c
+++ b/third_party/libpng/pngset.c
@@ -1,8 +1,8 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.2.43 [February 25, 2010]
- * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.51 [February 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -533,9 +533,11 @@
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
       int_green_y, int_blue_x, int_blue_y;
 #endif
+#endif
    png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
 
    if (png_ptr == NULL || info_ptr == NULL)
@@ -555,6 +557,7 @@
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
+#  ifdef PNG_FIXED_POINT_SUPPORTED
    int_white_x = 31270L;
    int_white_y = 32900L;
    int_red_x   = 64000L;
@@ -563,8 +566,12 @@
    int_green_y = 60000L;
    int_blue_x  = 15000L;
    int_blue_y  =  6000L;
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+       int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+       int_green_y, int_blue_x, int_blue_y);
+#  endif
 
-#ifdef PNG_FLOATING_POINT_SUPPORTED
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
    white_x = (float).3127;
    white_y = (float).3290;
    red_x   = (float).64;
@@ -573,17 +580,9 @@
    green_y = (float).60;
    blue_x  = (float).15;
    blue_y  = (float).06;
-#endif
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_cHRM_fixed(png_ptr, info_ptr,
-       int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
-       int_green_y, int_blue_x, int_blue_y);
-#endif
-#ifdef PNG_FLOATING_POINT_SUPPORTED
    png_set_cHRM(png_ptr, info_ptr,
        white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
-#endif
+#  endif
 #endif /* cHRM */
 }
 #endif /* sRGB */
@@ -667,22 +666,26 @@
     */
    if (info_ptr->num_text + num_text > info_ptr->max_text)
    {
+      int old_max_text = info_ptr->max_text;
+      int old_num_text = info_ptr->num_text;
+
       if (info_ptr->text != NULL)
       {
          png_textp old_text;
-         int old_max;
 
-         old_max = info_ptr->max_text;
          info_ptr->max_text = info_ptr->num_text + num_text + 8;
          old_text = info_ptr->text;
+
          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
          if (info_ptr->text == NULL)
          {
-            png_free(png_ptr, old_text);
+            /* Restore to previous condition */
+            info_ptr->max_text = old_max_text;
+            info_ptr->text = old_text;
             return(1);
          }
-         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
+         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
             png_sizeof(png_text)));
          png_free(png_ptr, old_text);
       }
@@ -693,7 +696,12 @@
          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
          if (info_ptr->text == NULL)
+         {
+            /* Restore to previous condition */
+            info_ptr->num_text = old_num_text;
+            info_ptr->max_text = old_max_text;
             return(1);
+         }
 #ifdef PNG_FREE_ME_SUPPORTED
          info_ptr->free_me |= PNG_FREE_TEXT;
 #endif
@@ -701,6 +709,7 @@
       png_debug1(3, "allocated %d entries for info_ptr->text",
          info_ptr->max_text);
    }
+
    for (i = 0; i < num_text; i++)
    {
       png_size_t text_length, key_len;
@@ -840,6 +849,12 @@
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
+   if (num_trans < 0 || num_trans > PNG_MAX_PALETTE_LENGTH)
+      {
+        png_warning(png_ptr, "Ignoring invalid num_trans value");
+        return;
+      }
+
    if (trans != NULL)
    {
        /* It may not actually be necessary to set png_ptr->trans here;
@@ -1174,7 +1189,7 @@
 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
     if (png_ptr != NULL)
     png_ptr->asm_flags = 0;
-    asm_flags = asm_flags; /* Quiet the compiler */
+    PNG_UNUSED(asm_flags) /* Quiet the compiler */
 }
 
 /* This function was added to libpng 1.2.0 */
@@ -1187,8 +1202,8 @@
     if (png_ptr == NULL)
        return;
     /* Quiet the compiler */
-    mmx_bitdepth_threshold = mmx_bitdepth_threshold;
-    mmx_rowbytes_threshold = mmx_rowbytes_threshold;
+    PNG_UNUSED(mmx_bitdepth_threshold)
+    PNG_UNUSED(mmx_rowbytes_threshold)
 }
 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
 
diff --git a/third_party/libpng/pngvcrd.c b/third_party/libpng/pngvcrd.c
index ce4233ef..f553138 100644
--- a/third_party/libpng/pngvcrd.c
+++ b/third_party/libpng/pngvcrd.c
@@ -1 +1,12 @@
-/* pnggvrd.c was removed from libpng-1.2.20. */
+/* pngvcrd.c
+ *
+ * Last changed in libpng 1.2.48 [March 8, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This nearly empty file is for use by configure's compilation test. The
+ * remainder of the file  was removed from libpng-1.2.20.
+ */
diff --git a/third_party/libpng/pngwrite.c b/third_party/libpng/pngwrite.c
index 1d8c53f9..894a984 100644
--- a/third_party/libpng/pngwrite.c
+++ b/third_party/libpng/pngwrite.c
@@ -1,8 +1,8 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.2.45 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.52 [November 20, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -525,15 +525,23 @@
 #endif /* PNG_USER_MEM_SUPPORTED */
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
-   if (user_png_ver)
+   if (user_png_ver != NULL)
    {
-      i = 0;
+      int found_dots = 0;
+      i = -1;
+
       do
       {
-         if (user_png_ver[i] != png_libpng_ver[i])
+         i++;
+         if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
             png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-      } while (png_libpng_ver[i++]);
+         if (user_png_ver[i] == '.')
+            found_dots++;
+      } while (found_dots < 2 && user_png_ver[i] != 0 &&
+            PNG_LIBPNG_VER_STRING[i] != 0);
    }
+   else
+      png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
 
    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
    {
@@ -684,8 +692,9 @@
          png_warning(png_ptr,
  "Application uses deprecated png_write_init() and should be recompiled.");
 #endif
-      }
-   } while (png_libpng_ver[i++]);
+   }
+      i++;
+   } while (png_libpng_ver[i] != 0 && user_png_ver[i] != 0);
 
    png_debug(1, "in png_write_init_3");
 
@@ -1586,8 +1595,8 @@
    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
 
-   transforms = transforms; /* Quiet compiler warnings */
-   params = params;
+   PNG_UNUSED(transforms) /* Quiet compiler warnings */
+   PNG_UNUSED(params)
 }
 #endif
 #endif /* PNG_WRITE_SUPPORTED */
diff --git a/third_party/libusb/BUILD.gn b/third_party/libusb/BUILD.gn
index 0d7c9297..39afaf3 100644
--- a/third_party/libusb/BUILD.gn
+++ b/third_party/libusb/BUILD.gn
@@ -99,6 +99,10 @@
     ]
   }
 
+  if (is_chromeos) {
+    defines += [ "USBI_TIMERFD_AVAILABLE" ]
+  }
+
   if (use_udev) {
     sources += [ "src/libusb/os/linux_udev.cc" ]
     defines += [
diff --git a/third_party/libusb/libusb.gyp b/third_party/libusb/libusb.gyp
index 85f52302..1b0aa56 100644
--- a/third_party/libusb/libusb.gyp
+++ b/third_party/libusb/libusb.gyp
@@ -67,6 +67,11 @@
             '_GNU_SOURCE=1',
           ],
         }],
+        ['chromeos==1', {
+          'defines': [
+            'USBI_TIMERFD_AVAILABLE',
+          ]
+        }],
         ['use_udev==1', {
           'sources': [
             'src/libusb/os/linux_udev.cc',
diff --git a/third_party/libvpx_new/BUILD.gn b/third_party/libvpx_new/BUILD.gn
index 825024bb..33599b6 100644
--- a/third_party/libvpx_new/BUILD.gn
+++ b/third_party/libvpx_new/BUILD.gn
@@ -46,7 +46,7 @@
     "//third_party/libvpx_new/source/config",
     platform_include_dir,
     "//third_party/libvpx_new/source/libvpx",
-    "$root_gen_dir/third_party/libvpx_new", # Provides vpx_rtcd.h.
+    "$root_gen_dir/third_party/libvpx_new",  # Provides vpx_rtcd.h.
   ]
 }
 
@@ -58,21 +58,24 @@
     cflags = [
       # libvpx heavily relies on implicit enum casting.
       "-Wno-conversion",
+
       # libvpx does `if ((a == b))` in some places.
       "-Wno-parentheses-equality",
+
       # libvpx has many static functions in header, which trigger this warning.
       "-Wno-unused-function",
     ]
   } else if (!is_win) {
-    cflags = [ "-Wno-unused-function", "-Wno-sign-compare" ]
+    cflags = [
+      "-Wno-unused-function",
+      "-Wno-sign-compare",
+    ]
   }
 }
 
 # This config is applied to targets that depend on libvpx.
 config("libvpx_external_config") {
-  include_dirs = [
-    "//third_party/libvpx_new/source/libvpx",
-  ]
+  include_dirs = [ "//third_party/libvpx_new/source/libvpx" ]
 }
 
 if (current_cpu == "x86" || current_cpu == "x64") {
@@ -88,7 +91,7 @@
       platform_include_dir,
       "//third_party/libvpx_new/source/config",
       "//third_party/libvpx_new/source/libvpx",
-      target_gen_dir
+      target_gen_dir,
     ]
   }
 }
@@ -191,13 +194,18 @@
     } else {
       sources = libvpx_srcs_arm_assembly
     }
-    outputs = [ "$target_gen_dir/{{source_name_part}}.S" ]
+    outputs = [
+      "$target_gen_dir/{{source_name_part}}.S",
+    ]
     args = [
       "-s",
-      rebase_path("//third_party/libvpx_new/source/libvpx/build/make/ads2gas.pl",
-                  root_build_dir),
-      "-i", "{{source}}",
-      "-o", rebase_path("$target_gen_dir/{{source_name_part}}.S")
+      rebase_path(
+          "//third_party/libvpx_new/source/libvpx/build/make/ads2gas.pl",
+          root_build_dir),
+      "-i",
+      "{{source}}",
+      "-o",
+      rebase_path("$target_gen_dir/{{source_name_part}}.S"),
     ]
   }
 
@@ -206,9 +214,8 @@
     configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
     configs += [ ":libvpx_config" ]
     configs += [ ":libvpx_warnings" ]
-    if (cpu_arch_full == "arm-neon" ||
-        cpu_arch_full == "arm-neon-cpu-detect") {
-      cflags = [ "-mfpu=neon" ]
+    if (cpu_arch_full == "arm-neon" || cpu_arch_full == "arm-neon-cpu-detect") {
+      asmflags = [ "-mfpu=neon" ]
     }
     deps = [
       ":convert_arm_assembly",
diff --git a/third_party/libvpx_new/README.chromium b/third_party/libvpx_new/README.chromium
index 152aa84..0404d6c 100644
--- a/third_party/libvpx_new/README.chromium
+++ b/third_party/libvpx_new/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Tuesday September 22 2015
+Date: Tuesday September 29 2015
 Branch: master
-Commit: 90a109f0eef8bfaaa4869cf7b2873dac5076b582
+Commit: 7d28d12ef34f6cbb6b1e18f3b23b71392fd3ddf5
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
@@ -20,35 +20,20 @@
 Please follow these steps to update libvpx source code:
 
 1. Update the code:
-     cd source/libvpx
-     git fetch
-     git checkout NEW_HASH
+     roll_dep.py \
+       -r <libvpx OWNER> \
+       --log-limit 20 \
+       --roll-to <libvpx hash> \
+       src/third_party/libvpx_new/source/libvpx
 
-   For a list of changes for the commit message run:
-     cd source/libvpx
-     git log --no-merges --topo-order --pretty="%h %s" --max-count=20 \
-       OLD_HASH..NEW_HASH
+   Use the generated commit message for the roll.
 
 2. Generate .gypi, .gni and config files.
 
+   cd third_party/libvpx_new
    ./generate_gypi.sh
 
-3. Change the libvpx_new revision in src/DEPS to the desired hash from upstream
-   libvpx. Update README.chromium with Date, Branch, and Commit.
-
-4. Commit the changes in root (I.e README & .gypi files) and
-   source/config directories. The commit message should look like this:
-
-   Roll libvpx OLD_HASH:NEW_HASH
-
-   git log from upstream:
-   90a109f Restrict get_msb inputs
-   8903b9f remove static from fdct4/8/16/32
-   dd4f953 Remove vpx_filter_block1d16_v8_intrin_ssse3
-   38ad2dc Non-rd pickmode: Don't skip checking zeromv-last mode.
-   d6be267 Create sub8x8 block inter prediction function
-   571b7c9 vp9_end_to_end_test: disable vp10 w/high bitdepth
-   <..>
+3. Update README.chromium with Date, Branch, and Commit.
 
 Tools needed to build libvpx:
 
diff --git a/third_party/libvpx_new/generate_gypi.sh b/third_party/libvpx_new/generate_gypi.sh
index 2b99bb8..39adb8e7 100755
--- a/third_party/libvpx_new/generate_gypi.sh
+++ b/third_party/libvpx_new/generate_gypi.sh
@@ -15,8 +15,6 @@
 # --disable-avx : AVX+AVX2 support is disabled.
 # --only-configs: Excludes generation of GN and GYP files (i.e. only
 #                 configuration headers are generated).
-#
-# !!! It's highly recommended to install yasm before running this script.
 
 export LC_ALL=C
 BASE_DIR=$(pwd)
@@ -52,6 +50,31 @@
   echo "" >> $1
 }
 
+# Search for source files with the same basename in vp8, vp9, and vpx_dsp. The
+# build can support such files but only when they are built into disparate
+# modules. Configuring such modules for both gyp and gn are tricky so avoid the
+# issue at least until vp10 is added.
+function find_duplicates {
+  local readonly duplicate_file_names=$(find \
+    $BASE_DIR/$LIBVPX_SRC_DIR/vp8 \
+    $BASE_DIR/$LIBVPX_SRC_DIR/vp9 \
+    $BASE_DIR/$LIBVPX_SRC_DIR/vpx_dsp \
+    -type f -name \*.c  | xargs -I {} basename {} | sort | uniq -d \
+  )
+
+  if [ -n "${duplicate_file_names}" ]; then
+    echo "WARNING: DUPLICATE FILES FOUND"
+    for file in  ${duplicate_file_names}; do
+      find \
+        $BASE_DIR/$LIBVPX_SRC_DIR/vp8 \
+        $BASE_DIR/$LIBVPX_SRC_DIR/vp9 \
+        $BASE_DIR/$LIBVPX_SRC_DIR/vpx_dsp \
+        -name $file
+    done
+    exit 1
+  fi
+}
+
 # Print gypi boilerplate header.
 # $1 - Output base name
 function write_gypi_header {
@@ -137,10 +160,13 @@
   echo "          ]," >> "$2"
   echo "        }]," >> "$2"
   echo "      ]," >> "$2"
-  fi
+  echo "      'cflags': [ '-m$4', ]," >> "$2"
+  echo "      'asmflags': [ '-m$4', ]," >> "$2"
+  else
   echo "      'cflags': [ '-m$4', ]," >> "$2"
   echo "      'xcode_settings': { 'OTHER_CFLAGS': [ '-m$4' ] }," >> "$2"
-if [[ -z $DISABLE_AVX && $4 == avx2 ]]; then
+  fi
+  if [[ -z $DISABLE_AVX && $4 == avx2 ]]; then
   echo "      'msvs_settings': {" >> "$2"
   echo "        'VCCLCompilerTool': {" >> "$2"
   echo "          'EnableEnhancedInstructionSet': '5', # /arch:AVX2" >> "$2"
@@ -419,6 +445,8 @@
   rm -rf vpx_config.*
 }
 
+find_duplicates
+
 echo "Create temporary directory."
 TEMP_DIR="$LIBVPX_SRC_DIR.temp"
 rm -rf $TEMP_DIR
@@ -426,7 +454,7 @@
 cd $TEMP_DIR
 
 echo "Generate config files."
-all_platforms="--enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 $DISABLE_AVX"
+all_platforms="--enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 $DISABLE_AVX --as=yasm"
 gen_config_files linux/ia32 "--target=x86-linux-gcc --disable-ccache --enable-pic --enable-realtime-only ${all_platforms}"
 gen_config_files linux/x64 "--target=x86_64-linux-gcc --disable-ccache --enable-pic --enable-realtime-only ${all_platforms}"
 gen_config_files linux/arm "--target=armv6-linux-gcc --enable-pic --enable-realtime-only --disable-install-bins --disable-install-libs --disable-edsp ${all_platforms}"
@@ -556,4 +584,14 @@
 cd $BASE_DIR
 rm -rf $TEMP_DIR
 
+gn format --in-place $BASE_DIR/BUILD.gn
+gn format --in-place $BASE_DIR/libvpx_srcs.gni
+
+cd $BASE_DIR/$LIBVPX_SRC_DIR
+echo
+echo "Update README.chromium:"
+git log -1 --format="%cd%nCommit: %H" --date=format:"%A %B %d %Y"
+
+cd $BASE_DIR
+
 # TODO(fgalligan): Can we turn on "--enable-realtime-only" for mipsel?
diff --git a/third_party/libvpx_new/libvpx_srcs.gni b/third_party/libvpx_new/libvpx_srcs.gni
index 451ba45..63685cb 100644
--- a/third_party/libvpx_new/libvpx_srcs.gni
+++ b/third_party/libvpx_new/libvpx_srcs.gni
@@ -409,18 +409,15 @@
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/quantize_sse2.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/variance_sse2.c",
 ]
-libvpx_srcs_x86_sse3 = [
-]
+libvpx_srcs_x86_sse3 = []
 libvpx_srcs_x86_ssse3 = [
   "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_ssse3.c",
   "//third_party/libvpx_new/source/libvpx/vp9/encoder/x86/vp9_dct_ssse3.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c",
 ]
-libvpx_srcs_x86_sse4_1 = [
-  "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_sse4.c",
-]
-libvpx_srcs_x86_avx = [
-]
+libvpx_srcs_x86_sse4_1 =
+    [ "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_sse4.c" ]
+libvpx_srcs_x86_avx = []
 libvpx_srcs_x86_avx2 = [
   "//third_party/libvpx_new/source/libvpx/vp9/encoder/x86/vp9_error_intrin_avx2.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/fwd_txfm_avx2.c",
@@ -844,18 +841,15 @@
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/quantize_sse2.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/variance_sse2.c",
 ]
-libvpx_srcs_x86_64_sse3 = [
-]
+libvpx_srcs_x86_64_sse3 = []
 libvpx_srcs_x86_64_ssse3 = [
   "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_ssse3.c",
   "//third_party/libvpx_new/source/libvpx/vp9/encoder/x86/vp9_dct_ssse3.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c",
 ]
-libvpx_srcs_x86_64_sse4_1 = [
-  "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_sse4.c",
-]
-libvpx_srcs_x86_64_avx = [
-]
+libvpx_srcs_x86_64_sse4_1 =
+    [ "//third_party/libvpx_new/source/libvpx/vp8/encoder/x86/quantize_sse4.c" ]
+libvpx_srcs_x86_64_avx = []
 libvpx_srcs_x86_64_avx2 = [
   "//third_party/libvpx_new/source/libvpx/vp9/encoder/x86/vp9_error_intrin_avx2.c",
   "//third_party/libvpx_new/source/libvpx/vpx_dsp/x86/fwd_txfm_avx2.c",
@@ -2415,8 +2409,7 @@
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.c",
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.h",
 ]
-libvpx_srcs_arm64_assembly = [
-]
+libvpx_srcs_arm64_assembly = []
 libvpx_srcs_mips = [
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.c",
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.h",
@@ -2739,8 +2732,7 @@
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.c",
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.h",
 ]
-libvpx_srcs_mips_assembly = [
-]
+libvpx_srcs_mips_assembly = []
 libvpx_srcs_nacl = [
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.c",
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.h",
@@ -3061,8 +3053,7 @@
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.c",
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.h",
 ]
-libvpx_srcs_nacl_assembly = [
-]
+libvpx_srcs_nacl_assembly = []
 libvpx_srcs_generic = [
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.c",
   "//third_party/libvpx_new/source/libvpx/vp8/common/alloccommon.h",
@@ -3383,5 +3374,4 @@
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.c",
   "//third_party/libvpx_new/source/libvpx/vpx_util/vpx_thread.h",
 ]
-libvpx_srcs_generic_assembly = [
-]
+libvpx_srcs_generic_assembly = []
diff --git a/third_party/libvpx_new/libvpx_srcs_arm_neon_cpu_detect_intrinsics.gypi b/third_party/libvpx_new/libvpx_srcs_arm_neon_cpu_detect_intrinsics.gypi
index 6bc2b60..918dc3d 100644
--- a/third_party/libvpx_new/libvpx_srcs_arm_neon_cpu_detect_intrinsics.gypi
+++ b/third_party/libvpx_new/libvpx_srcs_arm_neon_cpu_detect_intrinsics.gypi
@@ -81,7 +81,7 @@
         }],
       ],
       'cflags': [ '-mfpu=neon', ],
-      'xcode_settings': { 'OTHER_CFLAGS': [ '-mfpu=neon' ] },
+      'asmflags': [ '-mfpu=neon', ],
     },
   ],
 }
diff --git a/third_party/libvpx_new/source/config/linux/arm-neon-cpu-detect/vpx_config.c b/third_party/libvpx_new/source/config/linux/arm-neon-cpu-detect/vpx_config.c
index 721ab0a..135d0ef 100644
--- a/third_party/libvpx_new/source/config/linux/arm-neon-cpu-detect/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/arm-neon-cpu-detect/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=armv7-linux-gcc --enable-pic --enable-realtime-only --enable-runtime-cpu-detect --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=armv7-linux-gcc --enable-pic --enable-realtime-only --enable-runtime-cpu-detect --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/arm-neon/vpx_config.c b/third_party/libvpx_new/source/config/linux/arm-neon/vpx_config.c
index e05d699..588edd5 100644
--- a/third_party/libvpx_new/source/config/linux/arm-neon/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/arm-neon/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=armv7-linux-gcc --enable-pic --enable-realtime-only --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=armv7-linux-gcc --enable-pic --enable-realtime-only --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/arm/vpx_config.c b/third_party/libvpx_new/source/config/linux/arm/vpx_config.c
index 0b06ef9..9e8bc81 100644
--- a/third_party/libvpx_new/source/config/linux/arm/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/arm/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=armv6-linux-gcc --enable-pic --enable-realtime-only --disable-install-bins --disable-install-libs --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=armv6-linux-gcc --enable-pic --enable-realtime-only --disable-install-bins --disable-install-libs --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/arm64/vpx_config.c b/third_party/libvpx_new/source/config/linux/arm64/vpx_config.c
index 6674d94..64b0c80 100644
--- a/third_party/libvpx_new/source/config/linux/arm64/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/arm64/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--force-target=armv8-linux-gcc --enable-pic --enable-realtime-only --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--force-target=armv8-linux-gcc --enable-pic --enable-realtime-only --disable-edsp --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/generic/vpx_config.c b/third_party/libvpx_new/source/config/linux/generic/vpx_config.c
index 2a18a45..4ea064d 100644
--- a/third_party/libvpx_new/source/config/linux/generic/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/generic/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=generic-gnu --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=generic-gnu --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/ia32/vpx_config.c b/third_party/libvpx_new/source/config/linux/ia32/vpx_config.c
index 08b58cc..5588449 100644
--- a/third_party/libvpx_new/source/config/linux/ia32/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/ia32/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86-linux-gcc --disable-ccache --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86-linux-gcc --disable-ccache --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/mips64el/vpx_config.c b/third_party/libvpx_new/source/config/linux/mips64el/vpx_config.c
index 9e6876b5..bdf1aa20 100644
--- a/third_party/libvpx_new/source/config/linux/mips64el/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/mips64el/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=mips64-linux-gcc --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=mips64-linux-gcc --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/mipsel/vpx_config.c b/third_party/libvpx_new/source/config/linux/mipsel/vpx_config.c
index 2c1375d8..702a26c9 100644
--- a/third_party/libvpx_new/source/config/linux/mipsel/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/mipsel/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=mips32-linux-gcc --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=mips32-linux-gcc --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/linux/x64/vpx_config.c b/third_party/libvpx_new/source/config/linux/x64/vpx_config.c
index 4f190b1..0cfd629c 100644
--- a/third_party/libvpx_new/source/config/linux/x64/vpx_config.c
+++ b/third_party/libvpx_new/source/config/linux/x64/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86_64-linux-gcc --disable-ccache --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86_64-linux-gcc --disable-ccache --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/mac/ia32/vpx_config.c b/third_party/libvpx_new/source/config/mac/ia32/vpx_config.c
index 90849ad6..cff894e 100644
--- a/third_party/libvpx_new/source/config/mac/ia32/vpx_config.c
+++ b/third_party/libvpx_new/source/config/mac/ia32/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86-darwin9-gcc --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86-darwin9-gcc --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/mac/x64/vpx_config.c b/third_party/libvpx_new/source/config/mac/x64/vpx_config.c
index cba8a3d..aa3eb69 100644
--- a/third_party/libvpx_new/source/config/mac/x64/vpx_config.c
+++ b/third_party/libvpx_new/source/config/mac/x64/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86_64-darwin9-gcc --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86_64-darwin9-gcc --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/nacl/vpx_config.c b/third_party/libvpx_new/source/config/nacl/vpx_config.c
index 2a18a45..4ea064d 100644
--- a/third_party/libvpx_new/source/config/nacl/vpx_config.c
+++ b/third_party/libvpx_new/source/config/nacl/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=generic-gnu --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=generic-gnu --enable-pic --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/vpx_version.h b/third_party/libvpx_new/source/config/vpx_version.h
index 217db02..2752f2d 100644
--- a/third_party/libvpx_new/source/config/vpx_version.h
+++ b/third_party/libvpx_new/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  4
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "1367-g90a109f"
+#define VERSION_EXTRA  "1410-g7d28d12"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.4.0-1367-g90a109f"
-#define VERSION_STRING      " v1.4.0-1367-g90a109f"
+#define VERSION_STRING_NOSP "v1.4.0-1410-g7d28d12"
+#define VERSION_STRING      " v1.4.0-1410-g7d28d12"
diff --git a/third_party/libvpx_new/source/config/win/ia32/vpx_config.c b/third_party/libvpx_new/source/config/win/ia32/vpx_config.c
index d88b6d68..7c66e2c 100644
--- a/third_party/libvpx_new/source/config/win/ia32/vpx_config.c
+++ b/third_party/libvpx_new/source/config/win/ia32/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86-win32-vs12 --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86-win32-vs12 --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/source/config/win/x64/vpx_config.c b/third_party/libvpx_new/source/config/win/x64/vpx_config.c
index 6dd3005..725e7689 100644
--- a/third_party/libvpx_new/source/config/win/x64/vpx_config.c
+++ b/third_party/libvpx_new/source/config/win/x64/vpx_config.c
@@ -6,5 +6,5 @@
 /* in the file PATENTS.  All contributing project authors may */
 /* be found in the AUTHORS file in the root of the source tree. */
 #include "vpx/vpx_codec.h"
-static const char* const cfg = "--target=x86_64-win64-vs12 --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384";
+static const char* const cfg = "--target=x86_64-win64-vs12 --enable-realtime-only --enable-external-build --enable-postproc --disable-install-srcs --enable-multi-res-encoding --enable-temporal-denoising --disable-unit-tests --disable-install-docs --disable-examples --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --as=yasm";
 const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx_new/update_libvpx.sh b/third_party/libvpx_new/update_libvpx.sh
deleted file mode 100755
index d3b6e9c7..0000000
--- a/third_party/libvpx_new/update_libvpx.sh
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/bin/bash -e
-#
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This tool is used to update libvpx source code with the latest git
-# repository.
-#
-# Make sure you run this in a git checkout of deps/third_party/libvpx_new!
-
-# Usage:
-#
-# $ ./update_libvpx.sh [branch | revision | file or url containing a revision]
-# When specifying a branch it may be necessary to prefix with origin/
-
-# Tools required for running this tool:
-#
-# 1. Linux / Mac
-# 2. git
-
-export LC_ALL=C
-
-# Location for the remote git repository.
-GIT_REPO="https://chromium.googlesource.com/webm/libvpx"
-
-GIT_BRANCH="origin/master"
-LIBVPX_SRC_DIR="source/libvpx"
-BASE_DIR=`pwd`
-
-if [ -n "$1" ]; then
-  GIT_BRANCH="$1"
-  if [ -f "$1"  ]; then
-    GIT_BRANCH=$(<"$1")
-  elif [[ $1 = http* ]]; then
-    GIT_BRANCH=`curl $1`
-  fi
-fi
-
-prev_hash="$(egrep "^Commit: [[:alnum:]]" README.chromium | awk '{ print $2 }')"
-echo "prev_hash:$prev_hash"
-
-rm -rf $LIBVPX_SRC_DIR
-mkdir $LIBVPX_SRC_DIR
-cd $LIBVPX_SRC_DIR
-
-# Start a local git repo.
-git clone $GIT_REPO .
-
-# Switch the content to the latest git repo.
-git checkout -b tot $GIT_BRANCH
-
-add="$(git diff-index --diff-filter=A $prev_hash | grep -v vp10/ | \
-tr -s [:blank:] ' ' | cut -f6 -d\ )"
-delete="$(git diff-index --diff-filter=D $prev_hash | grep -v vp10/ | \
-tr -s [:blank:] ' ' | cut -f6 -d\ )"
-
-# Get the current commit hash.
-hash=$(git log -1 --format="%H")
-
-# README reminder.
-echo "Update README.chromium:"
-echo "==============="
-echo "Date: $(date +"%A %B %d %Y")"
-echo "Branch: master"
-echo "Commit: $hash"
-echo "==============="
-echo ""
-
-# Commit message header.
-echo "Commit message:"
-echo "==============="
-echo "libvpx: Pull from upstream"
-echo ""
-
-# Output the current commit hash.
-echo "Current HEAD: $hash"
-echo ""
-
-# Output log for upstream from current hash.
-if [ -n "$prev_hash" ]; then
-  echo "git log from upstream:"
-  pretty_git_log="$(git log \
-                    --no-merges \
-                    --topo-order \
-                    --pretty="%h %s" \
-                    --max-count=20 \
-                    $prev_hash..$hash)"
-  if [ -z "$pretty_git_log" ]; then
-    echo "No log found. Checking for reverts."
-    pretty_git_log="$(git log \
-                      --no-merges \
-                      --topo-order \
-                      --pretty="%h %s" \
-                      --max-count=20 \
-                      $hash..$prev_hash)"
-  fi
-  echo "$pretty_git_log"
-  # If it makes it to 20 then it's probably skipping even more.
-  if [ `echo "$pretty_git_log" | wc -l` -eq 20 ]; then
-    echo "<...>"
-  fi
-fi
-
-# Commit message footer.
-echo ""
-echo "TBR=tomfinegan@chromium.org"
-echo "==============="
-
-# Git is useless now, remove the local git repo.
-# Remove vp10 to cut down on code churn since it is not currently built.
-rm -rf .git vp10
-
-# Add and remove files.
-echo "$add" | xargs -I {} git add {}
-echo "$delete" | xargs -I {} git rm --ignore-unmatch {}
-
-# Find empty directories and remove them.
-find . -type d -empty -exec git rm {} \;
-
-# Mark the scripts as executable so presubmit doesn't complain. The important
-# ones already have the x bit set but some of the files they include do not.
-chmod 755 build/make/*.sh build/make/*.pl configure
-
-# The build system doesn't support files with the same name. Search vp8, vp9 and vpx_dsp
-# for such files.
-duplicate_files=$(find vp8 vp9 vpx_dsp -type f | xargs basename | sort | uniq -d | \
-  egrep -v '(^exports_(dec|enc)|\.h)$' | \
-  xargs -I {} find vp8 vp9 vpx_dsp -name {})
-
-if [ -n "$duplicate_files" ]; then
-  echo "WARNING: DUPLICATE FILES FOUND"
-  echo "It would be a good idea to resolve these before attempting to roll"
-  echo $duplicate_files
-fi
-
-cd $BASE_DIR
diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn
index d52e1da..fbaffd6f 100644
--- a/third_party/libwebp/BUILD.gn
+++ b/third_party/libwebp/BUILD.gn
@@ -82,18 +82,10 @@
   ]
   if (is_android) {
     deps += [ "//third_party/android_tools:cpu_features" ]
-  }
 
-  # TODO(GYP):
-  #      'conditions': [
-  #        ['order_profiling != 0', {
-  #          'target_conditions' : [
-  #            ['_toolset=="target"', {
-  #              'cflags!': [ '-finstrument-functions' ],
-  #            }],
-  #          ],
-  #        }],
-  #      ],
+    configs -= [ "//build/config/android:default_cygprofile_instrumentation" ]
+    configs += [ "//build/config/android:no_cygprofile_instrumentation" ]
+  }
 }
 
 if (use_dsp_neon) {
@@ -116,16 +108,10 @@
       cflags = [ "-frename-registers" ]
     }
 
-    # TODO(GYP):
-    #        ['order_profiling != 0', {
-    #          'target_conditions' : [
-    #            ['_toolset=="target"', {
-    #              'cflags!': [ '-finstrument-functions' ],
-    #            }],
-    #          ],
-    #        }],
-    #      ],
-    #    }
+    if (is_android) {
+      configs -= [ "//build/config/android:default_cygprofile_instrumentation" ]
+      configs += [ "//build/config/android:no_cygprofile_instrumentation" ]
+    }
   }
 }  # use_dsp_neon
 
diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp
index e8cea60..833776d 100644
--- a/third_party/mojo/mojo_public.gyp
+++ b/third_party/mojo/mojo_public.gyp
@@ -155,6 +155,7 @@
         'src/mojo/public/cpp/bindings/lib/validation_errors.h',
         'src/mojo/public/cpp/bindings/lib/validation_util.cc',
         'src/mojo/public/cpp/bindings/lib/validation_util.h',
+        'src/mojo/public/cpp/bindings/lib/value_traits.h',
         # This comes from the mojo_interface_bindings_cpp_sources dependency.
         '>@(mojom_generated_sources)',
       ],
diff --git a/third_party/mojo/src/mojo/edk/system/channel.cc b/third_party/mojo/src/mojo/edk/system/channel.cc
index bd4a347d..b0101b5c 100644
--- a/third_party/mojo/src/mojo/edk/system/channel.cc
+++ b/third_party/mojo/src/mojo/edk/system/channel.cc
@@ -156,11 +156,11 @@
   if (!is_running_) {
     // TODO(vtl): I think this is probably not an error condition, but I should
     // think about it (and the shutdown sequence) more carefully.
-    LOG(WARNING) << "WriteMessage() after shutdown";
+    VLOG(2) << "WriteMessage() after shutdown";
     return false;
   }
 
-  DLOG_IF(WARNING, is_shutting_down_) << "WriteMessage() while shutting down";
+  DVLOG_IF(2, is_shutting_down_) << "WriteMessage() while shutting down";
   return raw_channel_->WriteMessage(message.Pass());
 }
 
@@ -339,7 +339,8 @@
       break;
     case ERROR_READ_BROKEN: {
       MutexLocker locker(&mutex_);
-      LOG_IF(ERROR, !is_shutting_down_)
+      // The other side likely crashed or was killed.
+      VLOG_IF(2, !is_shutting_down_)
           << "RawChannel read error (connection broken)";
       break;
     }
@@ -581,7 +582,7 @@
 void Channel::HandleRemoteError(const char* error_message) {
   // TODO(vtl): Is this how we really want to handle this? Probably we want to
   // terminate the connection, since it's spewing invalid stuff.
-  LOG(WARNING) << error_message;
+  VLOG(2) << error_message;
 }
 
 void Channel::HandleLocalError(const char* error_message) {
@@ -590,7 +591,7 @@
   // (endpoint), and notify it that the remote is (effectively) closed.
   // Sometimes we'll want to kill the channel (and notify all the endpoints that
   // their remotes are dead.
-  LOG(WARNING) << error_message;
+  VLOG(2) << error_message;
 }
 
 // Note: |endpoint| being a |scoped_refptr| makes this function safe, since it
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
index e3453134..14eb550c 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
@@ -52,6 +52,7 @@
     "lib/validation_errors.h",
     "lib/validation_util.cc",
     "lib/validation_util.h",
+    "lib/value_traits.h",
     "map.h",
     "message.h",
     "message_filter.h",
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/array.h b/third_party/mojo/src/mojo/public/cpp/bindings/array.h
index c51a455..f7d3921 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/array.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/array.h
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/lib/array_internal.h"
 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/lib/value_traits.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 
 namespace mojo {
@@ -170,6 +171,13 @@
   operator Testable() const { return is_null_ ? 0 : &Array::vec_; }
 
  private:
+  // Forbid the == and != operators explicitly, otherwise Array will be
+  // converted to Testable to do == or != comparison.
+  template <typename U>
+  bool operator==(const Array<U>& other) const = delete;
+  template <typename U>
+  bool operator!=(const Array<U>& other) const = delete;
+
   void Take(Array* other) {
     reset();
     Swap(other);
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h b/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
index 7908ca8..dc44667 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h
@@ -168,6 +168,13 @@
   }
 
  private:
+  // Forbid the == and != operators explicitly, otherwise InterfacePtr will be
+  // converted to Testable to do == or != comparison.
+  template <typename T>
+  bool operator==(const InterfacePtr<T>& other) const = delete;
+  template <typename T>
+  bool operator!=(const InterfacePtr<T>& other) const = delete;
+
   typedef internal::InterfacePtrState<Interface> State;
   mutable State internal_state_;
 };
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
index 6e6afde..28bc289a 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -10,15 +10,8 @@
 #include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
-class String;
-
-template <typename T>
-class Array;
-
-template <typename K, typename V>
-class Map;
-
 namespace internal {
+
 template <typename T>
 class Array_Data;
 
@@ -125,29 +118,6 @@
   typedef typename S::Data_* DataType;
 };
 
-template <typename T, typename Enable = void>
-struct ValueTraits {
-  static bool Equals(const T& a, const T& b) { return a == b; }
-};
-
-template <typename T>
-struct ValueTraits<
-    T,
-    typename EnableIf<IsSpecializationOf<Array, T>::value ||
-                      IsSpecializationOf<Map, T>::value ||
-                      IsSpecializationOf<StructPtr, T>::value ||
-                      IsSpecializationOf<InlinedStructPtr, T>::value>::type> {
-  static bool Equals(const T& a, const T& b) { return a.Equals(b); }
-};
-
-template <typename T>
-struct ValueTraits<ScopedHandleBase<T>> {
-  static bool Equals(const ScopedHandleBase<T>& a,
-                     const ScopedHandleBase<T>& b) {
-    return a.get().value() == b.get().value();
-  }
-};
-
 }  // namespace internal
 }  // namespace mojo
 
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/value_traits.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/value_traits.h
new file mode 100644
index 0000000..79a717a3
--- /dev/null
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/value_traits.h
@@ -0,0 +1,75 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALUE_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALUE_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/lib/template_util.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/struct_ptr.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+template <typename T>
+class Array;
+
+template <typename K, typename V>
+class Map;
+
+namespace internal {
+
+template <typename T, typename Enable = void>
+struct ValueTraits {
+  static bool Equals(const T& a, const T& b) { return a == b; }
+};
+
+template <typename T>
+struct ValueTraits<
+    T,
+    typename EnableIf<IsSpecializationOf<Array, T>::value ||
+                      IsSpecializationOf<Map, T>::value ||
+                      IsSpecializationOf<StructPtr, T>::value ||
+                      IsSpecializationOf<InlinedStructPtr, T>::value>::type> {
+  static bool Equals(const T& a, const T& b) { return a.Equals(b); }
+};
+
+template <typename T>
+struct ValueTraits<ScopedHandleBase<T>> {
+  static bool Equals(const ScopedHandleBase<T>& a,
+                     const ScopedHandleBase<T>& b) {
+    return a.get().value() == b.get().value();
+  }
+};
+
+template <typename T>
+struct ValueTraits<InterfaceRequest<T>> {
+  static bool Equals(const InterfaceRequest<T>& a,
+                     const InterfaceRequest<T>& b) {
+    if (&a == &b)
+      return true;
+
+    // If |a| and |b| refer to different objects, they are equivalent iff they
+    // are both invalid.
+    return !a.is_pending() && !b.is_pending();
+  }
+};
+
+template <typename T>
+struct ValueTraits<InterfacePtr<T>> {
+  static bool Equals(const InterfacePtr<T>& a, const InterfacePtr<T>& b) {
+    if (&a == &b)
+      return true;
+
+    // If |a| and |b| refer to different objects, they are equivalent iff they
+    // are both null.
+    return !a && !b;
+  }
+};
+
+}  // namespace internal
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALUE_TRAITS_H_
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/map.h b/third_party/mojo/src/mojo/public/cpp/bindings/map.h
index 09ca4ad9..a69aafa 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/map.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/map.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "mojo/public/cpp/bindings/lib/map_internal.h"
+#include "mojo/public/cpp/bindings/lib/value_traits.h"
 
 namespace mojo {
 
@@ -231,6 +232,13 @@
   operator Testable() const { return is_null_ ? 0 : &Map::map_; }
 
  private:
+  // Forbid the == and != operators explicitly, otherwise Map will be converted
+  // to Testable to do == or != comparison.
+  template <typename T, typename U>
+  bool operator==(const Map<T, U>& other) const = delete;
+  template <typename T, typename U>
+  bool operator!=(const Map<T, U>& other) const = delete;
+
   void Take(Map* other) {
     reset();
     Swap(other);
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h b/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
index 04a8130f..b324e93a 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/struct_ptr.h
@@ -93,6 +93,14 @@
 
  private:
   friend class internal::StructHelper<Struct>;
+
+  // Forbid the == and != operators explicitly, otherwise StructPtr will be
+  // converted to Testable to do == or != comparison.
+  template <typename T>
+  bool operator==(const StructPtr<T>& other) const = delete;
+  template <typename T>
+  bool operator!=(const StructPtr<T>& other) const = delete;
+
   void Initialize() {
     MOJO_DCHECK(!ptr_);
     ptr_ = new Struct();
@@ -174,6 +182,14 @@
 
  private:
   friend class internal::StructHelper<Struct>;
+
+  // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will
+  // be converted to Testable to do == or != comparison.
+  template <typename T>
+  bool operator==(const InlinedStructPtr<T>& other) const = delete;
+  template <typename T>
+  bool operator!=(const InlinedStructPtr<T>& other) const = delete;
+
   void Initialize() { is_null_ = false; }
 
   void Take(InlinedStructPtr* other) {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/equals_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/equals_unittest.cc
index 9196d86..72b02d4 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/equals_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/equals_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 "mojo/public/cpp/bindings/lib/value_traits.h"
 #include "mojo/public/cpp/environment/environment.h"
 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -29,7 +30,7 @@
 };
 }
 
-TEST_F(EqualsTest, Null) {
+TEST_F(EqualsTest, NullStruct) {
   RectPtr r1;
   RectPtr r2;
   EXPECT_TRUE(r1.Equals(r2));
@@ -40,7 +41,7 @@
   EXPECT_FALSE(r2.Equals(r1));
 }
 
-TEST_F(EqualsTest, EqualsStruct) {
+TEST_F(EqualsTest, Struct) {
   RectPtr r1(CreateRect());
   RectPtr r2(r1.Clone());
   EXPECT_TRUE(r1.Equals(r2));
@@ -50,7 +51,7 @@
   EXPECT_FALSE(r1.Equals(r2));
 }
 
-TEST_F(EqualsTest, EqualsStructNested) {
+TEST_F(EqualsTest, StructNested) {
   RectPairPtr p1(RectPair::New());
   p1->first = CreateRect();
   p1->second = CreateRect();
@@ -62,7 +63,7 @@
   EXPECT_FALSE(p1.Equals(p2));
 }
 
-TEST_F(EqualsTest, EqualsArray) {
+TEST_F(EqualsTest, Array) {
   NamedRegionPtr n1(NamedRegion::New());
   n1->name = "n1";
   n1->rects.push_back(CreateRect());
@@ -86,7 +87,7 @@
   EXPECT_TRUE(n1.Equals(n2));
 }
 
-TEST_F(EqualsTest, EqualsMap) {
+TEST_F(EqualsTest, Map) {
   auto n1(NamedRegion::New());
   n1->name = "foo";
   n1->rects.push_back(CreateRect());
@@ -116,5 +117,48 @@
   EXPECT_TRUE(m1.Equals(m2));
 }
 
+TEST_F(EqualsTest, InterfacePtr) {
+  using InterfaceValueTraits = mojo::internal::ValueTraits<SomeInterfacePtr>;
+
+  SomeInterfacePtr inf1;
+  SomeInterfacePtr inf2;
+
+  EXPECT_TRUE(InterfaceValueTraits::Equals(inf1, inf1));
+  EXPECT_TRUE(InterfaceValueTraits::Equals(inf1, inf2));
+
+  auto inf1_request = GetProxy(&inf1);
+  MOJO_ALLOW_UNUSED_LOCAL(inf1_request);
+
+  EXPECT_TRUE(InterfaceValueTraits::Equals(inf1, inf1));
+  EXPECT_FALSE(InterfaceValueTraits::Equals(inf1, inf2));
+
+  auto inf2_request = GetProxy(&inf2);
+  MOJO_ALLOW_UNUSED_LOCAL(inf2_request);
+
+  EXPECT_FALSE(InterfaceValueTraits::Equals(inf1, inf2));
+}
+
+TEST_F(EqualsTest, InterfaceRequest) {
+  using RequestValueTraits =
+      mojo::internal::ValueTraits<InterfaceRequest<SomeInterface>>;
+
+  InterfaceRequest<SomeInterface> req1;
+  InterfaceRequest<SomeInterface> req2;
+
+  EXPECT_TRUE(RequestValueTraits::Equals(req1, req1));
+  EXPECT_TRUE(RequestValueTraits::Equals(req1, req2));
+
+  SomeInterfacePtr inf1;
+  req1 = GetProxy(&inf1);
+
+  EXPECT_TRUE(RequestValueTraits::Equals(req1, req1));
+  EXPECT_FALSE(RequestValueTraits::Equals(req1, req2));
+
+  SomeInterfacePtr inf2;
+  req2 = GetProxy(&inf2);
+
+  EXPECT_FALSE(RequestValueTraits::Equals(req1, req2));
+}
+
 }  // test
 }  // mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/string_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/string_unittest.cc
index 7e3d9102..f6bc424 100644
--- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/string_unittest.cc
+++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/string_unittest.cc
@@ -54,11 +54,28 @@
   String s("hello world");
   String t("hello world");
   EXPECT_EQ(s, t);
+  EXPECT_TRUE(s == s);
+  EXPECT_FALSE(s != s);
   EXPECT_TRUE(s == t);
+  EXPECT_FALSE(s != t);
   EXPECT_TRUE("hello world" == s);
   EXPECT_TRUE(s == "hello world");
   EXPECT_TRUE("not" != s);
+  EXPECT_FALSE("not" == s);
   EXPECT_TRUE(s != "not");
+  EXPECT_FALSE(s == "not");
+
+  // Test null strings.
+  String n1;
+  String n2;
+  EXPECT_TRUE(n1 == n1);
+  EXPECT_FALSE(n1 != n2);
+  EXPECT_TRUE(n1 == n2);
+  EXPECT_FALSE(n1 != n2);
+  EXPECT_TRUE(n1 != s);
+  EXPECT_FALSE(n1 == s);
+  EXPECT_TRUE(s != n1);
+  EXPECT_FALSE(s == n1);
 }
 
 TEST(StringTest, LessThanNullness) {
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
index b55b43ea..b62df5b 100644
--- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
+++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_structs.mojom
@@ -369,3 +369,9 @@
 struct ContainsOther {
   int32 other;
 };
+
+// Used to verify that structs can contain interface requests.
+
+struct ContainsInterfaceRequest {
+  SomeInterface& request;
+};
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
index b4b4df8..2d748fc9 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module-internal.h.tmpl
@@ -11,6 +11,7 @@
 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
 #include "mojo/public/cpp/bindings/lib/buffer.h"
 #include "mojo/public/cpp/bindings/lib/union_accessor.h"
+#include "mojo/public/cpp/bindings/lib/value_traits.h"
 #include "mojo/public/cpp/bindings/struct_ptr.h"
 
 {%- for import in imports %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 160f657..5425cdb 100644
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -167,7 +167,7 @@
   if mojom.IsInterfaceKind(kind):
     return "%sPtr" % GetNameForKind(kind)
   if mojom.IsInterfaceRequestKind(kind):
-    raise Exception("InterfaceRequest fields not supported!")
+    return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
   if mojom.IsStringKind(kind):
     return "mojo::String"
   if mojom.IsGenericHandleKind(kind):
diff --git a/third_party/polymer/v1_0/chromium.patch b/third_party/polymer/v1_0/chromium.patch
index 231b205b..a7a5b48 100644
--- a/third_party/polymer/v1_0/chromium.patch
+++ b/third_party/polymer/v1_0/chromium.patch
@@ -42,3 +42,17 @@
  
    </template>
  </dom-module>
+diff --git a/components-chromium/polymer/polymer-extracted.js b/components-chromium/polymer/polymer-extracted.js
+index baf9ab3..985fe6c 100644
+--- a/components-chromium/polymer/polymer-extracted.js
++++ b/components-chromium/polymer/polymer-extracted.js
+@@ -2157,8 +2157,7 @@ _hasMixinRules: function (rules) {
+ return rules[0].selector.indexOf(this.VAR_START) >= 0;
+ },
+ removeCustomProps: function (cssText) {
+-cssText = this.removeCustomPropAssignment(cssText);
+-return this.removeCustomPropApply(cssText);
++return cssText;
+ },
+ removeCustomPropAssignment: function (cssText) {
+ return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, '');
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js
index baf9ab3..985fe6c 100644
--- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js
@@ -2157,8 +2157,7 @@
 return rules[0].selector.indexOf(this.VAR_START) >= 0;
 },
 removeCustomProps: function (cssText) {
-cssText = this.removeCustomPropAssignment(cssText);
-return this.removeCustomPropApply(cssText);
+return cssText;
 },
 removeCustomPropAssignment: function (cssText) {
 return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, '');
diff --git a/third_party/sfntly/BUILD.gn b/third_party/sfntly/BUILD.gn
index 111f1cd..32b2328 100644
--- a/third_party/sfntly/BUILD.gn
+++ b/third_party/sfntly/BUILD.gn
@@ -4,124 +4,126 @@
 
 static_library("sfntly") {
   sources = [
-    "cpp/src/sample/chromium/font_subsetter.cc",
-    "cpp/src/sample/chromium/font_subsetter.h",
-    "cpp/src/sample/chromium/subsetter_impl.cc",
-    "cpp/src/sample/chromium/subsetter_impl.h",
-    "cpp/src/sfntly/data/byte_array.cc",
-    "cpp/src/sfntly/data/byte_array.h",
-    "cpp/src/sfntly/data/font_data.cc",
-    "cpp/src/sfntly/data/font_data.h",
-    "cpp/src/sfntly/data/font_input_stream.cc",
-    "cpp/src/sfntly/data/font_input_stream.h",
-    "cpp/src/sfntly/data/font_output_stream.cc",
-    "cpp/src/sfntly/data/font_output_stream.h",
-    "cpp/src/sfntly/data/growable_memory_byte_array.cc",
-    "cpp/src/sfntly/data/growable_memory_byte_array.h",
-    "cpp/src/sfntly/data/memory_byte_array.cc",
-    "cpp/src/sfntly/data/memory_byte_array.h",
-    "cpp/src/sfntly/data/readable_font_data.cc",
-    "cpp/src/sfntly/data/readable_font_data.h",
-    "cpp/src/sfntly/data/writable_font_data.cc",
-    "cpp/src/sfntly/data/writable_font_data.h",
-    "cpp/src/sfntly/font.cc",
-    "cpp/src/sfntly/font.h",
-    "cpp/src/sfntly/font_factory.cc",
-    "cpp/src/sfntly/font_factory.h",
-    "cpp/src/sfntly/math/fixed1616.h",
-    "cpp/src/sfntly/math/font_math.h",
-    "cpp/src/sfntly/port/atomic.h",
-    "cpp/src/sfntly/port/config.h",
-    "cpp/src/sfntly/port/endian.h",
-    "cpp/src/sfntly/port/exception_type.h",
-    "cpp/src/sfntly/port/file_input_stream.cc",
-    "cpp/src/sfntly/port/file_input_stream.h",
-    "cpp/src/sfntly/port/input_stream.h",
-    "cpp/src/sfntly/port/lock.cc",
-    "cpp/src/sfntly/port/lock.h",
-    "cpp/src/sfntly/port/memory_input_stream.cc",
-    "cpp/src/sfntly/port/memory_input_stream.h",
-    "cpp/src/sfntly/port/memory_output_stream.cc",
-    "cpp/src/sfntly/port/memory_output_stream.h",
-    "cpp/src/sfntly/port/output_stream.h",
-    "cpp/src/sfntly/port/refcount.h",
-    "cpp/src/sfntly/port/type.h",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/big_glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.cc",
-    "cpp/src/sfntly/table/bitmap/bitmap_size_table.h",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebdt_table.h",
-    "cpp/src/sfntly/table/bitmap/eblc_table.cc",
-    "cpp/src/sfntly/table/bitmap/eblc_table.h",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.cc",
-    "cpp/src/sfntly/table/bitmap/ebsc_table.h",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/glyph_metrics.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format1.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format2.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format3.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format4.h",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc",
-    "cpp/src/sfntly/table/bitmap/index_sub_table_format5.h",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc",
-    "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc",
-    "cpp/src/sfntly/table/bitmap/small_glyph_metrics.h",
-    "cpp/src/sfntly/table/byte_array_table_builder.cc",
-    "cpp/src/sfntly/table/byte_array_table_builder.h",
-    "cpp/src/sfntly/table/core/cmap_table.cc",
-    "cpp/src/sfntly/table/core/cmap_table.h",
-    "cpp/src/sfntly/table/core/font_header_table.cc",
-    "cpp/src/sfntly/table/core/font_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_device_metrics_table.h",
-    "cpp/src/sfntly/table/core/horizontal_header_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_header_table.h",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.cc",
-    "cpp/src/sfntly/table/core/horizontal_metrics_table.h",
-    "cpp/src/sfntly/table/core/maximum_profile_table.cc",
-    "cpp/src/sfntly/table/core/maximum_profile_table.h",
-    "cpp/src/sfntly/table/core/name_table.cc",
-    "cpp/src/sfntly/table/core/name_table.h",
-    "cpp/src/sfntly/table/core/os2_table.cc",
-    "cpp/src/sfntly/table/core/os2_table.h",
-    "cpp/src/sfntly/table/font_data_table.cc",
-    "cpp/src/sfntly/table/font_data_table.h",
-    "cpp/src/sfntly/table/generic_table_builder.cc",
-    "cpp/src/sfntly/table/generic_table_builder.h",
-    "cpp/src/sfntly/table/header.cc",
-    "cpp/src/sfntly/table/header.h",
-    "cpp/src/sfntly/table/subtable.cc",
-    "cpp/src/sfntly/table/subtable.h",
-    "cpp/src/sfntly/table/subtable_container_table.h",
-    "cpp/src/sfntly/table/table.cc",
-    "cpp/src/sfntly/table/table.h",
-    "cpp/src/sfntly/table/table_based_table_builder.cc",
-    "cpp/src/sfntly/table/table_based_table_builder.h",
-    "cpp/src/sfntly/table/truetype/glyph_table.cc",
-    "cpp/src/sfntly/table/truetype/glyph_table.h",
-    "cpp/src/sfntly/table/truetype/loca_table.cc",
-    "cpp/src/sfntly/table/truetype/loca_table.h",
-    "cpp/src/sfntly/tag.cc",
-    "cpp/src/sfntly/tag.h",
+    "src/cpp/src/sample/chromium/font_subsetter.cc",
+    "src/cpp/src/sample/chromium/font_subsetter.h",
+    "src/cpp/src/sample/chromium/subsetter_impl.cc",
+    "src/cpp/src/sample/chromium/subsetter_impl.h",
+    "src/cpp/src/sfntly/data/byte_array.cc",
+    "src/cpp/src/sfntly/data/byte_array.h",
+    "src/cpp/src/sfntly/data/font_data.cc",
+    "src/cpp/src/sfntly/data/font_data.h",
+    "src/cpp/src/sfntly/data/font_input_stream.cc",
+    "src/cpp/src/sfntly/data/font_input_stream.h",
+    "src/cpp/src/sfntly/data/font_output_stream.cc",
+    "src/cpp/src/sfntly/data/font_output_stream.h",
+    "src/cpp/src/sfntly/data/growable_memory_byte_array.cc",
+    "src/cpp/src/sfntly/data/growable_memory_byte_array.h",
+    "src/cpp/src/sfntly/data/memory_byte_array.cc",
+    "src/cpp/src/sfntly/data/memory_byte_array.h",
+    "src/cpp/src/sfntly/data/readable_font_data.cc",
+    "src/cpp/src/sfntly/data/readable_font_data.h",
+    "src/cpp/src/sfntly/data/writable_font_data.cc",
+    "src/cpp/src/sfntly/data/writable_font_data.h",
+    "src/cpp/src/sfntly/font.cc",
+    "src/cpp/src/sfntly/font.h",
+    "src/cpp/src/sfntly/font_factory.cc",
+    "src/cpp/src/sfntly/font_factory.h",
+    "src/cpp/src/sfntly/math/fixed1616.h",
+    "src/cpp/src/sfntly/math/font_math.h",
+    "src/cpp/src/sfntly/port/atomic.h",
+    "src/cpp/src/sfntly/port/config.h",
+    "src/cpp/src/sfntly/port/endian.h",
+    "src/cpp/src/sfntly/port/exception_type.h",
+    "src/cpp/src/sfntly/port/file_input_stream.cc",
+    "src/cpp/src/sfntly/port/file_input_stream.h",
+    "src/cpp/src/sfntly/port/input_stream.h",
+    "src/cpp/src/sfntly/port/lock.cc",
+    "src/cpp/src/sfntly/port/lock.h",
+    "src/cpp/src/sfntly/port/memory_input_stream.cc",
+    "src/cpp/src/sfntly/port/memory_input_stream.h",
+    "src/cpp/src/sfntly/port/memory_output_stream.cc",
+    "src/cpp/src/sfntly/port/memory_output_stream.h",
+    "src/cpp/src/sfntly/port/output_stream.h",
+    "src/cpp/src/sfntly/port/refcount.h",
+    "src/cpp/src/sfntly/port/type.h",
+    "src/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc",
+    "src/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_glyph.cc",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_glyph.h",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_size_table.cc",
+    "src/cpp/src/sfntly/table/bitmap/bitmap_size_table.h",
+    "src/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc",
+    "src/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h",
+    "src/cpp/src/sfntly/table/bitmap/ebdt_table.cc",
+    "src/cpp/src/sfntly/table/bitmap/ebdt_table.h",
+    "src/cpp/src/sfntly/table/bitmap/eblc_table.cc",
+    "src/cpp/src/sfntly/table/bitmap/eblc_table.h",
+    "src/cpp/src/sfntly/table/bitmap/ebsc_table.cc",
+    "src/cpp/src/sfntly/table/bitmap/ebsc_table.h",
+    "src/cpp/src/sfntly/table/bitmap/glyph_metrics.cc",
+    "src/cpp/src/sfntly/table/bitmap/glyph_metrics.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format2.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format4.h",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc",
+    "src/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h",
+    "src/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc",
+    "src/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h",
+    "src/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc",
+    "src/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h",
+    "src/cpp/src/sfntly/table/byte_array_table_builder.cc",
+    "src/cpp/src/sfntly/table/byte_array_table_builder.h",
+    "src/cpp/src/sfntly/table/core/cmap_table.cc",
+    "src/cpp/src/sfntly/table/core/cmap_table.h",
+    "src/cpp/src/sfntly/table/core/font_header_table.cc",
+    "src/cpp/src/sfntly/table/core/font_header_table.h",
+    "src/cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc",
+    "src/cpp/src/sfntly/table/core/horizontal_device_metrics_table.h",
+    "src/cpp/src/sfntly/table/core/horizontal_header_table.cc",
+    "src/cpp/src/sfntly/table/core/horizontal_header_table.h",
+    "src/cpp/src/sfntly/table/core/horizontal_metrics_table.cc",
+    "src/cpp/src/sfntly/table/core/horizontal_metrics_table.h",
+    "src/cpp/src/sfntly/table/core/maximum_profile_table.cc",
+    "src/cpp/src/sfntly/table/core/maximum_profile_table.h",
+    "src/cpp/src/sfntly/table/core/name_table.cc",
+    "src/cpp/src/sfntly/table/core/name_table.h",
+    "src/cpp/src/sfntly/table/core/os2_table.cc",
+    "src/cpp/src/sfntly/table/core/os2_table.h",
+    "src/cpp/src/sfntly/table/font_data_table.cc",
+    "src/cpp/src/sfntly/table/font_data_table.h",
+    "src/cpp/src/sfntly/table/generic_table_builder.cc",
+    "src/cpp/src/sfntly/table/generic_table_builder.h",
+    "src/cpp/src/sfntly/table/header.cc",
+    "src/cpp/src/sfntly/table/header.h",
+    "src/cpp/src/sfntly/table/subtable.cc",
+    "src/cpp/src/sfntly/table/subtable.h",
+    "src/cpp/src/sfntly/table/subtable_container_table.h",
+    "src/cpp/src/sfntly/table/table.cc",
+    "src/cpp/src/sfntly/table/table.h",
+    "src/cpp/src/sfntly/table/table_based_table_builder.cc",
+    "src/cpp/src/sfntly/table/table_based_table_builder.h",
+    "src/cpp/src/sfntly/table/truetype/glyph_table.cc",
+    "src/cpp/src/sfntly/table/truetype/glyph_table.h",
+    "src/cpp/src/sfntly/table/truetype/loca_table.cc",
+    "src/cpp/src/sfntly/table/truetype/loca_table.h",
+    "src/cpp/src/sfntly/tag.cc",
+    "src/cpp/src/sfntly/tag.h",
   ]
 
   defines = [ "SFNTLY_NO_EXCEPTION" ]
-  include_dirs = [ "cpp/src" ]
+  include_dirs = [ "src/cpp/src" ]
 
+  # This is the equivalent to the following in sfntly.gyp.
+  # 'msvs_disabled_warnings': [ 4267 ],
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
 
diff --git a/third_party/sfntly/README.chromium b/third_party/sfntly/README.chromium
index d351bd5..e9a0762 100644
--- a/third_party/sfntly/README.chromium
+++ b/third_party/sfntly/README.chromium
@@ -1,7 +1,6 @@
 Name: sfntly
-URL: http://code.google.com/p/sfntly/
-Version: unknown
-Revision: 111
+URL: https://github.com/googlei18n/sfntly
+Version: 130f832eddf98467e6578b548cb74ce17d04a26d
 Security Critical: yes
 License: Apache 2.0
 License File: COPYING.txt
@@ -12,9 +11,4 @@
 PDF generated in print preview so that the result PDF documents are
 significantly smaller and loaded faster.
 
-Local files (not taken from upstream):
-README.chromium
-src/subsetter/*
-
 COPYING.txt is the license file copied from upstream.
-A sfntly.gyp file has been added for building with Chromium.
diff --git a/third_party/sfntly/sfntly.gyp b/third_party/sfntly/sfntly.gyp
index f76b820..df337991 100644
--- a/third_party/sfntly/sfntly.gyp
+++ b/third_party/sfntly/sfntly.gyp
@@ -11,122 +11,122 @@
       'target_name': 'sfntly',
       'type': 'static_library',
       'sources': [
-        'cpp/src/sfntly/data/byte_array.cc',
-        'cpp/src/sfntly/data/byte_array.h',
-        'cpp/src/sfntly/data/font_data.cc',
-        'cpp/src/sfntly/data/font_data.h',
-        'cpp/src/sfntly/data/font_input_stream.cc',
-        'cpp/src/sfntly/data/font_input_stream.h',
-        'cpp/src/sfntly/data/font_output_stream.cc',
-        'cpp/src/sfntly/data/font_output_stream.h',
-        'cpp/src/sfntly/data/growable_memory_byte_array.cc',
-        'cpp/src/sfntly/data/growable_memory_byte_array.h',
-        'cpp/src/sfntly/data/memory_byte_array.cc',
-        'cpp/src/sfntly/data/memory_byte_array.h',
-        'cpp/src/sfntly/data/readable_font_data.cc',
-        'cpp/src/sfntly/data/readable_font_data.h',
-        'cpp/src/sfntly/data/writable_font_data.cc',
-        'cpp/src/sfntly/data/writable_font_data.h',
-        'cpp/src/sfntly/font.cc',
-        'cpp/src/sfntly/font.h',
-        'cpp/src/sfntly/font_factory.cc',
-        'cpp/src/sfntly/font_factory.h',
-        'cpp/src/sfntly/math/fixed1616.h',
-        'cpp/src/sfntly/math/font_math.h',
-        'cpp/src/sfntly/port/atomic.h',
-        'cpp/src/sfntly/port/config.h',
-        'cpp/src/sfntly/port/endian.h',
-        'cpp/src/sfntly/port/exception_type.h',
-        'cpp/src/sfntly/port/file_input_stream.cc',
-        'cpp/src/sfntly/port/file_input_stream.h',
-        'cpp/src/sfntly/port/input_stream.h',
-        'cpp/src/sfntly/port/lock.cc',
-        'cpp/src/sfntly/port/lock.h',
-        'cpp/src/sfntly/port/memory_input_stream.cc',
-        'cpp/src/sfntly/port/memory_input_stream.h',
-        'cpp/src/sfntly/port/memory_output_stream.cc',
-        'cpp/src/sfntly/port/memory_output_stream.h',
-        'cpp/src/sfntly/port/output_stream.h',
-        'cpp/src/sfntly/port/refcount.h',
-        'cpp/src/sfntly/port/type.h',
-        'cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc',
-        'cpp/src/sfntly/table/bitmap/big_glyph_metrics.h',
-        'cpp/src/sfntly/table/bitmap/bitmap_glyph.cc',
-        'cpp/src/sfntly/table/bitmap/bitmap_glyph.h',
-        'cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc',
-        'cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h',
-        'cpp/src/sfntly/table/bitmap/bitmap_size_table.cc',
-        'cpp/src/sfntly/table/bitmap/bitmap_size_table.h',
-        'cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc',
-        'cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h',
-        'cpp/src/sfntly/table/bitmap/ebdt_table.cc',
-        'cpp/src/sfntly/table/bitmap/ebdt_table.h',
-        'cpp/src/sfntly/table/bitmap/eblc_table.cc',
-        'cpp/src/sfntly/table/bitmap/eblc_table.h',
-        'cpp/src/sfntly/table/bitmap/ebsc_table.cc',
-        'cpp/src/sfntly/table/bitmap/ebsc_table.h',
-        'cpp/src/sfntly/table/bitmap/glyph_metrics.cc',
-        'cpp/src/sfntly/table/bitmap/glyph_metrics.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format1.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format2.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format3.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format4.h',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc',
-        'cpp/src/sfntly/table/bitmap/index_sub_table_format5.h',
-        'cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc',
-        'cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h',
-        'cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc',
-        'cpp/src/sfntly/table/bitmap/small_glyph_metrics.h',
-        'cpp/src/sfntly/table/byte_array_table_builder.cc',
-        'cpp/src/sfntly/table/byte_array_table_builder.h',
-        'cpp/src/sfntly/table/core/cmap_table.cc',
-        'cpp/src/sfntly/table/core/cmap_table.h',
-        'cpp/src/sfntly/table/core/font_header_table.cc',
-        'cpp/src/sfntly/table/core/font_header_table.h',
-        'cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc',
-        'cpp/src/sfntly/table/core/horizontal_device_metrics_table.h',
-        'cpp/src/sfntly/table/core/horizontal_header_table.cc',
-        'cpp/src/sfntly/table/core/horizontal_header_table.h',
-        'cpp/src/sfntly/table/core/horizontal_metrics_table.cc',
-        'cpp/src/sfntly/table/core/horizontal_metrics_table.h',
-        'cpp/src/sfntly/table/core/maximum_profile_table.cc',
-        'cpp/src/sfntly/table/core/maximum_profile_table.h',
-        'cpp/src/sfntly/table/core/name_table.cc',
-        'cpp/src/sfntly/table/core/name_table.h',
-        'cpp/src/sfntly/table/core/os2_table.cc',
-        'cpp/src/sfntly/table/core/os2_table.h',
-        'cpp/src/sfntly/table/font_data_table.cc',
-        'cpp/src/sfntly/table/font_data_table.h',
-        'cpp/src/sfntly/table/generic_table_builder.cc',
-        'cpp/src/sfntly/table/generic_table_builder.h',
-        'cpp/src/sfntly/table/header.cc',
-        'cpp/src/sfntly/table/header.h',
-        'cpp/src/sfntly/table/subtable.cc',
-        'cpp/src/sfntly/table/subtable.h',
-        'cpp/src/sfntly/table/subtable_container_table.h',
-        'cpp/src/sfntly/table/table.cc',
-        'cpp/src/sfntly/table/table.h',
-        'cpp/src/sfntly/table/table_based_table_builder.cc',
-        'cpp/src/sfntly/table/table_based_table_builder.h',
-        'cpp/src/sfntly/table/truetype/glyph_table.cc',
-        'cpp/src/sfntly/table/truetype/glyph_table.h',
-        'cpp/src/sfntly/table/truetype/loca_table.cc',
-        'cpp/src/sfntly/table/truetype/loca_table.h',
-        'cpp/src/sfntly/tag.cc',
-        'cpp/src/sfntly/tag.h',
-        'cpp/src/sample/chromium/font_subsetter.cc',
-        'cpp/src/sample/chromium/font_subsetter.h',
-        'cpp/src/sample/chromium/subsetter_impl.cc',
-        'cpp/src/sample/chromium/subsetter_impl.h',
+        'src/cpp/src/sfntly/data/byte_array.cc',
+        'src/cpp/src/sfntly/data/byte_array.h',
+        'src/cpp/src/sfntly/data/font_data.cc',
+        'src/cpp/src/sfntly/data/font_data.h',
+        'src/cpp/src/sfntly/data/font_input_stream.cc',
+        'src/cpp/src/sfntly/data/font_input_stream.h',
+        'src/cpp/src/sfntly/data/font_output_stream.cc',
+        'src/cpp/src/sfntly/data/font_output_stream.h',
+        'src/cpp/src/sfntly/data/growable_memory_byte_array.cc',
+        'src/cpp/src/sfntly/data/growable_memory_byte_array.h',
+        'src/cpp/src/sfntly/data/memory_byte_array.cc',
+        'src/cpp/src/sfntly/data/memory_byte_array.h',
+        'src/cpp/src/sfntly/data/readable_font_data.cc',
+        'src/cpp/src/sfntly/data/readable_font_data.h',
+        'src/cpp/src/sfntly/data/writable_font_data.cc',
+        'src/cpp/src/sfntly/data/writable_font_data.h',
+        'src/cpp/src/sfntly/font.cc',
+        'src/cpp/src/sfntly/font.h',
+        'src/cpp/src/sfntly/font_factory.cc',
+        'src/cpp/src/sfntly/font_factory.h',
+        'src/cpp/src/sfntly/math/fixed1616.h',
+        'src/cpp/src/sfntly/math/font_math.h',
+        'src/cpp/src/sfntly/port/atomic.h',
+        'src/cpp/src/sfntly/port/config.h',
+        'src/cpp/src/sfntly/port/endian.h',
+        'src/cpp/src/sfntly/port/exception_type.h',
+        'src/cpp/src/sfntly/port/file_input_stream.cc',
+        'src/cpp/src/sfntly/port/file_input_stream.h',
+        'src/cpp/src/sfntly/port/input_stream.h',
+        'src/cpp/src/sfntly/port/lock.cc',
+        'src/cpp/src/sfntly/port/lock.h',
+        'src/cpp/src/sfntly/port/memory_input_stream.cc',
+        'src/cpp/src/sfntly/port/memory_input_stream.h',
+        'src/cpp/src/sfntly/port/memory_output_stream.cc',
+        'src/cpp/src/sfntly/port/memory_output_stream.h',
+        'src/cpp/src/sfntly/port/output_stream.h',
+        'src/cpp/src/sfntly/port/refcount.h',
+        'src/cpp/src/sfntly/port/type.h',
+        'src/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc',
+        'src/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_glyph.cc',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_glyph.h',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.h',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_size_table.cc',
+        'src/cpp/src/sfntly/table/bitmap/bitmap_size_table.h',
+        'src/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc',
+        'src/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.h',
+        'src/cpp/src/sfntly/table/bitmap/ebdt_table.cc',
+        'src/cpp/src/sfntly/table/bitmap/ebdt_table.h',
+        'src/cpp/src/sfntly/table/bitmap/eblc_table.cc',
+        'src/cpp/src/sfntly/table/bitmap/eblc_table.h',
+        'src/cpp/src/sfntly/table/bitmap/ebsc_table.cc',
+        'src/cpp/src/sfntly/table/bitmap/ebsc_table.h',
+        'src/cpp/src/sfntly/table/bitmap/glyph_metrics.cc',
+        'src/cpp/src/sfntly/table/bitmap/glyph_metrics.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format2.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format4.h',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc',
+        'src/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h',
+        'src/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc',
+        'src/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.h',
+        'src/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc',
+        'src/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h',
+        'src/cpp/src/sfntly/table/byte_array_table_builder.cc',
+        'src/cpp/src/sfntly/table/byte_array_table_builder.h',
+        'src/cpp/src/sfntly/table/core/cmap_table.cc',
+        'src/cpp/src/sfntly/table/core/cmap_table.h',
+        'src/cpp/src/sfntly/table/core/font_header_table.cc',
+        'src/cpp/src/sfntly/table/core/font_header_table.h',
+        'src/cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc',
+        'src/cpp/src/sfntly/table/core/horizontal_device_metrics_table.h',
+        'src/cpp/src/sfntly/table/core/horizontal_header_table.cc',
+        'src/cpp/src/sfntly/table/core/horizontal_header_table.h',
+        'src/cpp/src/sfntly/table/core/horizontal_metrics_table.cc',
+        'src/cpp/src/sfntly/table/core/horizontal_metrics_table.h',
+        'src/cpp/src/sfntly/table/core/maximum_profile_table.cc',
+        'src/cpp/src/sfntly/table/core/maximum_profile_table.h',
+        'src/cpp/src/sfntly/table/core/name_table.cc',
+        'src/cpp/src/sfntly/table/core/name_table.h',
+        'src/cpp/src/sfntly/table/core/os2_table.cc',
+        'src/cpp/src/sfntly/table/core/os2_table.h',
+        'src/cpp/src/sfntly/table/font_data_table.cc',
+        'src/cpp/src/sfntly/table/font_data_table.h',
+        'src/cpp/src/sfntly/table/generic_table_builder.cc',
+        'src/cpp/src/sfntly/table/generic_table_builder.h',
+        'src/cpp/src/sfntly/table/header.cc',
+        'src/cpp/src/sfntly/table/header.h',
+        'src/cpp/src/sfntly/table/subtable.cc',
+        'src/cpp/src/sfntly/table/subtable.h',
+        'src/cpp/src/sfntly/table/subtable_container_table.h',
+        'src/cpp/src/sfntly/table/table.cc',
+        'src/cpp/src/sfntly/table/table.h',
+        'src/cpp/src/sfntly/table/table_based_table_builder.cc',
+        'src/cpp/src/sfntly/table/table_based_table_builder.h',
+        'src/cpp/src/sfntly/table/truetype/glyph_table.cc',
+        'src/cpp/src/sfntly/table/truetype/glyph_table.h',
+        'src/cpp/src/sfntly/table/truetype/loca_table.cc',
+        'src/cpp/src/sfntly/table/truetype/loca_table.h',
+        'src/cpp/src/sfntly/tag.cc',
+        'src/cpp/src/sfntly/tag.h',
+        'src/cpp/src/sample/chromium/font_subsetter.cc',
+        'src/cpp/src/sample/chromium/font_subsetter.h',
+        'src/cpp/src/sample/chromium/subsetter_impl.cc',
+        'src/cpp/src/sample/chromium/subsetter_impl.h',
       ],
       'include_dirs': [
-        'cpp/src', '../..',
+        'src/cpp/src',
       ],
       # This macro must be define to suppress the use of exception
       'defines': [
diff --git a/third_party/webrtc_overrides/DEPS b/third_party/webrtc_overrides/DEPS
new file mode 100644
index 0000000..d2817be
--- /dev/null
+++ b/third_party/webrtc_overrides/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  '+base',
+  '+net/base',
+  '+third_party/webrtc',
+]
diff --git a/third_party/webrtc_overrides/OWNERS b/third_party/webrtc_overrides/OWNERS
new file mode 100644
index 0000000..c4df37e
--- /dev/null
+++ b/third_party/webrtc_overrides/OWNERS
@@ -0,0 +1,3 @@
+ajm@chromium.org
+grunell@chromium.org
+tommi@chromium.org
diff --git a/third_party/webrtc_overrides/README.chromium b/third_party/webrtc_overrides/README.chromium
new file mode 100644
index 0000000..5ed2ca74
--- /dev/null
+++ b/third_party/webrtc_overrides/README.chromium
@@ -0,0 +1,20 @@
+Name: WebRTC
+URL: http://www.webrtc.org
+Version: 0
+Revision: 0
+License: BSD
+License File: ../webrtc/LICENSE
+Security Critical: yes
+
+Description:
+This folder contains WebRTC files (third_party/webrtc) that should be
+overridden. The reason for this folder to be separate from third_party/webrtc is
+that WebRTC is pulled directly into third_party/webrtc and the overrides need to
+be in the Chromium repo since they depend on Chromium code.
+
+For information on WebRTC, see third_party/webrtc/README.chromium.
+
+Third party code used in this project is described in the file
+third_party/webrtc/LICENSE_THIRD_PARTY.
+
+Local Modifications:
diff --git a/third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h b/third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h
new file mode 100644
index 0000000..fd33374
--- /dev/null
+++ b/third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h
@@ -0,0 +1,152 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_DIAGNOSTIC_LOGGING_H_
+#define THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_DIAGNOSTIC_LOGGING_H_
+
+#include <sstream>
+#include <string>
+
+#include "third_party/webrtc/base/checks.h"
+#include "third_party/webrtc/base/scoped_ref_ptr.h"
+
+namespace rtc {
+
+///////////////////////////////////////////////////////////////////////////////
+// ConstantLabel can be used to easily generate string names from constant
+// values.  This can be useful for logging descriptive names of error messages.
+// Usage:
+//   const ConstantLabel LIBRARY_ERRORS[] = {
+//     KLABEL(SOME_ERROR),
+//     KLABEL(SOME_OTHER_ERROR),
+//     ...
+//     LASTLABEL
+//   }
+//
+//   int err = LibraryFunc();
+//   LOG(LS_ERROR) << "LibraryFunc returned: "
+//                 << ErrorName(err, LIBRARY_ERRORS);
+
+struct ConstantLabel {
+  int value;
+  const char* label;
+};
+#define KLABEL(x) { x, #x }
+#define LASTLABEL { 0, 0 }
+
+const char* FindLabel(int value, const ConstantLabel entries[]);
+std::string ErrorName(int err, const ConstantLabel* err_table);
+
+//////////////////////////////////////////////////////////////////////
+// Note that the non-standard LoggingSeverity aliases exist because they are
+// still in broad use.  The meanings of the levels are:
+//  LS_SENSITIVE: Information which should only be logged with the consent
+//   of the user, due to privacy concerns.
+//  LS_VERBOSE: This level is for data which we do not want to appear in the
+//   normal debug log, but should appear in diagnostic logs.
+//  LS_INFO: Chatty level used in debugging for all sorts of things, the default
+//   in debug builds.
+//  LS_WARNING: Something that may warrant investigation.
+//  LS_ERROR: Something that should not have occurred.
+// Note that LoggingSeverity is mapped over to chromiums verbosity levels where
+// anything lower than or equal to the current verbosity level is written to
+// file which is the opposite of logging severity in libjingle where higher
+// severity numbers than or equal to the current severity level are written to
+// file. Also, note that the values are explicitly defined here for convenience
+// since the command line flag must be set using numerical values.
+// TODO(tommi): To keep things simple, we should just use the same values for
+// these constants as Chrome does.
+enum LoggingSeverity { LS_ERROR = 1,
+                       LS_WARNING = 2,
+                       LS_INFO = 3,
+                       LS_VERBOSE = 4,
+                       LS_SENSITIVE = 5,
+                       INFO = LS_INFO,
+                       WARNING = LS_WARNING,
+                       LERROR = LS_ERROR };
+
+// LogErrorContext assists in interpreting the meaning of an error value.
+enum LogErrorContext {
+  ERRCTX_NONE,
+  ERRCTX_ERRNO,     // System-local errno
+  ERRCTX_HRESULT,   // Windows HRESULT
+  ERRCTX_OSSTATUS,  // MacOS OSStatus
+
+  // Abbreviations for LOG_E macro
+  ERRCTX_EN = ERRCTX_ERRNO,     // LOG_E(sev, EN, x)
+  ERRCTX_HR = ERRCTX_HRESULT,   // LOG_E(sev, HR, x)
+  ERRCTX_OS = ERRCTX_OSSTATUS,  // LOG_E(sev, OS, x)
+};
+
+// Class that writes a log message to the logging delegate ("WebRTC logging
+// stream" in Chrome) and to Chrome's logging stream.
+class DiagnosticLogMessage {
+ public:
+  DiagnosticLogMessage(const char* file, int line, LoggingSeverity severity,
+                       LogErrorContext err_ctx, int err);
+  DiagnosticLogMessage(const char* file, int line, LoggingSeverity severity,
+                       LogErrorContext err_ctx, int err, const char* module);
+  ~DiagnosticLogMessage();
+
+  void CreateTimestamp();
+
+  std::ostream& stream() { return print_stream_; }
+
+ private:
+  const char* file_name_;
+  const int line_;
+  const LoggingSeverity severity_;
+  const bool log_to_chrome_;
+
+  std::string extra_;
+
+  std::ostringstream print_stream_;
+};
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros.  This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+class LogMessageVoidify {
+ public:
+  LogMessageVoidify() { }
+  // This has to be an operator with a precedence lower than << but
+  // higher than ?:
+  void operator&(std::ostream&) { }
+};
+
+//////////////////////////////////////////////////////////////////////
+// Logging Helpers
+//////////////////////////////////////////////////////////////////////
+
+class LogMultilineState {
+ public:
+  size_t unprintable_count_[2];
+  LogMultilineState() {
+    unprintable_count_[0] = unprintable_count_[1] = 0;
+  }
+};
+
+class LogMessage {
+ public:
+  static void LogToDebug(int min_sev);
+};
+
+// When possible, pass optional state variable to track various data across
+// multiple calls to LogMultiline.  Otherwise, pass NULL.
+void LogMultiline(LoggingSeverity level, const char* label, bool input,
+                  const void* data, size_t len, bool hex_mode,
+                  LogMultilineState* state);
+
+// TODO(grunell): Change name to InitDiagnosticLoggingDelegate or
+// InitDiagnosticLogging. Change also in init_webrtc.h/cc.
+// TODO(grunell): typedef the delegate function.
+void InitDiagnosticLoggingDelegateFunction(
+    void (*delegate)(const std::string&));
+
+void SetExtraLoggingInit(
+    void (*function)(void (*delegate)(const std::string&)));
+
+}  // namespace rtc
+
+#endif  // THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_DIAGNOSTIC_LOGGING_H_
diff --git a/third_party/webrtc_overrides/webrtc/base/logging.cc b/third_party/webrtc_overrides/webrtc/base/logging.cc
new file mode 100644
index 0000000..ce4fbd9
--- /dev/null
+++ b/third_party/webrtc_overrides/webrtc/base/logging.cc
@@ -0,0 +1,372 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// NOTE:
+// Since this file includes Chromium headers, it must not include
+// third_party/webrtc/base/logging.h since it defines some of the same macros as
+// Chromium does and we'll run into conflicts.
+
+#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
+#include <CoreServices/CoreServices.h>
+#endif  // OS_MACOSX
+
+#include <algorithm>
+#include <iomanip>
+
+#include "base/atomicops.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/threading/platform_thread.h"
+#include "third_party/webrtc/base/ipaddress.h"
+#include "third_party/webrtc/base/stream.h"
+#include "third_party/webrtc/base/stringencode.h"
+#include "third_party/webrtc/base/stringutils.h"
+#include "third_party/webrtc/base/timeutils.h"
+#include "third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h"
+
+// From this file we can't use VLOG since it expands into usage of the __FILE__
+// macro (for correct filtering). The actual logging call from DIAGNOSTIC_LOG in
+// ~DiagnosticLogMessage. Note that the second parameter to the LAZY_STREAM
+// macro is true since the filter check has already been done for
+// DIAGNOSTIC_LOG.
+#define LOG_LAZY_STREAM_DIRECT(file_name, line_number, sev)              \
+  LAZY_STREAM(logging::LogMessage(file_name, line_number, sev).stream(), \
+                  true)
+
+namespace rtc {
+
+void (*g_logging_delegate_function)(const std::string&) = NULL;
+void (*g_extra_logging_init_function)(
+    void (*logging_delegate_function)(const std::string&)) = NULL;
+#ifndef NDEBUG
+static_assert(sizeof(base::subtle::Atomic32) == sizeof(base::PlatformThreadId),
+              "Atomic32 not same size as PlatformThreadId");
+base::subtle::Atomic32 g_init_logging_delegate_thread_id = 0;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// Constant Labels
+/////////////////////////////////////////////////////////////////////////////
+
+const char* FindLabel(int value, const ConstantLabel entries[]) {
+  for (int i = 0; entries[i].label; ++i) {
+    if (value == entries[i].value) return entries[i].label;
+  }
+  return 0;
+}
+
+std::string ErrorName(int err, const ConstantLabel* err_table) {
+  if (err == 0)
+    return "No error";
+
+  if (err_table != 0) {
+    if (const char * value = FindLabel(err, err_table))
+      return value;
+  }
+
+  char buffer[16];
+  base::snprintf(buffer, sizeof(buffer), "0x%08x", err);
+  return buffer;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Log helper functions
+/////////////////////////////////////////////////////////////////////////////
+
+inline int WebRtcSevToChromeSev(LoggingSeverity sev) {
+  switch (sev) {
+    case LS_ERROR:
+      return ::logging::LOG_ERROR;
+    case LS_WARNING:
+      return ::logging::LOG_WARNING;
+    case LS_INFO:
+      return ::logging::LOG_INFO;
+    case LS_VERBOSE:
+    case LS_SENSITIVE:
+      return ::logging::LOG_VERBOSE;
+    default:
+      NOTREACHED();
+      return ::logging::LOG_FATAL;
+  }
+}
+
+inline int WebRtcVerbosityLevel(LoggingSeverity sev) {
+  switch (sev) {
+    case LS_ERROR:
+      return -2;
+    case LS_WARNING:
+      return -1;
+    case LS_INFO:  // We treat 'info' and 'verbose' as the same verbosity level.
+    case LS_VERBOSE:
+      return 1;
+    case LS_SENSITIVE:
+      return 2;
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
+// Generates extra information for LOG_E.
+static std::string GenerateExtra(LogErrorContext err_ctx,
+                                 int err,
+                                 const char* module) {
+  if (err_ctx != ERRCTX_NONE) {
+    std::ostringstream tmp;
+    tmp << ": ";
+    tmp << "[0x" << std::setfill('0') << std::hex << std::setw(8) << err << "]";
+    switch (err_ctx) {
+      case ERRCTX_ERRNO:
+        tmp << " " << strerror(err);
+        break;
+#if defined(WEBRTC_WIN)
+      case ERRCTX_HRESULT: {
+        char msgbuf[256];
+        DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
+        HMODULE hmod = GetModuleHandleA(module);
+        if (hmod)
+          flags |= FORMAT_MESSAGE_FROM_HMODULE;
+        if (DWORD len = FormatMessageA(
+            flags, hmod, err,
+            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+            msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL)) {
+          while ((len > 0) &&
+              isspace(static_cast<unsigned char>(msgbuf[len-1]))) {
+            msgbuf[--len] = 0;
+          }
+          tmp << " " << msgbuf;
+        }
+        break;
+      }
+#endif  // OS_WIN
+#if defined(WEBRTC_IOS)
+      case ERRCTX_OSSTATUS:
+        tmp << " " << "Unknown LibJingle error: " << err;
+        break;
+#elif defined(WEBRTC_MAC)
+      case ERRCTX_OSSTATUS: {
+        tmp << " " << nonnull(GetMacOSStatusErrorString(err), "Unknown error");
+        if (const char* desc = GetMacOSStatusCommentString(err)) {
+          tmp << ": " << desc;
+        }
+        break;
+      }
+#endif  // OS_MACOSX
+      default:
+        break;
+    }
+    return tmp.str();
+  }
+  return "";
+}
+
+DiagnosticLogMessage::DiagnosticLogMessage(const char* file,
+                                           int line,
+                                           LoggingSeverity severity,
+                                           LogErrorContext err_ctx,
+                                           int err)
+    : file_name_(file),
+      line_(line),
+      severity_(severity),
+      log_to_chrome_(CheckVlogIsOnHelper(severity, file, strlen(file) + 1)) {
+  extra_ = GenerateExtra(err_ctx, err, NULL);
+}
+
+DiagnosticLogMessage::DiagnosticLogMessage(const char* file,
+                                           int line,
+                                           LoggingSeverity severity,
+                                           LogErrorContext err_ctx,
+                                           int err,
+                                           const char* module)
+    : file_name_(file),
+      line_(line),
+      severity_(severity),
+      log_to_chrome_(CheckVlogIsOnHelper(severity, file, strlen(file) + 1)) {
+  extra_ = GenerateExtra(err_ctx, err, module);
+}
+
+DiagnosticLogMessage::~DiagnosticLogMessage() {
+  const bool call_delegate =
+      g_logging_delegate_function && severity_ <= LS_INFO;
+
+  if (call_delegate || log_to_chrome_) {
+    print_stream_ << extra_;
+    const std::string& str = print_stream_.str();
+    if (log_to_chrome_) {
+      LOG_LAZY_STREAM_DIRECT(file_name_, line_,
+          rtc::WebRtcSevToChromeSev(severity_)) << str;
+    }
+
+    if (g_logging_delegate_function && severity_ <= LS_INFO) {
+      g_logging_delegate_function(str);
+    }
+  }
+}
+
+// static
+void LogMessage::LogToDebug(int min_sev) {
+  logging::SetMinLogLevel(min_sev);
+}
+
+// Note: this function is a copy from the overriden libjingle implementation.
+void LogMultiline(LoggingSeverity level, const char* label, bool input,
+                  const void* data, size_t len, bool hex_mode,
+                  LogMultilineState* state) {
+  // TODO(grunell): This will not do the expected verbosity level checking. We
+  // need a macro for the multiline logging.
+  // https://code.google.com/p/webrtc/issues/detail?id=5011
+  if (!LOG_CHECK_LEVEL_V(level))
+    return;
+
+  const char * direction = (input ? " << " : " >> ");
+
+  // NULL data means to flush our count of unprintable characters.
+  if (!data) {
+    if (state && state->unprintable_count_[input]) {
+      LOG_V(level) << label << direction << "## "
+                   << state->unprintable_count_[input]
+                   << " consecutive unprintable ##";
+      state->unprintable_count_[input] = 0;
+    }
+    return;
+  }
+
+  // The ctype classification functions want unsigned chars.
+  const unsigned char* udata = static_cast<const unsigned char*>(data);
+
+  if (hex_mode) {
+    const size_t LINE_SIZE = 24;
+    char hex_line[LINE_SIZE * 9 / 4 + 2], asc_line[LINE_SIZE + 1];
+    while (len > 0) {
+      memset(asc_line, ' ', sizeof(asc_line));
+      memset(hex_line, ' ', sizeof(hex_line));
+      size_t line_len = std::min(len, LINE_SIZE);
+      for (size_t i = 0; i < line_len; ++i) {
+        unsigned char ch = udata[i];
+        asc_line[i] = isprint(ch) ? ch : '.';
+        hex_line[i*2 + i/4] = hex_encode(ch >> 4);
+        hex_line[i*2 + i/4 + 1] = hex_encode(ch & 0xf);
+      }
+      asc_line[sizeof(asc_line)-1] = 0;
+      hex_line[sizeof(hex_line)-1] = 0;
+      LOG_V(level) << label << direction
+                   << asc_line << " " << hex_line << " ";
+      udata += line_len;
+      len -= line_len;
+    }
+    return;
+  }
+
+  size_t consecutive_unprintable = state ? state->unprintable_count_[input] : 0;
+
+  const unsigned char* end = udata + len;
+  while (udata < end) {
+    const unsigned char* line = udata;
+    const unsigned char* end_of_line = strchrn<unsigned char>(udata,
+                                                              end - udata,
+                                                              '\n');
+    if (!end_of_line) {
+      udata = end_of_line = end;
+    } else {
+      udata = end_of_line + 1;
+    }
+
+    bool is_printable = true;
+
+    // If we are in unprintable mode, we need to see a line of at least
+    // kMinPrintableLine characters before we'll switch back.
+    const ptrdiff_t kMinPrintableLine = 4;
+    if (consecutive_unprintable && ((end_of_line - line) < kMinPrintableLine)) {
+      is_printable = false;
+    } else {
+      // Determine if the line contains only whitespace and printable
+      // characters.
+      bool is_entirely_whitespace = true;
+      for (const unsigned char* pos = line; pos < end_of_line; ++pos) {
+        if (isspace(*pos))
+          continue;
+        is_entirely_whitespace = false;
+        if (!isprint(*pos)) {
+          is_printable = false;
+          break;
+        }
+      }
+      // Treat an empty line following unprintable data as unprintable.
+      if (consecutive_unprintable && is_entirely_whitespace) {
+        is_printable = false;
+      }
+    }
+    if (!is_printable) {
+      consecutive_unprintable += (udata - line);
+      continue;
+    }
+    // Print out the current line, but prefix with a count of prior unprintable
+    // characters.
+    if (consecutive_unprintable) {
+      LOG_V(level) << label << direction << "## " << consecutive_unprintable
+                  << " consecutive unprintable ##";
+      consecutive_unprintable = 0;
+    }
+    // Strip off trailing whitespace.
+    while ((end_of_line > line) && isspace(*(end_of_line-1))) {
+      --end_of_line;
+    }
+    // Filter out any private data
+    std::string substr(reinterpret_cast<const char*>(line), end_of_line - line);
+    std::string::size_type pos_private = substr.find("Email");
+    if (pos_private == std::string::npos) {
+      pos_private = substr.find("Passwd");
+    }
+    if (pos_private == std::string::npos) {
+      LOG_V(level) << label << direction << substr;
+    } else {
+      LOG_V(level) << label << direction << "## omitted for privacy ##";
+    }
+  }
+
+  if (state) {
+    state->unprintable_count_[input] = consecutive_unprintable;
+  }
+}
+
+void InitDiagnosticLoggingDelegateFunction(
+    void (*delegate)(const std::string&)) {
+#ifndef NDEBUG
+  // Ensure that this function is always called from the same thread.
+  base::subtle::NoBarrier_CompareAndSwap(&g_init_logging_delegate_thread_id, 0,
+      static_cast<base::subtle::Atomic32>(base::PlatformThread::CurrentId()));
+  DCHECK_EQ(
+      g_init_logging_delegate_thread_id,
+      static_cast<base::subtle::Atomic32>(base::PlatformThread::CurrentId()));
+#endif
+  CHECK(delegate);
+  // This function may be called with the same argument several times if the
+  // page is reloaded or there are several PeerConnections on one page with
+  // logging enabled. This is OK, we simply don't have to do anything.
+  if (delegate == g_logging_delegate_function)
+    return;
+  CHECK(!g_logging_delegate_function);
+#ifdef NDEBUG
+  IPAddress::set_strip_sensitive(true);
+#endif
+  g_logging_delegate_function = delegate;
+
+  if (g_extra_logging_init_function)
+    g_extra_logging_init_function(delegate);
+}
+
+void SetExtraLoggingInit(
+    void (*function)(void (*delegate)(const std::string&))) {
+  CHECK(function);
+  CHECK(!g_extra_logging_init_function);
+  g_extra_logging_init_function = function;
+}
+
+bool CheckVlogIsOnHelper(
+    rtc::LoggingSeverity severity, const char* file, size_t N) {
+  return rtc::WebRtcVerbosityLevel(severity) <=
+         ::logging::GetVlogLevelHelper(file, N);
+}
+
+}  // namespace rtc
diff --git a/third_party/webrtc_overrides/webrtc/base/logging.h b/third_party/webrtc_overrides/webrtc/base/logging.h
new file mode 100644
index 0000000..2d858ec
--- /dev/null
+++ b/third_party/webrtc_overrides/webrtc/base/logging.h
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium 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 overrides the logging macros in WebRTC (webrtc/base/logging.h).
+// Instead of using WebRTC's logging implementation, the WebRTC macros are
+// mapped to DIAGNOSTIC_LOGING. In it's implementation (DiagnosticLogMessage in
+// third_party/webrtc_overrides/webrtc/base/logging.h), the corresponding
+// base/logging.h macros (e.g. Chromium's VLOG) are used.
+// If this file is included outside of WebRTC/libjingle it should be included
+// after base/logging.h (if any) or compiler error or unexpected behavior may
+// occur (macros that have the same name in WebRTC as in Chromium will use
+// the WebRTC definition if this file is included first).
+
+// Setting the LoggingSeverity (and lower) that should be written to file should
+// be done via command line by specifying the flags:
+// --vmodule or --v please see base/logging.h for details on how to use them.
+// Specifying what file to write to is done using InitLogging also in
+// base/logging.h.
+
+// The macros and classes declared in here are not described as they are
+// NOT TO BE USED outside of WebRTC/libjingle.
+
+#ifndef THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_LOGGING_H_
+#define THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_LOGGING_H_
+
+#include "third_party/webrtc_overrides/webrtc/base/diagnostic_logging.h"
+
+//////////////////////////////////////////////////////////////////////
+// WebRTC macros which in DiagnosticLogMessage are mapped over to
+// their VLOG equivalent in base/logging.h.
+//////////////////////////////////////////////////////////////////////
+
+#if defined(LOGGING_INSIDE_WEBRTC)
+
+namespace rtc {
+
+// Note that |N| is the size *with* the null terminator.
+bool CheckVlogIsOnHelper(LoggingSeverity severity,
+                         const char* file, size_t N);
+
+template <size_t N>
+bool CheckVlogIsOn(LoggingSeverity severity, const char (&file)[N]) {
+  return CheckVlogIsOnHelper(severity, file, N);
+}
+
+}  // namespace rtc
+
+#define DIAGNOSTIC_LOG(sev, ctx, err, ...) \
+  rtc::DiagnosticLogMessage( \
+      __FILE__, __LINE__, sev, rtc::ERRCTX_ ## ctx, err, ##__VA_ARGS__).stream()
+
+#define LOG_CHECK_LEVEL(sev) CheckVlogIsOn(rtc::sev, __FILE__)
+#define LOG_CHECK_LEVEL_V(sev) CheckVlogIsOn(sev, __FILE__)
+
+#define LOG_V(sev) DIAGNOSTIC_LOG(sev, NONE, 0)
+#undef LOG
+#define LOG(sev) DIAGNOSTIC_LOG(rtc::sev, NONE, 0)
+
+// The _F version prefixes the message with the current function name.
+#if defined(__GNUC__) && defined(_DEBUG)
+#define LOG_F(sev) LOG(sev) << __PRETTY_FUNCTION__ << ": "
+#else
+#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
+#endif
+
+#define LOG_E(sev, ctx, err, ...) \
+  DIAGNOSTIC_LOG(rtc::sev, ctx, err, ##__VA_ARGS__)
+
+#undef LOG_ERRNO_EX
+#define LOG_ERRNO_EX(sev, err) LOG_E(sev, ERRNO, err)
+#undef LOG_ERRNO
+#define LOG_ERRNO(sev) LOG_ERRNO_EX(sev, errno)
+
+#if defined(WEBRTC_WIN)
+#define LOG_GLE_EX(sev, err) LOG_E(sev, HRESULT, err)
+#define LOG_GLE(sev) LOG_GLE_EX(sev, GetLastError())
+#define LOG_GLEM(sev, mod) LOG_E(sev, HRESULT, GetLastError(), mod)
+#define LOG_ERR_EX(sev, err) LOG_GLE_EX(sev, err)
+#define LOG_ERR(sev) LOG_GLE(sev)
+#define LAST_SYSTEM_ERROR (::GetLastError())
+#else
+#define LOG_ERR_EX(sev, err) LOG_ERRNO_EX(sev, err)
+#define LOG_ERR(sev) LOG_ERRNO(sev)
+#define LAST_SYSTEM_ERROR (errno)
+#endif  // OS_WIN
+
+#undef PLOG
+#define PLOG(sev, err) LOG_ERR_EX(sev, err)
+
+#endif  // LOGGING_INSIDE_WEBRTC
+
+#endif  // THIRD_PARTY_WEBRTC_OVERRIDES_WEBRTC_BASE_LOGGING_H_
diff --git a/third_party/webrtc_overrides/webrtc/base/win32socketinit.cc b/third_party/webrtc_overrides/webrtc/base/win32socketinit.cc
new file mode 100644
index 0000000..770f8f22
--- /dev/null
+++ b/third_party/webrtc_overrides/webrtc/base/win32socketinit.cc
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Redirect WebRTC's winsock initialization activity into Chromium's
+// singleton object that managest precisely that for the browser.
+
+#include "third_party/webrtc/base/win32socketinit.h"
+
+#include "net/base/winsock_init.h"
+
+#if !defined(WEBRTC_WIN)
+#error "Only compile this on Windows"
+#endif
+
+namespace rtc {
+
+void EnsureWinsockInit() {
+  net::EnsureWinsockInit();
+}
+
+}  // namespace rtc
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 12c935ac..0c3e578 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -24,6 +24,8 @@
     <classpathentry kind="src" path="base/android/java/src"/>
     <classpathentry kind="src" path="base/android/javatests/src"/>
     <classpathentry kind="src" path="base/test/android/javatests/src"/>
+    <classpathentry kind="src" path="blimp/client/android/java/src"/>
+    <classpathentry kind="src" path="blimp/client/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/sync_shell/javatests/src"/>
@@ -139,6 +141,7 @@
     <classpathentry kind="src" path="out/Debug/gen/enums/touch_device_types_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/touch_handle_orientation_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/url_request_failed_job_java"/>
+    <classpathentry kind="src" path="out/Debug/gen/enums/web_display_mode"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/web_input_event_java"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/web_text_input_type"/>
     <classpathentry kind="src" path="out/Debug/gen/enums/window_open_disposition_java"/>
diff --git a/tools/android/md5sum/BUILD.gn b/tools/android/md5sum/BUILD.gn
index 0e5b2216a..075fe73 100644
--- a/tools/android/md5sum/BUILD.gn
+++ b/tools/android/md5sum/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/android/config.gni")
+
 # GYP: //tools/android/md5sum/md5sum.gyp:md5sum
 group("md5sum") {
   data_deps = [
@@ -23,12 +25,9 @@
     "//build/config/sanitizers:deps",
   ]
 
-  # TODO(GYP)
-  #'conditions': [
-  #[ 'order_profiling!=0 and OS=="android"', {
-  #'dependencies': [ '../../../tools/cygprofile/cygprofile.gyp:cygprofile', ],
-  #}],
-  #],
+  if (is_android && use_order_profiling) {
+    deps += [ "//tools/cygprofile" ]
+  }
 }
 
 if (current_toolchain == default_toolchain) {
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py
index 1a107c3..65ce9498 100755
--- a/tools/checklicenses/checklicenses.py
+++ b/tools/checklicenses/checklicenses.py
@@ -309,6 +309,12 @@
         'GPL (v3 or later)',
         'UNKNOWN',  # http://crbug.com/98123
     ],
+    # This file's license is actually "BSD-like" but "LGPL (v2.1 or later)" has
+    # been appended because there is a test string inside that contains the
+    # LGPL header. See http://crbug.com/537408
+    'third_party/ffmpeg/chromium/scripts/credits_updater_unittest.py': [
+        'BSD-like LGPL (v2.1 or later)',
+    ],
     'third_party/fontconfig': [
         # https://bugs.freedesktop.org/show_bug.cgi?id=73401
         'UNKNOWN',
@@ -428,6 +434,9 @@
     'third_party/scons-2.0.1/engine/SCons': [  # http://crbug.com/98462
         'UNKNOWN',
     ],
+    'third_party/sfntly/src/java': [  # Apache 2.0, not shipped.
+        'UNKNOWN',
+    ],
     'third_party/simplejson': [
         'UNKNOWN',
     ],
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
index e156d31a..5261add 100644
--- a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
+++ b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
@@ -192,8 +192,14 @@
     super(ChromeProxyHTTPFallbackViaHeader,
           self).CustomizeBrowserOptions(options)
     options.AppendExtraBrowserArgs('--ignore-certificate-errors')
+    # Set the primary Data Reduction Proxy to be the test server. The test
+    # doesn't know if Chrome is configuring the DRP using the Data Saver API or
+    # not, so the appropriate flags are set for both cases.
     options.AppendExtraBrowserArgs(
         '--spdy-proxy-auth-origin=http://%s' % _TEST_SERVER)
+    options.AppendExtraBrowserArgs(
+        '--data-reduction-proxy-http-proxies='
+        'http://%s;http://compress.googlezip.net' % _TEST_SERVER)
 
   def AddResults(self, tab, results):
     self._metrics.AddResultsForHTTPFallback(tab, results)
@@ -307,9 +313,14 @@
     super(ChromeProxyHTTPToDirectFallback,
           self).CustomizeBrowserOptions(options)
     # Set the primary proxy to something that will fail to be resolved so that
-    # this test will run using the HTTP fallback proxy.
+    # this test will run using the HTTP fallback proxy. The test doesn't know if
+    # Chrome is configuring the DRP using the Data Saver API or not, so the
+    # appropriate flags are set for both cases.
     options.AppendExtraBrowserArgs(
         '--spdy-proxy-auth-origin=http://nonexistent.googlezip.net')
+    options.AppendExtraBrowserArgs(
+        '--data-reduction-proxy-http-proxies='
+        'http://nonexistent.googlezip.net;http://compress.googlezip.net')
 
   def WillNavigateToPage(self, page, tab):
     super(ChromeProxyHTTPToDirectFallback, self).WillNavigateToPage(page, tab)
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 52b8ed1..757c384 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -11,6 +11,7 @@
 #include <algorithm>
 
 #include "BlinkGCPluginOptions.h"
+#include "CheckDispatchVisitor.h"
 #include "CheckFieldsVisitor.h"
 #include "CheckFinalizerVisitor.h"
 #include "CheckGCRootsVisitor.h"
@@ -183,42 +184,6 @@
   return v.late_parsed_decls;
 }
 
-// This visitor checks that a method contains within its body, a call to a
-// method on the provided receiver class. This is used to check manual
-// dispatching for trace and finalize methods.
-class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
- public:
-  CheckDispatchVisitor(RecordInfo* receiver)
-      : receiver_(receiver), dispatched_to_receiver_(false) {}
-
-  bool dispatched_to_receiver() { return dispatched_to_receiver_; }
-
-  bool VisitMemberExpr(MemberExpr* member) {
-    if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) {
-      if (fn->getParent() == receiver_->record())
-        dispatched_to_receiver_ = true;
-    }
-    return true;
-  }
-
-  bool VisitUnresolvedMemberExpr(UnresolvedMemberExpr* member) {
-    for (Decl* decl : member->decls()) {
-      if (CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl)) {
-        if (method->getParent() == receiver_->record() &&
-            Config::GetTraceMethodType(method) ==
-            Config::TRACE_AFTER_DISPATCH_METHOD) {
-          dispatched_to_receiver_ = true;
-          return true;
-        }
-      }
-    }
-    return true;
-  }
-
- private:
-  RecordInfo* receiver_;
-  bool dispatched_to_receiver_;
-};
 
 class EmptyStmtVisitor
     : public RecursiveASTVisitor<EmptyStmtVisitor> {
diff --git a/tools/clang/blink_gc_plugin/CMakeLists.txt b/tools/clang/blink_gc_plugin/CMakeLists.txt
index c7fe7692..006121b 100644
--- a/tools/clang/blink_gc_plugin/CMakeLists.txt
+++ b/tools/clang/blink_gc_plugin/CMakeLists.txt
@@ -2,6 +2,7 @@
 
 set(plugin_sources
   BlinkGCPlugin.cpp
+  CheckDispatchVisitor.cpp
   CheckFieldsVisitor.cpp
   CheckFinalizerVisitor.cpp
   CheckGCRootsVisitor.cpp
diff --git a/tools/clang/blink_gc_plugin/CheckDispatchVisitor.cpp b/tools/clang/blink_gc_plugin/CheckDispatchVisitor.cpp
new file mode 100644
index 0000000..9c3de6d
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/CheckDispatchVisitor.cpp
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "CheckDispatchVisitor.h"
+
+#include "Config.h"
+#include "RecordInfo.h"
+
+using namespace clang;
+
+CheckDispatchVisitor::CheckDispatchVisitor(RecordInfo* receiver)
+    : receiver_(receiver),
+      dispatched_to_receiver_(false) {
+}
+
+bool CheckDispatchVisitor::dispatched_to_receiver() {
+  return dispatched_to_receiver_;
+}
+
+bool CheckDispatchVisitor::VisitMemberExpr(MemberExpr* member) {
+  if (CXXMethodDecl* fn = dyn_cast<CXXMethodDecl>(member->getMemberDecl())) {
+    if (fn->getParent() == receiver_->record())
+      dispatched_to_receiver_ = true;
+  }
+  return true;
+}
+
+bool CheckDispatchVisitor::VisitUnresolvedMemberExpr(
+    UnresolvedMemberExpr* member) {
+  for (Decl* decl : member->decls()) {
+    if (CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl)) {
+      if (method->getParent() == receiver_->record() &&
+          Config::GetTraceMethodType(method) ==
+          Config::TRACE_AFTER_DISPATCH_METHOD) {
+        dispatched_to_receiver_ = true;
+        return true;
+      }
+    }
+  }
+  return true;
+}
diff --git a/tools/clang/blink_gc_plugin/CheckDispatchVisitor.h b/tools/clang/blink_gc_plugin/CheckDispatchVisitor.h
new file mode 100644
index 0000000..d96193d
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/CheckDispatchVisitor.h
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_BLINK_GC_PLUGIN_CHECK_DISPATCH_VISITOR_H_
+#define TOOLS_BLINK_GC_PLUGIN_CHECK_DISPATCH_VISITOR_H_
+
+#include "clang/AST/RecursiveASTVisitor.h"
+
+class RecordInfo;
+
+// This visitor checks that a method contains within its body, a call to a
+// method on the provided receiver class. This is used to check manual
+// dispatching for trace and finalize methods.
+class CheckDispatchVisitor
+    : public clang::RecursiveASTVisitor<CheckDispatchVisitor> {
+ public:
+  explicit CheckDispatchVisitor(RecordInfo* receiver);
+
+  bool dispatched_to_receiver();
+
+  bool VisitMemberExpr(clang::MemberExpr* member);
+  bool VisitUnresolvedMemberExpr(clang::UnresolvedMemberExpr* member);
+
+ private:
+  RecordInfo* receiver_;
+  bool dispatched_to_receiver_;
+};
+
+#endif  // TOOLS_BLINK_GC_PLUGIN_CHECK_DISPATCH_VISITOR_H_
diff --git a/tools/cygprofile/BUILD.gn b/tools/cygprofile/BUILD.gn
new file mode 100644
index 0000000..c846546
--- /dev/null
+++ b/tools/cygprofile/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# GYP: //tools/cygprofile/cygprofile.gyp:cygprofile
+static_library("cygprofile") {
+  sources = [
+    "cygprofile.cc",
+    "cygprofile.h",
+  ]
+
+  configs -= [ "//build/config/android:default_cygprofile_instrumentation" ]
+  configs += [ "//build/config/android:no_cygprofile_instrumentation" ]
+
+  deps = [
+    # This adds uninstrumented symbols to the static library from base.
+    # These symbols are likely *not* to be used because there are many other
+    # duplicates in other objects/libraries.
+    "//base",
+  ]
+}
+
+# GYP: //tools/cygprofile/cygprofile.gyp:cygprofile_unittests
+executable("cygprofile_unittests") {
+  testonly = true
+
+  sources = [
+    "cygprofile_unittest.cc",
+  ]
+
+  configs -= [ "//build/config/android:default_cygprofile_instrumentation" ]
+  configs += [ "//build/config/android:no_cygprofile_instrumentation" ]
+
+  deps = [
+    ":cygprofile",
+    "//base",
+    "//testing/gtest",
+  ]
+}
diff --git a/tools/cygprofile/cygprofile.gyp b/tools/cygprofile/cygprofile.gyp
index 97ab2c6..c0deded 100644
--- a/tools/cygprofile/cygprofile.gyp
+++ b/tools/cygprofile/cygprofile.gyp
@@ -5,6 +5,7 @@
 {
   'targets': [
     {
+      # GN: //tools/cygprofile
       'target_name': 'cygprofile',
       'type': 'static_library',
       'include_dirs': [ '../..', ],
@@ -21,6 +22,7 @@
       ],
     },
     {
+      # GN: //tools/cygprofile:cygprofile_unittests
       'target_name': 'cygprofile_unittests',
       'type': 'executable',
       'include_dirs': [ '../..', ],
diff --git a/tools/gn/bin/roll_gn.py b/tools/gn/bin/roll_gn.py
index a479bdcf..b5c276ec 100644
--- a/tools/gn/bin/roll_gn.py
+++ b/tools/gn/bin/roll_gn.py
@@ -182,13 +182,26 @@
     print('Checking build')
     results = self.CheckBuild()
     while (len(results) < 3 or
-           any(r['state'] == 'pending' for r in results.values())):
+           any(r['state'] in ('pending', 'started')
+               for r in results.values())):
       print()
       print('Sleeping for 30 seconds')
       time.sleep(30)
       print('Checking build')
       results = self.CheckBuild()
-    return 0 if all(r['state'] == 'success' for r in results.values()) else 1
+
+    ret = 0 if all(r['state'] == 'success' for r in results.values()) else 1
+    if ret:
+      print('Build failed.')
+    else:
+      print('Builds ready.')
+
+    # Close the build CL and move off of the build branch back to whatever
+    # we were on before.
+    self.Call('git-cl set-close')
+    self.MoveToLastHead()
+
+    return ret
 
   def CheckBuild(self):
     _, out, _ = self.Call('git-cl issue')
@@ -264,7 +277,8 @@
 
   def RollBuildtools(self):
     results = self.CheckBuild()
-    if not all(r['state'] == 'success' for r in results.values()):
+    if (len(results) < 3 or
+        not all(r['state'] == 'success' for r in results.values())):
       print("Roll isn't done or didn't succeed, exiting:")
       return 1
 
@@ -306,6 +320,11 @@
     # merged branch.
     self.Call('git checkout origin/master', cwd=self.buildtools_dir)
 
+    _, out, _ = self.Call('git rev-parse origin/master',
+                          cwd=self.buildtools_dir)
+    new_buildtools_commitish = out.strip()
+    print('Ready to roll buildtools to %s in DEPS' % new_buildtools_commitish)
+
     return 0
 
   def RollDEPS(self):
@@ -336,7 +355,7 @@
       return 1
 
     with open('DEPS', 'w') as fp:
-      fp.write(''.join(new_deps_lines) + '\n')
+      fp.write(''.join(new_deps_lines))
 
     desc = self.GetDEPSRollDesc(old_buildtools_commitish,
                                 new_buildtools_commitish)
@@ -349,11 +368,22 @@
     finally:
       os.remove(desc_file.name)
 
-    # Intentionally leave the src checkout on the new branch with the roll
-    # since we're not auto-committing it.
+    # Move off of the roll branch onto whatever we were on before.
+    # Do not explicitly close the roll CL issue, however; the CQ
+    # will close it when the roll lands, assuming it does so.
+    self.MoveToLastHead()
 
     return 0
 
+  def MoveToLastHead(self):
+    # When this is called, there will be a commit + a checkout as
+    # the two most recent entries in the reflog, assuming nothing as
+    # modified the repo while this script has been running.
+    _, out, _ = self.Call('git reflog -2')
+    m = re.search('moving from ([^\s]+)', out)
+    last_head = m.group(1)
+    self.Call('git checkout %s' % last_head)
+
   def GetBuildtoolsDesc(self):
     gn_changes = self.GetGNChanges()
     return (
@@ -382,8 +412,7 @@
       '%s'
       '\n'
       'TBR=%s\n'
-      'CQ_EXTRA_TRYBOTS=tryserver.chromium.mac:mac_chromium_gn_rel,'
-      'mac_chromium_gn_dbg;'
+      'CQ_EXTRA_TRYBOTS=tryserver.chromium.mac:mac_chromium_gn_dbg;'
       'tryserver.chromium.win:win8_chromium_gn_dbg,'
       'win_chromium_gn_x64_rel\n' % (
         old_buildtools_commitish[:COMMITISH_DIGITS],
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py
index cb5e0ab..8764f0d 100755
--- a/tools/gn/bootstrap/bootstrap.py
+++ b/tools/gn/bootstrap/bootstrap.py
@@ -247,6 +247,7 @@
       'base/trace_event/memory_dump_manager.cc',
       'base/trace_event/memory_dump_request_args.cc',
       'base/trace_event/memory_dump_session_state.cc',
+      'base/trace_event/memory_profiler_allocation_context.cc',
       'base/trace_event/process_memory_dump.cc',
       'base/trace_event/process_memory_maps.cc',
       'base/trace_event/process_memory_maps_dump_provider.cc',
diff --git a/tools/gn/builder.cc b/tools/gn/builder.cc
index 3a0c1f5..ca11e888 100644
--- a/tools/gn/builder.cc
+++ b/tools/gn/builder.cc
@@ -242,7 +242,7 @@
     return false;
 
   // Make sure all deps of this config are scheduled to be loaded. For other
-  // item types like targets, the "should generate" flag is propogated around
+  // item types like targets, the "should generate" flag is propagated around
   // to mark whether this should happen. We could call
   // RecursiveSetShouldGenerate to do this step here, but since configs nor
   // anything they depend on is actually written, the "generate" flag isn't
diff --git a/tools/gn/builder_unittest.cc b/tools/gn/builder_unittest.cc
index a5356a2..5129063 100644
--- a/tools/gn/builder_unittest.cc
+++ b/tools/gn/builder_unittest.cc
@@ -184,7 +184,7 @@
   EXPECT_TRUE(c_record->waiting_on_resolution().empty());
 }
 
-// Tests that the should generate bit is set and propogated properly.
+// Tests that the "should generate" flag is set and propagated properly.
 TEST_F(BuilderTest, ShouldGenerate) {
   DefineToolchain();
 
diff --git a/tools/gn/config_values.cc b/tools/gn/config_values.cc
index d87ed84b..73486cd8 100644
--- a/tools/gn/config_values.cc
+++ b/tools/gn/config_values.cc
@@ -23,6 +23,7 @@
 }
 
 void ConfigValues::AppendValues(const ConfigValues& append) {
+  VectorAppend(&asmflags_,     append.asmflags_);
   VectorAppend(&cflags_,       append.cflags_);
   VectorAppend(&cflags_c_,     append.cflags_c_);
   VectorAppend(&cflags_cc_,    append.cflags_cc_);
diff --git a/tools/gn/function_write_file.cc b/tools/gn/function_write_file.cc
index 45387a3..d24abc1 100644
--- a/tools/gn/function_write_file.cc
+++ b/tools/gn/function_write_file.cc
@@ -115,6 +115,14 @@
     return Value();
   g_scheduler->AddWrittenFile(source_file);  // Track that we wrote this file.
 
+  // Track how to recreate this file, since we write it a gen time.
+  // Note this is a hack since the correct output is not a dependency proper,
+  // but an addition of this file to the output of the gn rule that writes it.
+  // This dependency will, however, cause the gen step to be re-run and the
+  // build restarted if the file is missing.
+  g_scheduler->AddGenDependency(
+      scope->settings()->build_settings()->GetFullPath(source_file));
+
   // Compute output.
   std::ostringstream contents;
   if (args[1].type() == Value::LIST) {
diff --git a/tools/gn/ninja_binary_target_writer.cc b/tools/gn/ninja_binary_target_writer.cc
index b7dace7..ae467600 100644
--- a/tools/gn/ninja_binary_target_writer.cc
+++ b/tools/gn/ninja_binary_target_writer.cc
@@ -420,16 +420,12 @@
     WriteOneFlag(SUBSTITUTION_ASMFLAGS, false, Toolchain::TYPE_NONE,
                  &ConfigValues::asmflags, opts);
   }
-  // TODO(andybons): Remove SOURCE_S and SOURCE_ASM checks once asmflags is
-  // used.
   if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) ||
-      used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM) ||
-      used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) {
+      used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM)) {
     WriteOneFlag(SUBSTITUTION_CFLAGS, false, Toolchain::TYPE_NONE,
                  &ConfigValues::cflags, opts);
   }
-  if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_S) ||
-      used_types.Get(SOURCE_ASM)) {
+  if (used_types.Get(SOURCE_C)) {
     WriteOneFlag(SUBSTITUTION_CFLAGS_C, has_precompiled_headers,
                  Toolchain::TYPE_CC, &ConfigValues::cflags_c, opts);
   }
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc
index d27ebdc..50638fb 100644
--- a/tools/gn/ninja_build_writer.cc
+++ b/tools/gn/ninja_build_writer.cc
@@ -180,23 +180,10 @@
 void NinjaBuildWriter::WriteNinjaRules() {
   out_ << "rule gn\n";
   out_ << "  command = " << GetSelfInvocationCommand(build_settings_) << "\n";
-  out_ << "  description = Regenerating ninja files\n";
-  out_ << "  restat = 1\n\n";
+  out_ << "  description = Regenerating ninja files\n\n";
 
-  // This rule will regenerate the ninja files when any input file has changed,
-  // or is missing.
-  out_ << "build build.ninja";
-
-  // Other files read by the build.
-  EscapeOptions path_escaping;
-  path_escaping.mode = ESCAPE_NINJA_COMMAND;
-  std::vector<SourceFile> written_files = g_scheduler->GetWrittenFiles();
-  for (const auto& written_file : written_files)
-    out_ << " " << EscapeString(RebasePath(written_file.value(),
-        build_settings_->build_dir(), build_settings_->root_path_utf8()),
-        path_escaping, nullptr);
-
-  out_ << ": gn\n"
+  // This rule will regenerate the ninja files when any input file has changed.
+  out_ << "build build.ninja: gn\n"
        << "  generator = 1\n"
        << "  depfile = build.ninja.d\n";
 
diff --git a/tools/gn/scheduler.cc b/tools/gn/scheduler.cc
index db0929db..622019e 100644
--- a/tools/gn/scheduler.cc
+++ b/tools/gn/scheduler.cc
@@ -113,11 +113,6 @@
   written_files_.push_back(file);
 }
 
-std::vector<SourceFile> Scheduler::GetWrittenFiles() const {
-  base::AutoLock lock(lock_);
-  return written_files_;
-}
-
 void Scheduler::AddUnknownGeneratedInput(const Target* target,
                                          const SourceFile& file) {
   base::AutoLock lock(lock_);
diff --git a/tools/gn/scheduler.h b/tools/gn/scheduler.h
index 7e29ab5..5d0502f 100644
--- a/tools/gn/scheduler.h
+++ b/tools/gn/scheduler.h
@@ -56,7 +56,6 @@
   // Tracks calls to write_file for resolving with the unknown generated
   // inputs (see AddUnknownGeneratedInput below).
   void AddWrittenFile(const SourceFile& file);
-  std::vector<SourceFile> GetWrittenFiles() const;
 
   // Unknown generated inputs are files that a target declares as an input
   // in the output directory, but which aren't generated by any dependency.
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 93dbbe2a..585c850c3 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -277,7 +277,7 @@
     //
     // However, if the dependency is private:
     //   EXE -> INTERMEDIATE_SHLIB --[private]--> FINAL_SHLIB
-    // the dependency will not be propogated because INTERMEDIATE_SHLIB is
+    // the dependency will not be propagated because INTERMEDIATE_SHLIB is
     // not granting permission to call functiosn from FINAL_SHLIB. If EXE
     // wants to use functions (and link to) FINAL_SHLIB, it will need to do
     // so explicitly.
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 12f942d..347fc8c 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -147,9 +147,7 @@
       cmd = self.GNCmd('gen', '_path_', vals['gn_args'])
       env = None
     elif vals['type'] == 'gyp':
-      if vals['gyp_crosscompile']:
-        self.Print('GYP_CROSSCOMPILE=1')
-      cmd, env = self.GYPCmd('_path_', vals['gyp_defines'])
+      cmd, env = self.GYPCmd('_path_', vals)
     else:
       raise MBErr('Unknown meta-build type "%s"' % vals['type'])
 
@@ -462,9 +460,7 @@
     path = self.args.path[0]
 
     output_dir = self.ParseGYPConfigPath(path)
-    cmd, env = self.GYPCmd(output_dir, vals['gyp_defines'])
-    if vals['gyp_crosscompile']:
-      env['GYP_CROSSCOMPILE'] = '1'
+    cmd, env = self.GYPCmd(output_dir, vals)
     ret, _, _ = self.Run(cmd, env=env)
     return ret
 
@@ -477,7 +473,7 @@
       self.PrintJSON(inp)
       self.Print()
 
-    cmd, env = self.GYPCmd(output_dir, vals['gyp_defines'])
+    cmd, env = self.GYPCmd(output_dir, vals)
     cmd.extend(['-f', 'analyzer',
                 '-G', 'config_path=%s' % self.args.input_path[0],
                 '-G', 'analyzer_output_path=%s' % self.args.output_path[0]])
@@ -557,7 +553,8 @@
       ]
       cmdline = [
           '../../testing/test_env.py',
-      ] + ['../../' + self.ToSrcRelPath(gn_isolate_map[target]['script'])]
+          '../../' + self.ToSrcRelPath(gn_isolate_map[target]['script'])
+      ] + gn_isolate_map[target].get('args', [])
     elif test_type in ('raw'):
       extra_files = []
       cmdline = [
@@ -586,7 +583,8 @@
     output_dir, _, _ = rpath.rpartition(self.sep)
     return output_dir
 
-  def GYPCmd(self, output_dir, gyp_defines):
+  def GYPCmd(self, output_dir, vals):
+    gyp_defines = vals['gyp_defines']
     goma_dir = self.args.goma_dir
 
     # GYP uses shlex.split() to split the gyp defines into separate arguments,
@@ -602,8 +600,17 @@
         '-G',
         'output_dir=' + output_dir,
     ]
+
+    # Ensure that we have an environment that only contains
+    # the exact values of the GYP variables we need.
     env = os.environ.copy()
+    if 'GYP_CHROMIUM_NO_ACTION' in env:
+      del env['GYP_CHROMIUM_NO_ACTION']
+    if 'GYP_CROSSCOMPILE' in env:
+      del env['GYP_CROSSCOMPILE']
     env['GYP_DEFINES'] = gyp_defines
+    if vals['gyp_crosscompile']:
+      env['GYP_CROSSCOMPILE'] = '1'
     return cmd, env
 
   def RunGNAnalyze(self, vals):
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 4339002..98921fdc 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -34,6 +34,7 @@
     'gn_debug_bot_minimal_symbols_x86': ['gn', 'debug_bot_minimal_symbols', 'x86'],
     'gn_debug_static_bot': ['gn', 'debug_static_bot'],
     'gn_linux_upload': ['gn_linux_upload', 'official', 'goma'],
+    'gn_official_goma': ['gn', 'official', 'goma'],
     'gn_release_bot': ['gn', 'release_bot'],
     'gn_release_bot_minimal_symbols': ['gn', 'release_bot_minimal_symbols'],
     'gn_release_bot_minimal_symbols_x86': ['gn', 'release_bot_minimal_symbols', 'x86'],
@@ -370,7 +371,7 @@
       'Win Builder': 'gyp_official_goma_minimal_symbols_x86',
       'Win x64 Builder': 'gyp_official_goma_minimal_symbols_x64',
       'Mac Builder': 'gyp_official_goma',
-      'Linux Builder': 'gyp_official_goma',
+      'Linux Builder': 'gn_official_goma',
     },
     'chromium.win': {
       # Windows bots take too long to link w/ full symbols and time out.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 34fa10b8..9ec692d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -4101,6 +4101,24 @@
   </summary>
 </histogram>
 
+<histogram name="Chromoting.Video.CaptureOverhead" units="ms">
+  <owner>anandc@chromium.org</owner>
+  <owner>sergeyu@chromium.org</owner>
+  <summary>
+    Amount of time wasted on IPC and threading overhead when capturing a video
+    frame.
+  </summary>
+</histogram>
+
+<histogram name="Chromoting.Video.CapturePendingLatency" units="ms">
+  <owner>anandc@chromium.org</owner>
+  <owner>sergeyu@chromium.org</owner>
+  <summary>
+    The time from when an input event is received to when the next frame is
+    captured.
+  </summary>
+</histogram>
+
 <histogram name="Chromoting.Video.DecodeLatency" units="ms">
   <owner>anandc@chromium.org</owner>
   <owner>sergeyu@chromium.org</owner>
@@ -4116,6 +4134,14 @@
   </summary>
 </histogram>
 
+<histogram name="Chromoting.Video.EncodePendingLatency" units="ms">
+  <owner>anandc@chromium.org</owner>
+  <owner>sergeyu@chromium.org</owner>
+  <summary>
+    Delay before a newly captured frame is passed to the encoder.
+  </summary>
+</histogram>
+
 <histogram name="Chromoting.Video.FrameRate" units="fps">
   <owner>anandc@chromium.org</owner>
   <owner>sergeyu@chromium.org</owner>
@@ -4149,6 +4175,14 @@
   </summary>
 </histogram>
 
+<histogram name="Chromoting.Video.SendPendingLatency" units="ms">
+  <owner>anandc@chromium.org</owner>
+  <owner>sergeyu@chromium.org</owner>
+  <summary>
+    Delay before an encoded video packet is written to the send buffer.
+  </summary>
+</histogram>
+
 <histogram name="clickjacking.discard_download" units="ms">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -5482,6 +5516,15 @@
   </summary>
 </histogram>
 
+<histogram name="CustomTabs.WarmupStateOnLaunch" enum="WarmupStateOnLaunch">
+  <owner>lizeb@chromium.org</owner>
+  <summary>
+    Recorded only on Android. Reports whether warmup() has been called when a
+    Custom Tabs Intent is received from an application, and if so, whether the
+    call could be matched with a session.
+  </summary>
+</histogram>
+
 <histogram name="DataReductionProxy.AutoLoFiAccuracy"
     enum="DataReductionProxyAutoLoFiAccuracy">
   <owner>bengr@chromium.org</owner>
@@ -5946,8 +5989,9 @@
   <owner>bengr@chromium.org</owner>
   <owner>megjablon@chromium.org</owner>
   <summary>
-    Samples of user interactions with the promo and settings menu. All samples
-    are mutually exclusive. These samples include:
+    Samples of user interactions with the Data Reduction Proxy promo, First Run
+    Experience, and settings menu. All samples are mutually exclusive. These
+    samples include:
 
     The user interactions with the promo. On Android, there are three actions
     that dismiss the promo (enable, dismiss, and learn more) and on iOS there is
@@ -5960,6 +6004,12 @@
     reducing data usage setting menu and leaving the menu will be sampled
     regardless of how many times he or she toggles the ON/OFF switch. Other
     samples that report ON/OFF settings menu changes are not also reported here.
+
+    The user interactions with the First Run Experience. On Android when the
+    user sees the FRE card, the Data Reduction Proxy defaults to ON. The user
+    can disable the proxy via a switch on the card. The state of the proxy is
+    sampled when the First Run Experience is completed and only reported if the
+    Data Reduction Proxy card was shown.
   </summary>
 </histogram>
 
@@ -7567,6 +7617,15 @@
   </summary>
 </histogram>
 
+<histogram name="DomainReliability.ReportedBeaconError_HasServerIP"
+    enum="NetErrorCodes">
+  <owner>ttuttle@chromium.org</owner>
+  <summary>
+    The Chrome error code included in a beacon with a non-empty server_ip field
+    saved to be uploaded to the collector.
+  </summary>
+</histogram>
+
 <histogram name="DomainReliability.UploadCollectorIndex">
   <owner>ttuttle@chromium.org</owner>
   <summary>
@@ -29710,6 +29769,10 @@
 <histogram name="PageLoad.Timing.NavigationToDOMContentLoadedEventFired"
     units="milliseconds">
   <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
+  <obsolete>
+    deprecated in favor of PageLoad.Timing2.*
+  </obsolete>
   <summary>
     Measures the time from navigation timing's navigation start to the time the
     DOMContentLoaded event is fired, for main frame documents.
@@ -29718,6 +29781,10 @@
 
 <histogram name="PageLoad.Timing.NavigationToFirstLayout" units="milliseconds">
   <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
+  <obsolete>
+    deprecated in favor of PageLoad.Timing2.*
+  </obsolete>
   <summary>
     Measures the time from navigation timing's navigation start to the time the
     first layout is performed, for main frame documents.
@@ -29727,6 +29794,39 @@
 <histogram name="PageLoad.Timing.NavigationToLoadEventFired"
     units="milliseconds">
   <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
+  <obsolete>
+    deprecated in favor of PageLoad.Timing2.*
+  </obsolete>
+  <summary>
+    Measures the time from navigation timing's navigation start to the time the
+    load event is fired, for main frame documents.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Timing2.NavigationToDOMContentLoadedEventFired"
+    units="milliseconds">
+  <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
+  <summary>
+    Measures the time from navigation timing's navigation start to the time the
+    DOMContentLoaded event is fired, for main frame documents.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Timing2.NavigationToFirstLayout" units="milliseconds">
+  <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
+  <summary>
+    Measures the time from navigation timing's navigation start to the time the
+    first layout is performed, for main frame documents.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Timing2.NavigationToLoadEventFired"
+    units="milliseconds">
+  <owner>bmcquade@chromium.org</owner>
+  <owner>csharrison@chromium.org</owner>
   <summary>
     Measures the time from navigation timing's navigation start to the time the
     load event is fired, for main frame documents.
@@ -30274,6 +30374,19 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.SettingsReconciliation.InitialValues"
+    enum="PasswordManagerPreferencesInitialValues">
+  <owner>engedy@chromium.org</owner>
+  <owner>melandory@chromium.org</owner>
+  <summary>
+    Tracks the pair of initial values for both for the legacy preference for
+    controlling the Chrome Password Manager and new preference for controlling
+    Smart Lock on Android. Sample is recorded on every profile initialization
+    before reconciliation logic is taken place, e.g. when user logs in to
+    browser, on a startup of a browser.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.StoreReadyWhenWiping" enum="Boolean">
   <owner>vabr@chromium.org</owner>
   <summary>
@@ -40457,6 +40570,15 @@
   </summary>
 </histogram>
 
+<histogram name="ServiceWorker.ScriptLoadSuccess" units="BooleanSuccess">
+  <owner>falken@chromium.org</owner>
+  <summary>
+    Whether loading the service worker script succeeded. Only recorded for
+    installed service workers. Recorded by the browser process when reported
+    back by the renderer during worker startup.
+  </summary>
+</histogram>
+
 <histogram name="ServiceWorker.ScriptSize" units="bytes">
   <owner>ksakamoto@chromium.org</owner>
   <summary>
@@ -47823,6 +47945,13 @@
   </summary>
 </histogram>
 
+<histogram name="UrlFetcher.StringResponseSize" units="KB">
+  <owner>mmenke@chromium.org</owner>
+  <summary>
+    Size (in kilobytes) of response bodies retrieved as strings from URLFetcher.
+  </summary>
+</histogram>
+
 <histogram name="UserImage.ChangeChoice" enum="ChromeOSUserImageId">
   <owner>nkostylev@chromium.org</owner>
   <summary>
@@ -50352,6 +50481,17 @@
   </summary>
 </histogram>
 
+<histogram name="WebRTC.PeerConnection.IPPermissionStatus"
+    enum="IPPermissionStatus">
+  <owner>guoweis@chromium.org</owner>
+  <summary>
+    Whether the permission to collect the local IP addresses in WebRTC has been
+    requested and/or granted. This is collected the first time when networks
+    updated event is reported or if never reported, during the destruction phase
+    of a call.
+  </summary>
+</histogram>
+
 <histogram name="WebRTC.PeerConnection.IPv4Interfaces">
   <owner>mallinath@chromium.org</owner>
   <summary>
@@ -50398,6 +50538,15 @@
   <summary>Time to setup a peer to peer call with PeerConnection.</summary>
 </histogram>
 
+<histogram name="WebRTC.PeerConnection.TimeToNetworkUpdated"
+    units="milliseconds">
+  <owner>guoweis@chromium.org</owner>
+  <summary>
+    Time to receive the first SignalNetworksChanged from the request to start
+    updating network in PeerConnection.
+  </summary>
+</histogram>
+
 <histogram name="WebRTC.ReceivedAudioTrackDuration" units="milliseconds">
   <owner>perkj@chromium.org</owner>
   <summary>
@@ -54214,7 +54363,7 @@
 
 <enum name="DataReductionProxyNetworkChangeEvent" type="int">
   <int value="0" label="IP Address Change"/>
-  <int value="1" label="Proxy disabled on VPN"/>
+  <int value="1" label="Proxy disabled on VPN (deprecated)"/>
 </enum>
 
 <enum name="DataReductionProxyProbeURLFetchResult" type="int">
@@ -54290,6 +54439,8 @@
       label="Arrived at settings menu by another path: entered on, exited off"/>
   <int value="8"
       label="Arrived at settings menu by another path: entered on, exited on"/>
+  <int value="9" label="Enabled directly from the First Run Experience"/>
+  <int value="10" label="Diabled directly from the First Run Experience"/>
 </enum>
 
 <enum name="DataUseServices" type="int">
@@ -55229,6 +55380,8 @@
   <int value="5" label="SCRIPT_LOADED"/>
   <int value="6" label="SCRIPT_EVALUATED"/>
   <int value="7" label="THREAD_STARTED"/>
+  <int value="8" label="SCRIPT_READ_STARTED"/>
+  <int value="9" label="SCRIPT_READ_FINISHED"/>
 </enum>
 
 <enum name="EnhancedBookmarkViewMode" type="int">
@@ -57807,6 +57960,7 @@
   <int value="1087" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONDISCONNECT"/>
   <int value="1088" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONSEND"/>
   <int value="1089" label="DATAREDUCTIONPROXY_GETDATAUSAGE"/>
+  <int value="1090" label="EASYUNLOCKPRIVATE_SETUPCONNECTIONGETDEVICEADDRESS"/>
 </enum>
 
 <enum name="ExtensionInstallCause" type="int">
@@ -62178,6 +62332,15 @@
   </int>
 </enum>
 
+<enum name="IPPermissionStatus" type="int">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Not requested"/>
+  <int value="2" label="Requested but denied"/>
+  <int value="3"
+      label="Requested and granted after checking mic/camera permission"/>
+  <int value="4" label="Requested and granted automatically"/>
+</enum>
+
 <enum name="IPv6ConnectivityStatus" type="int">
   <int value="0" label="Incomplete IPv6 Configuration"/>
   <int value="1" label="Complete IPv6 Configuration"/>
@@ -63636,6 +63799,7 @@
   <int value="2101151142" label="disable-direct-write"/>
   <int value="2119964154" label="enable-download-resumption"/>
   <int value="2121776031" label="auto-virtual-keyboard"/>
+  <int value="2122023503" label="enable-win32k-lockdown-mimetypes"/>
   <int value="2122876605" label="enable-bleeding-edge-rendering-fast-paths"/>
   <int value="2137347307" label="enable-drive-apps-in-app-list"/>
   <int value="2137599770" label="enable-win32k-renderer-lockdown"/>
@@ -66939,6 +67103,18 @@
       label="Password status not checked as user is on a Windows Domain"/>
 </enum>
 
+<enum name="PasswordManagerPreferencesInitialValues" type="int">
+  <summary>
+    The pair of initial values for the legacy preference for controlling the
+    Chrome Password Manager and new preference for controlling Smart Lock on
+    Android.
+  </summary>
+  <int value="0" label="New pref is 'off', legacy pref is 'off'"/>
+  <int value="1" label="New pref is 'off', legacy pref is 'on'"/>
+  <int value="2" label="New pref is 'on', legacy pref is 'off'"/>
+  <int value="3" label="New pref is 'on', legacy pref is 'on'"/>
+</enum>
+
 <enum name="PasswordManagerPslDomainMatchTriggering" type="int">
   <summary>
     The value indicates whether an entry returned by password autofill contains
@@ -71444,7 +71620,8 @@
   </int>
   <int value="10"
       label="AUTHORTIY_ERROR_CAPTIVE_PORTAL: Captive portal was detected">
-    This cause is recorded only for CERT_AUTHORITY_INVALID errors.
+    This cause is recorded only for CERT_AUTHORITY_INVALID errors. (Deprecated
+    in M47.)
   </int>
   <int value="11" label="SELF_SIGNED: The cert is self-signed">
     This cause is recorded only for CERT_AUTHORITY_INVALID errors.
@@ -73316,6 +73493,14 @@
   <int value="5" label="Policy"/>
 </enum>
 
+<enum name="WarmupStateOnLaunch" type="int">
+  <int value="0" label="No Session, No Warmup"/>
+  <int value="1" label="No Session, Warmup"/>
+  <int value="2" label="Session, No Warmup, Warmup called from another UID"/>
+  <int value="3" label="Session, No Warmup"/>
+  <int value="4" label="Session, Warmup"/>
+</enum>
+
 <enum name="WebBluetoothConnectGATTOutcome" type="int">
   <int value="0" label="Success"/>
   <int value="1" label="Device no longer in range"/>
@@ -77147,6 +77332,15 @@
   <affected-histogram name="PLT.LoadType"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="PageLoadBackgrounded" separator=".">
+  <suffix name="BG"
+      label="Event occurred at least partially in the background"/>
+  <affected-histogram
+      name="PageLoad.Timing2.NavigationToDOMContentLoadedEventFired"/>
+  <affected-histogram name="PageLoad.Timing2.NavigationToFirstLayout"/>
+  <affected-histogram name="PageLoad.Timing2.NavigationToLoadEventFired"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="PageLoadType">
   <suffix name="HistoryLoad"
       label="but only for user pressing back or forward"/>
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index eb447cc..52729f6 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -138,12 +138,7 @@
   def __init__(self, test, finder_options, user_story_set):
     super(_SharedPywebsocketPageState, self).__init__(
         test, finder_options, user_story_set)
-    self._pywebsocket_server = pywebsocket_server.PywebsocketServer()
-    self.platform.StartLocalServer(self._pywebsocket_server)
-
-  def TearDownState(self):
-    super(_SharedPywebsocketPageState, self).TearDownState()
-    self._pywebsocket_server.Close()
+    self.platform.StartLocalServer(pywebsocket_server.PywebsocketServer())
 
 
 class BlinkPerfBindings(perf_benchmark.PerfBenchmark):
diff --git a/tools/perf/benchmarks/tbm_smoke.py b/tools/perf/benchmarks/tbm_smoke.py
new file mode 100644
index 0000000..b02c5d5
--- /dev/null
+++ b/tools/perf/benchmarks/tbm_smoke.py
@@ -0,0 +1,31 @@
+# Copyright 2015 The Chromium 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 core import perf_benchmark
+
+from telemetry.timeline import tracing_category_filter
+from telemetry.web_perf import timeline_based_measurement
+
+import page_sets
+
+
+TIMELINE_REQUIRED_CATEGORY = 'blink.console'
+
+
+class TbmSmoke(perf_benchmark.PerfBenchmark):
+  """Timeline based measurement benchmark to test TBM Everywhere."""
+  # TODO(eakuefner): Remove this benchmark once crbug.com/461101 is closed.
+
+  page_set = page_sets.BlankPageSetForTbmSmoke
+
+  def CreateTimelineBasedMeasurementOptions(self):
+    cat_filter = tracing_category_filter.CreateMinimalOverheadFilter()
+    cat_filter.AddIncludedCategory(TIMELINE_REQUIRED_CATEGORY)
+
+    return timeline_based_measurement.Options(
+        overhead_level=cat_filter)
+
+  @classmethod
+  def Name(cls):
+    return 'tbm_smoke.tbm_smoke'
diff --git a/tools/perf/benchmarks/v8.py b/tools/perf/benchmarks/v8.py
index 88c8e2b..17a3c5a 100644
--- a/tools/perf/benchmarks/v8.py
+++ b/tools/perf/benchmarks/v8.py
@@ -10,13 +10,14 @@
 from telemetry import benchmark
 
 # Disabled on Win due to crbug.com/416502.
-@benchmark.Disabled('win')
+# Disabled on Linux due to crbug.com/537620.
+@benchmark.Disabled('win', 'linux')
 class V8Top25(perf_benchmark.PerfBenchmark):
   """Measures V8 GC metrics on the while scrolling down the top 25 web pages.
 
   http://www.chromium.org/developers/design-documents/rendering-benchmarks"""
   test = v8_gc_times.V8GCTimes
-  page_set = page_sets.V8Top25SmoothPageSet
+  page_set = page_sets.Top25SmoothPageSet
 
   @classmethod
   def Name(cls):
diff --git a/tools/perf/clear_system_cache/BUILD.gn b/tools/perf/clear_system_cache/BUILD.gn
index ab29ad4..c4d736534 100644
--- a/tools/perf/clear_system_cache/BUILD.gn
+++ b/tools/perf/clear_system_cache/BUILD.gn
@@ -2,19 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-if (is_linux && !is_chromeos) {
-  # TODO(GYP): Figure out which of these work and are needed on other platforms.
-  executable("clear_system_cache") {
-    testonly = true
+executable("clear_system_cache") {
+  testonly = true
 
-    sources = [
-      "clear_system_cache_main.cc",
-    ]
+  sources = [
+    "clear_system_cache_main.cc",
+  ]
 
-    deps = [
-      "//base",
-      "//base/test:test_support",
-      "//build/config/sanitizers:deps",
-    ]
-  }
+  deps = [
+    "//base",
+    "//base/test:test_support",
+  ]
 }
diff --git a/tools/perf/measurements/page_cycler.py b/tools/perf/measurements/page_cycler.py
index e50d5c4..b9e47ed 100644
--- a/tools/perf/measurements/page_cycler.py
+++ b/tools/perf/measurements/page_cycler.py
@@ -77,7 +77,7 @@
     if page.is_file:
       # For legacy page cyclers which use the filesystem, do an initial
       # navigate to avoid paying for a cross-renderer navigation.
-      initial_url = tab.browser.http_server.UrlOf('nonexistent.html')
+      initial_url = tab.browser.platform.http_server.UrlOf('nonexistent.html')
       if self._initial_renderer_url != initial_url:
         self._initial_renderer_url = initial_url
         tab.Navigate(self._initial_renderer_url)
diff --git a/tools/perf/measurements/page_cycler_unittest.py b/tools/perf/measurements/page_cycler_unittest.py
index 173cee6..d2a38d0 100644
--- a/tools/perf/measurements/page_cycler_unittest.py
+++ b/tools/perf/measurements/page_cycler_unittest.py
@@ -88,13 +88,6 @@
     return FakePlatform()
 
   @property
-  def http_server(self):
-    class FakeHttpServer(object):
-      def UrlOf(self, url_path):
-        return 'http://fakeserver:99999/%s' % url_path
-    return FakeHttpServer()
-
-  @property
   def supports_cpu_metrics(self):
     return True
 
@@ -113,6 +106,13 @@
   def CanMonitorPower(self):
     return False
 
+  @property
+  def http_server(self):
+    class FakeHttpServer(object):
+      def UrlOf(self, url_path):
+        return 'http://fakeserver:99999/%s' % url_path
+    return FakeHttpServer()
+
 
 class PageCyclerUnitTest(unittest.TestCase):
 
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index 3ff5023..e75e5273 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -40,7 +40,6 @@
     options.AppendExtraBrowserArgs('--running-performance-benchmark')
 
   def WillNavigateToPage(self, page, tab):
-    tracing_controller = tab.browser.platform.tracing_controller
     # FIXME: Remove webkit.console when blink.console lands in chromium and
     # the ref builds are updated. crbug.com/386847
     custom_categories = [
@@ -54,7 +53,7 @@
       options.category_filter.AddSyntheticDelay(delay)
     self._tbm = timeline_based_measurement.TimelineBasedMeasurement(
         options, self._results_wrapper)
-    self._tbm.WillRunStoryForPageTest(tracing_controller)
+    self._tbm.WillRunStory(tab.browser.platform)
 
   def ValidateAndMeasurePage(self, _, tab, results):
     self._tbm.Measure(tab.browser.platform, results)
diff --git a/tools/perf/measurements/v8_gc_times.py b/tools/perf/measurements/v8_gc_times.py
index 824c882..3230baa7 100644
--- a/tools/perf/measurements/v8_gc_times.py
+++ b/tools/perf/measurements/v8_gc_times.py
@@ -15,7 +15,6 @@
   _TIME_OUT_IN_SECONDS = 60
   _CATEGORIES = ['blink.console',
                  'renderer.scheduler',
-                 'toplevel',
                  'v8',
                  'webkit.console']
   _RENDERER_MAIN_THREAD = 'CrRendererMain'
diff --git a/tools/perf/metrics/power.py b/tools/perf/metrics/power.py
index ab709648..df3d919b 100644
--- a/tools/perf/metrics/power.py
+++ b/tools/perf/metrics/power.py
@@ -85,7 +85,8 @@
     # Make sure that power monitoring is cleaned up when program exits.
     platform = self._platform
     def CleanUp():
-      platform.StopMonitoringPower()
+      if platform.IsMonitoringPower():
+        platform.StopMonitoringPower()
     atexit.register(CleanUp)
 
     self._running = True
diff --git a/tools/perf/page_sets/blank_page_for_tbm_smoke.py b/tools/perf/page_sets/blank_page_for_tbm_smoke.py
new file mode 100644
index 0000000..5214d54
--- /dev/null
+++ b/tools/perf/page_sets/blank_page_for_tbm_smoke.py
@@ -0,0 +1,35 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.page import page as page_module
+from telemetry import story
+
+
+class BlankPageForTbmSmoke(page_module.Page):
+  def __init__(self, url, page_set):
+    super(BlankPageForTbmSmoke, self).__init__(url, page_set=page_set)
+
+  def RunPageInteractions(self, action_runner):
+    # Request a RAF and wait for it to be processed to ensure that the metric
+    # Startup.FirstWebContents.NonEmptyPaint is recorded.
+    action_runner.ExecuteJavaScript(
+        """
+        this.hasRunRAF = 0;
+        requestAnimationFrame(function() {
+            this.hasRunRAF = 1;
+        });
+        """
+    )
+    action_runner.WaitForJavaScriptCondition("this.hasRunRAF == 1")
+    with action_runner.CreateInteraction('MyIR1'):
+      action_runner.Wait(1)
+    with action_runner.CreateInteraction('MyIR2'):
+      action_runner.Wait(2)
+
+class BlankPageSetForTbmSmoke(story.StorySet):
+  """A single blank page."""
+
+  def __init__(self):
+    super(BlankPageSetForTbmSmoke, self).__init__()
+    self.AddStory(BlankPageForTbmSmoke(
+        'file://blank_page/blank_page.html', self))
diff --git a/tools/perf/page_sets/top_25_smooth.py b/tools/perf/page_sets/top_25_smooth.py
index 91d56b2..534ce75 100644
--- a/tools/perf/page_sets/top_25_smooth.py
+++ b/tools/perf/page_sets/top_25_smooth.py
@@ -81,7 +81,7 @@
 
   """ Pages hand-picked for 2012 CrOS scrolling tuning efforts. """
 
-  def __init__(self, techcrunch=True):
+  def __init__(self):
     super(Top25SmoothPageSet, self).__init__(
         archive_data_file='data/top_25_smooth.json',
         cloud_storage_bucket=story.PARTNER_BUCKET)
@@ -136,17 +136,9 @@
         'http://answers.yahoo.com',
         # Why: #1 Alexa sports
         'http://sports.yahoo.com/',
+        # Why: top tech blog
+        'http://techcrunch.com'
     ]
 
-    if techcrunch:
-      # Why: top tech blog
-      other_urls.append('http://techcrunch.com')
-
     for url in other_urls:
       self.AddStory(TopSmoothPage(url, self))
-
-
-class V8Top25SmoothPageSet(Top25SmoothPageSet):
-  def __init__(self):
-    # Disabled for V8 because of crbug.com/507836, crbug.com/527425
-    super(V8Top25SmoothPageSet, self).__init__(techcrunch=False)
diff --git a/tools/perf/page_sets/tough_ad_cases.py b/tools/perf/page_sets/tough_ad_cases.py
index 1e7ea53..26d77452 100644
--- a/tools/perf/page_sets/tough_ad_cases.py
+++ b/tools/perf/page_sets/tough_ad_cases.py
@@ -53,7 +53,8 @@
     # Rewrite file urls to point to the replay server instead.
     if self.is_file:
       url = self.file_path_url_with_scheme
-      url = action_runner.tab.browser.http_server.UrlOf(url[len('file://'):])
+      url = action_runner.tab.browser.platform.http_server.UrlOf(
+          url[len('file://'):])
     else:
       url = self._url
     action_runner.tab.Navigate(url)
diff --git a/tools/perf/page_sets/tough_scrolling_cases/canvas.html b/tools/perf/page_sets/tough_scrolling_cases/canvas.html
index 29e77a90..7248580 100644
--- a/tools/perf/page_sets/tough_scrolling_cases/canvas.html
+++ b/tools/perf/page_sets/tough_scrolling_cases/canvas.html
@@ -11,9 +11,9 @@
                Math.random() * (c.height / 2),
                c.width / 2,
                c.height / 2);
-  window.setTimeout(redraw, 1);
+  window.requestAnimationFrame(redraw);
 }
-window.setTimeout(redraw, 1);
+window.requestAnimationFrame(redraw);
 </script>
 <div style="position:fixed; background-color: blue; -webkit-transform: translateZ(0);">
 <canvas id="canvas" width="400" height="300"></canvas>
diff --git a/tools/resources/optimize-ico-files.py b/tools/resources/optimize-ico-files.py
index fcd9f53..71185f1 100755
--- a/tools/resources/optimize-ico-files.py
+++ b/tools/resources/optimize-ico-files.py
@@ -17,6 +17,7 @@
 
 import argparse
 import logging
+import math
 import os
 import StringIO
 import struct
@@ -83,6 +84,73 @@
       os.unlink(png_filename)
     os.rmdir(temp_dir)
 
+def ComputeANDMaskFromAlpha(image_data, width, height):
+  """Compute an AND mask from 32-bit BGRA image data."""
+  and_bytes = []
+  for y in range(height):
+    bit_count = 0
+    current_byte = 0
+    for x in range(width):
+      alpha = image_data[(y * width + x) * 4 + 3]
+      current_byte <<= 1
+      if ord(alpha) == 0:
+        current_byte |= 1
+      bit_count += 1
+      if bit_count == 8:
+        and_bytes.append(current_byte)
+        bit_count = 0
+        current_byte = 0
+
+    # At the end of a row, pad the current byte.
+    if bit_count > 0:
+      current_byte <<= (8 - bit_count)
+      and_bytes.append(current_byte)
+    # And keep padding until a multiple of 4 bytes.
+    while len(and_bytes) % 4 != 0:
+      and_bytes.append(0)
+
+  and_bytes = ''.join(map(chr, and_bytes))
+  return and_bytes
+
+def RebuildANDMask(iconimage):
+  """Rebuild the AND mask in an icon image.
+
+  GIMP (<=2.8.14) creates a bad AND mask on 32-bit icon images (pixels with <50%
+  opacity are marked as transparent, which end up looking black on Windows). So,
+  if this is a 32-bit image, throw the mask away and recompute it from the alpha
+  data. (See: https://bugzilla.gnome.org/show_bug.cgi?id=755200)
+
+  Args:
+    iconimage: Bytes of an icon image (the BMP data for an entry in an ICO
+      file). Must be in BMP format, not PNG. Does not need to be 32-bit (if it
+      is not 32-bit, this is a no-op).
+
+  Returns:
+    An updated |iconimage|, with the AND mask re-computed using
+    ComputeANDMaskFromAlpha.
+  """
+  # Parse BITMAPINFOHEADER.
+  (_, width, height, _, bpp, _, _, _, _, num_colors, _) = struct.unpack(
+      '<LLLHHLLLLLL', iconimage[:40])
+
+  if bpp != 32:
+    # No alpha channel, so the mask cannot be "wrong" (it is the only source of
+    # transparency information).
+    return iconimage
+
+  height /= 2
+  xor_size = int(math.ceil(width * bpp / 32.0)) * 4 * height
+
+  # num_colors can be 0, implying 2^bpp colors.
+  xor_palette_size = (num_colors or (1 << bpp if bpp < 24 else 0)) * 4
+  xor_data = iconimage[40 + xor_palette_size :
+                       40 + xor_palette_size + xor_size]
+
+  and_data = ComputeANDMaskFromAlpha(xor_data, width, height)
+
+  # Replace the AND mask in the original icon data.
+  return iconimage[:40 + xor_palette_size + xor_size] + and_data
+
 def OptimizeIcoFile(infile, outfile, optimization_level=None):
   """Read an ICO file, optimize its PNGs, and write the output to outfile.
 
@@ -123,11 +191,17 @@
 
     if entry_is_png:
       icon_data = OptimizePng(icon_data, optimization_level=optimization_level)
-    elif width >= 256 or height >= 256:
-      # TODO(mgiuca): Automatically convert large BMP images to PNGs.
-      logging.warning('Entry #%d is a large image in uncompressed BMP format. '
-                      'Please manually convert to PNG format before running '
-                      'this utility.', i + 1)
+    else:
+      new_icon_data = RebuildANDMask(icon_data)
+      if new_icon_data != icon_data:
+        logging.info('  * Rebuilt AND mask for this image from alpha channel.')
+        icon_data = new_icon_data
+
+      if width >= 256 or height >= 256:
+        # TODO(mgiuca): Automatically convert large BMP images to PNGs.
+        logging.warning('Entry #%d is a large image in uncompressed BMP '
+                        'format. Please manually convert to PNG format before '
+                        'running this utility.', i + 1)
 
     new_size = len(icon_data)
     current_offset += new_size
@@ -167,13 +241,16 @@
     OptimizeIcoFile(file, buf, args.optimization_level)
 
     new_length = len(buf.getvalue())
+
+    # Always write (even if file size not reduced), because we make other fixes
+    # such as regenerating the AND mask.
+    file.truncate(new_length)
+    file.seek(0)
+    file.write(buf.getvalue())
+
     if new_length >= old_length:
       logging.info('%s : Could not reduce file size.', file.name)
     else:
-      file.truncate(new_length)
-      file.seek(0)
-      file.write(buf.getvalue())
-
       saving = old_length - new_length
       saving_percent = float(saving) / old_length
       logging.info('%s : %d => %d (%d bytes : %d %%)', file.name, old_length,
diff --git a/tools/telemetry/telemetry/core/local_server_unittest.py b/tools/telemetry/telemetry/core/local_server_unittest.py
index 1b3b712..a70bfd5cf3 100644
--- a/tools/telemetry/telemetry/core/local_server_unittest.py
+++ b/tools/telemetry/telemetry/core/local_server_unittest.py
@@ -57,10 +57,10 @@
   def setUpClass(cls):
     super(LocalServerUnittest, cls).setUpClass()
     cls._server = SimpleLocalServer()
-    cls._browser.StartLocalServer(cls._server)
+    cls._platform.StartLocalServer(cls._server)
 
   def testLocalServer(self):
-    self.assertTrue(self._server in self._browser.local_servers)
+    self.assertTrue(self._server in self._platform.local_servers)
     self._tab.Navigate(self._server.url)
     self._tab.WaitForDocumentReadyStateToBeComplete()
     body_text = self._tab.EvaluateJavaScript('document.body.textContent')
@@ -70,9 +70,9 @@
   def testStartingAndRestarting(self):
     server2 = SimpleLocalServer()
     self.assertRaises(Exception,
-                      lambda: self._browser.StartLocalServer(server2))
+                      lambda: self._platform.StartLocalServer(server2))
 
     self._server.Close()
-    self.assertTrue(self._server not in self._browser.local_servers)
+    self.assertTrue(self._server not in self._platform.local_servers)
 
-    self._browser.StartLocalServer(server2)
+    self._platform.StartLocalServer(server2)
diff --git a/tools/telemetry/telemetry/core/platform.py b/tools/telemetry/telemetry/core/platform.py
index dbb2c1e8..19023bf 100644
--- a/tools/telemetry/telemetry/core/platform.py
+++ b/tools/telemetry/telemetry/core/platform.py
@@ -6,10 +6,12 @@
 
 from telemetry.core import discover
 from telemetry.core import local_server
+from telemetry.core import memory_cache_http_server
 from telemetry.core import network_controller
 from telemetry.core import tracing_controller
 from telemetry.core import util
-from telemetry.internal.platform import platform_backend as platform_backend_module
+from telemetry.internal.platform import (
+    platform_backend as platform_backend_module)
 
 
 _host_platform = None
@@ -82,6 +84,7 @@
         self._platform_backend.tracing_controller_backend)
     self._local_server_controller = local_server.LocalServerController(
         self._platform_backend)
+    self._is_monitoring_power = False
 
   @property
   def is_host_platform(self):
@@ -238,6 +241,7 @@
     """
     assert self._platform_backend.CanMonitorPower()
     self._platform_backend.StartMonitoringPower(browser)
+    self._is_monitoring_power = True
 
   def StopMonitoringPower(self):
     """Stops monitoring power utilization and returns stats
@@ -280,7 +284,13 @@
 
       }
     """
-    return self._platform_backend.StopMonitoringPower()
+    ret_val = self._platform_backend.StopMonitoringPower()
+    self._is_monitoring_power = False
+    return ret_val
+
+  def IsMonitoringPower(self):
+    """Returns true if power is currently being monitored, false otherwise."""
+    return self._is_monitoring_power
 
   def CanMonitorNetworkData(self):
     """Returns true if network data can be retrieved, false otherwise."""
@@ -321,3 +331,45 @@
     |server.Close()| should be called manually to close the started server.
     """
     self._local_server_controller.StartServer(server)
+
+  @property
+  def http_server(self):
+    return self._local_server_controller.GetRunningServer(
+        memory_cache_http_server.MemoryCacheHTTPServer, None)
+
+  def SetHTTPServerDirectories(self, paths):
+    """Returns True if the HTTP server was started, False otherwise."""
+    if isinstance(paths, basestring):
+      paths = set([paths])
+    paths = set(os.path.realpath(p) for p in paths)
+
+    # If any path is in a subdirectory of another, remove the subdirectory.
+    duplicates = set()
+    for parent_path in paths:
+      for sub_path in paths:
+        if parent_path == sub_path:
+          continue
+        if os.path.commonprefix((parent_path, sub_path)) == parent_path:
+          duplicates.add(sub_path)
+    paths -= duplicates
+
+    if self.http_server:
+      if paths and self.http_server.paths == paths:
+        return False
+
+      self.http_server.Close()
+
+    if not paths:
+      return False
+
+    server = memory_cache_http_server.MemoryCacheHTTPServer(paths)
+    self.StartLocalServer(server)
+    return True
+
+  def StopAllLocalServers(self):
+    self._local_server_controller.Close()
+
+  @property
+  def local_servers(self):
+    """Returns the currently running local servers."""
+    return self._local_server_controller.local_servers
diff --git a/tools/telemetry/telemetry/core/tracing_controller_unittest.py b/tools/telemetry/telemetry/core/tracing_controller_unittest.py
index 2b58d7d..adb5dc8 100644
--- a/tools/telemetry/telemetry/core/tracing_controller_unittest.py
+++ b/tools/telemetry/telemetry/core/tracing_controller_unittest.py
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from telemetry import decorators
+from telemetry.core import platform as platform_module
+from telemetry.testing import browser_test_case
 from telemetry.testing import tab_test_case
 from telemetry.timeline import model as model_module
 from telemetry.timeline import tracing_category_filter
@@ -84,3 +87,46 @@
     self.assertFalse(tracing_controller.is_tracing_running)
     # Calling stop again will raise exception
     self.assertRaises(Exception, tracing_controller.Stop)
+
+  def _StartupTracing(self, platform):
+    # Stop browser
+    browser_test_case.teardown_browser()
+
+    # Start tracing
+    self.assertFalse(platform.tracing_controller.is_tracing_running)
+    trace_options = tracing_options.TracingOptions()
+    trace_options.enable_chrome_trace = True
+    category_filter = tracing_category_filter.TracingCategoryFilter()
+    platform.tracing_controller.Start(trace_options, category_filter)
+    self.assertTrue(platform.tracing_controller.is_tracing_running)
+
+    try:
+      # Start browser
+      self.setUpClass()
+      self._browser.tabs[0].Navigate('about:blank')
+      self._browser.tabs[0].WaitForDocumentReadyStateToBeInteractiveOrBetter()
+      self.assertEquals(platform, self._browser.platform)
+      # Calling start tracing again will return False
+      self.assertFalse(self._browser.platform.tracing_controller.Start(
+          trace_options, category_filter))
+
+      trace_data = self._browser.platform.tracing_controller.Stop()
+      # Test that trace data is parsable
+      model_module.TimelineModel(trace_data)
+      self.assertFalse(
+          self._browser.platform.tracing_controller.is_tracing_running)
+      # Calling stop tracing again will raise exception
+      self.assertRaises(Exception,
+                        self._browser.platform.tracing_controller.Stop)
+    finally:
+      if self._browser:
+        self._browser.Close()
+        self._browser = None
+
+  @decorators.Enabled('android')
+  def testStartupTracingOnAndroid(self):
+    self._StartupTracing(self._browser.platform)
+
+  @decorators.Enabled('linux', 'mac', 'win')
+  def testStartupTracingOnDesktop(self):
+    self._StartupTracing(platform_module.GetHostPlatform())
diff --git a/tools/telemetry/telemetry/internal/backends/browser_backend.py b/tools/telemetry/telemetry/internal/backends/browser_backend.py
index 6e3de6cc..d5b71e8 100644
--- a/tools/telemetry/telemetry/internal/backends/browser_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/browser_backend.py
@@ -134,6 +134,14 @@
     raise NotImplementedError()
 
   @property
+  def supports_overriding_memory_pressure_notifications(self):
+    return False
+
+  def SetMemoryPressureNotificationsSuppressed(
+      self, suppressed, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT):
+    raise NotImplementedError()
+
+  @property
   def supports_cpu_metrics(self):
     raise NotImplementedError()
 
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py b/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py
index 7fa3b983..75d010a 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome/chrome_browser_backend.py
@@ -324,6 +324,14 @@
     return self.devtools_client.DumpMemory(timeout)
 
   @property
+  def supports_overriding_memory_pressure_notifications(self):
+    return True
+
+  def SetMemoryPressureNotificationsSuppressed(
+      self, suppressed, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT):
+    self.devtools_client.SetMemoryPressureNotificationsSuppressed(suppressed)
+
+  @property
   def supports_cpu_metrics(self):
     return True
 
diff --git a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
index 9c5802d9..fe58c015 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
@@ -218,6 +218,10 @@
         args.append('--ppapi-flash-path=%s' % self._flash_path)
       if not self.browser_options.dont_override_profile:
         args.append('--user-data-dir=%s' % self._tmp_profile_dir)
+    trace_config_file = (self.platform_backend.tracing_controller_backend
+                         .GetChromeTraceConfigFile())
+    if trace_config_file:
+      args.append('--trace-config-file=%s' % trace_config_file)
     return args
 
   def Start(self):
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
index 426219e..9fd994f 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
@@ -12,6 +12,7 @@
 from telemetry.internal.backends.chrome_inspector import devtools_http
 from telemetry.internal.backends.chrome_inspector import inspector_backend
 from telemetry.internal.backends.chrome_inspector import tracing_backend
+from telemetry.internal.platform.tracing_agent import chrome_tracing_agent
 from telemetry.internal.platform.tracing_agent import (
     chrome_tracing_devtools_manager)
 from telemetry.timeline import trace_data as trace_data_module
@@ -75,10 +76,29 @@
 
     if not self.supports_tracing:
       return
-    self._tracing_backend = tracing_backend.TracingBackend(self._devtools_port)
     chrome_tracing_devtools_manager.RegisterDevToolsClient(
         self, self._app_backend.platform_backend)
 
+    # Telemetry has started Chrome tracing if there is trace config, so start
+    # tracing on this newly created devtools client if needed.
+    trace_config = (self._app_backend.platform_backend
+                    .tracing_controller_backend.GetChromeTraceConfig())
+    if not trace_config:
+      self._tracing_backend = tracing_backend.TracingBackend(
+          self._devtools_port, False)
+      return
+
+    if self.support_startup_tracing:
+      self._tracing_backend = tracing_backend.TracingBackend(
+          self._devtools_port, True)
+      return
+
+    self._tracing_backend = tracing_backend.TracingBackend(
+        self._devtools_port, False)
+    self.StartChromeTracing(
+        trace_options=trace_config.tracing_options,
+        custom_categories=trace_config.tracing_category_filter.filter_string)
+
   @property
   def remote_port(self):
     return self._remote_devtools_port
@@ -90,6 +110,13 @@
     return self._app_backend.supports_tracing
 
   @property
+  def supports_overriding_memory_pressure_notifications(self):
+    if not isinstance(self._app_backend, browser_backend.BrowserBackend):
+      return False
+    return self._app_backend.supports_overriding_memory_pressure_notifications
+
+
+  @property
   def is_tracing_running(self):
     if not self.supports_tracing:
       return False
@@ -97,6 +124,18 @@
       return False
     return self._tracing_backend.is_tracing_running
 
+  @property
+  def support_startup_tracing(self):
+    # Startup tracing with --trace-config-file flag was not supported until
+    # Chromium branch number 2512 (see crrev.com/1309243004 and
+    # crrev.com/1353583002).
+    if not chrome_tracing_agent.ChromeTracingAgent.IsStartupTracingSupported(
+        self._app_backend.platform_backend):
+      return False
+    # TODO(zhenw): Remove this once stable Chrome and reference browser have
+    # passed 2512.
+    return self.GetChromeBranchNumber() >= 2512
+
   def IsAlive(self):
     """Whether the DevTools server is available and connectable."""
     return _IsDevToolsAgentAvailable(self._devtools_http)
@@ -258,6 +297,25 @@
     self._CreateTracingBackendIfNeeded()
     return self._tracing_backend.DumpMemory(timeout)
 
+  def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30):
+    """Enable/disable suppressing memory pressure notifications.
+
+    Args:
+      suppressed: If true, memory pressure notifications will be suppressed.
+      timeout: The timeout in seconds.
+
+    Raises:
+      TracingTimeoutException: If more than |timeout| seconds has passed
+      since the last time any data is received.
+      TracingUnrecoverableException: If there is a websocket error.
+      TracingUnexpectedResponseException: If the response contains an error
+      or does not contain the expected result.
+    """
+    assert self.supports_overriding_memory_pressure_notifications
+    self._CreateTracingBackendIfNeeded()
+    return self._tracing_backend.SetMemoryPressureNotificationsSuppressed(
+        suppressed, timeout)
+
 
 class _DevToolsContextMapBackend(object):
   def __init__(self, app_backend, devtools_client):
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_websocket.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_websocket.py
index 7a530fe..7eaaaea 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_websocket.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/inspector_websocket.py
@@ -15,6 +15,9 @@
 
 class InspectorWebsocket(object):
 
+  # See http://www.jsonrpc.org/specification#error_object.
+  METHOD_NOT_FOUND_CODE = -32601
+
   def __init__(self):
     """Create a websocket handler for communicating with Inspectors."""
     self._socket = None
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py
index dadf4a3..b2f23c97 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend.py
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import json
+import logging
 import socket
 import sys
 import time
@@ -97,7 +98,7 @@
 
 
 class TracingBackend(object):
-  def __init__(self, devtools_port):
+  def __init__(self, devtools_port, is_tracing_running=False):
     self._inspector_websocket = inspector_websocket.InspectorWebsocket()
     self._inspector_websocket.RegisterDomain(
         'Tracing', self._NotificationHandler)
@@ -105,7 +106,7 @@
     self._inspector_websocket.Connect(
         'ws://127.0.0.1:%i/devtools/browser' % devtools_port)
     self._trace_events = []
-    self._is_tracing_running = False
+    self._is_tracing_running = is_tracing_running
     self._has_received_all_tracing_data = False
 
   @property
@@ -194,6 +195,45 @@
     result = response['result']
     return result['dumpGuid'] if result['success'] else None
 
+  def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30):
+    """Enable/disable suppressing memory pressure notifications.
+
+    Args:
+      suppressed: If true, memory pressure notifications will be suppressed.
+      timeout: The timeout in seconds.
+
+    Raises:
+      TracingTimeoutException: If more than |timeout| seconds has passed
+      since the last time any data is received.
+      TracingUnrecoverableException: If there is a websocket error.
+      TracingUnexpectedResponseException: If the response contains an error
+      or does not contain the expected result.
+    """
+    request = {
+      'method': 'Memory.setPressureNotificationsSuppressed',
+      'params': {
+        'suppressed': suppressed
+      }
+    }
+    try:
+      response = self._inspector_websocket.SyncRequest(request, timeout)
+    except websocket.WebSocketTimeoutException:
+      raise TracingTimeoutException
+    except (socket.error, websocket.WebSocketException,
+            inspector_websocket.WebSocketDisconnected):
+      raise TracingUnrecoverableException
+
+    if 'error' in response:
+      code = response['error']['code']
+      if code == inspector_websocket.InspectorWebsocket.METHOD_NOT_FOUND_CODE:
+        logging.warning('Memory.setPressureNotificationsSuppressed DevTools '
+                        'method not supported by the browser')
+      else:
+        raise TracingUnexpectedResponseException(
+            'Inspector returned unexpected response for '
+            'Memory.setPressureNotificationsSuppressed:\n' +
+            json.dumps(response, indent=2))
+
   def _CollectTracingData(self, timeout):
     """Collects tracing data. Assumes that Tracing.end has already been sent.
 
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py
index cfb4d309..822ac2d 100644
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py
+++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py
@@ -4,6 +4,7 @@
 
 import unittest
 
+from telemetry.internal.backends.chrome_inspector import inspector_websocket
 from telemetry.internal.backends.chrome_inspector import tracing_backend
 from telemetry.internal.backends.chrome_inspector import websocket
 from telemetry.testing import simple_mock
@@ -86,6 +87,12 @@
     else:
       raise Exception('Unexpected response type')
 
+  def CreateTracingBackend(self):
+    with mock.patch('telemetry.internal.backends.chrome_inspector.'
+                    'inspector_websocket.InspectorWebsocket') as mock_class:
+      mock_class.return_value = self
+      return tracing_backend.TracingBackend(devtools_port=65000)
+
 
 class TracingBackendTest(tab_test_case.TabTestCase):
 
@@ -96,7 +103,7 @@
       self.skipTest('Browser does not support tracing, skipping test.')
 
 
-class TracingBackendMemoryTest(TracingBackendTest):
+class TracingBackendMemoryDumpTest(TracingBackendTest):
 
   # Number of consecutively requested memory dumps.
   _REQUESTED_DUMP_COUNT = 3
@@ -113,7 +120,7 @@
     ])
 
   def setUp(self):
-    super(TracingBackendMemoryTest, self).setUp()
+    super(TracingBackendMemoryDumpTest, self).setUp()
     if not self._browser.supports_memory_dumping:
       self.skipTest('Browser does not support memory dumping, skipping test.')
 
@@ -177,6 +184,34 @@
     self.assertEqual(len(list(model.IterGlobalMemoryDumps())), 0)
 
 
+class TracingBackendMemoryPressureNotificationsTest(TracingBackendTest):
+
+  def setUp(self):
+    super(TracingBackendMemoryPressureNotificationsTest, self).setUp()
+    if not self._browser.supports_overriding_memory_pressure_notifications:
+      self.skipTest('Browser does not support overriding memory pressure '
+                    'notification signals, skipping test.')
+
+  def testSetMemoryPressureNotificationsSuppressed(self):
+    def perform_check(suppressed):
+      # Check that the method sends the correct DevTools request.
+      with mock.patch.object(inspector_websocket.InspectorWebsocket,
+                             'SyncRequest') as mock_method:
+        self._browser.SetMemoryPressureNotificationsSuppressed(suppressed)
+        self.assertEqual(1, mock_method.call_count)
+        request = mock_method.call_args[0][0]
+        self.assertEqual('Memory.setPressureNotificationsSuppressed',
+                         request['method'])
+        self.assertEqual(suppressed, request['params']['suppressed'])
+
+      # Check that the request and the response from the browser are handled
+      # properly.
+      self._browser.SetMemoryPressureNotificationsSuppressed(suppressed)
+
+    perform_check(True)
+    perform_check(False)
+
+
 class TracingBackendUnitTest(unittest.TestCase):
   def setUp(self):
     self._mock_timer = simple_mock.MockTimer(tracing_backend)
@@ -189,11 +224,7 @@
     inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9)
     inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 19)
     inspector.AddEvent('Tracing.tracingComplete', {}, 35)
-
-    with mock.patch('telemetry.internal.backends.chrome_inspector.'
-                    'inspector_websocket.InspectorWebsocket') as mock_class:
-      mock_class.return_value = inspector
-      backend = tracing_backend.TracingBackend(devtools_port=65000)
+    backend = inspector.CreateTracingBackend()
 
     # The third response is 16 seconds after the second response, so we expect
     # a TracingTimeoutException.
@@ -207,11 +238,7 @@
     inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'B'}]}, 9)
     inspector.AddEvent('Tracing.dataCollected', {'value': [{'ph': 'E'}]}, 14)
     inspector.AddEvent('Tracing.tracingComplete', {}, 19)
-
-    with mock.patch('telemetry.internal.backends.chrome_inspector.'
-                    'inspector_websocket.InspectorWebsocket') as mock_class:
-      mock_class.return_value = inspector
-      backend = tracing_backend.TracingBackend(devtools_port=65000)
+    backend = inspector.CreateTracingBackend()
 
     backend._CollectTracingData(10)
     self.assertEqual(2, len(backend._trace_events))
@@ -222,11 +249,7 @@
     inspector.AddEvent('Tracing.tracingComplete', {'stream': '42'}, 1)
     inspector.AddAsyncResponse('IO.read', {'data': '[{},{},{'}, 2)
     inspector.AddAsyncResponse('IO.read', {'data': '},{},{}]', 'eof': True}, 3)
-
-    with mock.patch('telemetry.internal.backends.chrome_inspector.'
-                    'inspector_websocket.InspectorWebsocket') as mock_class:
-      mock_class.return_value = inspector
-      backend = tracing_backend.TracingBackend(devtools_port=65000)
+    backend = inspector.CreateTracingBackend()
 
     backend._CollectTracingData(10)
     self.assertEqual(5, len(backend._trace_events))
@@ -237,11 +260,7 @@
     inspector.AddResponseHandler(
         'Tracing.requestMemoryDump',
         lambda req: {'result': {'success': True, 'dumpGuid': '42abc'}})
-
-    with mock.patch('telemetry.internal.backends.chrome_inspector.'
-                    'inspector_websocket.InspectorWebsocket') as mock_class:
-      mock_class.return_value = inspector
-      backend = tracing_backend.TracingBackend(devtools_port=65000)
+    backend = inspector.CreateTracingBackend()
 
     self.assertEqual(backend.DumpMemory(), '42abc')
 
@@ -250,10 +269,48 @@
     inspector.AddResponseHandler(
         'Tracing.requestMemoryDump',
         lambda req: {'result': {'success': False, 'dumpGuid': '42abc'}})
-
-    with mock.patch('telemetry.internal.backends.chrome_inspector.'
-                    'inspector_websocket.InspectorWebsocket') as mock_class:
-      mock_class.return_value = inspector
-      backend = tracing_backend.TracingBackend(devtools_port=65000)
+    backend = inspector.CreateTracingBackend()
 
     self.assertIsNone(backend.DumpMemory())
+
+  def testSetMemoryPressureNotificationsSuppressedSuccess(self):
+    response_handler = mock.Mock(return_value={'result': {}})
+    inspector = FakeInspectorWebsocket(self._mock_timer)
+    inspector.AddResponseHandler(
+        'Memory.setPressureNotificationsSuppressed', response_handler)
+    backend = inspector.CreateTracingBackend()
+
+    backend.SetMemoryPressureNotificationsSuppressed(True)
+    self.assertEqual(1, response_handler.call_count)
+    self.assertTrue(response_handler.call_args[0][0]['params']['suppressed'])
+
+    backend.SetMemoryPressureNotificationsSuppressed(False)
+    self.assertEqual(2, response_handler.call_count)
+    self.assertFalse(response_handler.call_args[0][0]['params']['suppressed'])
+
+  def testSetMemoryPressureNotificationsSuppressedFailure(self):
+    response_handler = mock.Mock()
+    inspector = FakeInspectorWebsocket(self._mock_timer)
+    backend = inspector.CreateTracingBackend()
+    inspector.AddResponseHandler(
+        'Memory.setPressureNotificationsSuppressed', response_handler)
+
+    # If the DevTools method is missing, the backend should fail silently.
+    response_handler.return_value = {
+      'result': {},
+      'error': {
+        'code': -32601  # Method does not exist.
+      }
+    }
+    backend.SetMemoryPressureNotificationsSuppressed(True)
+    self.assertEqual(1, response_handler.call_count)
+
+    # All other errors should raise an exception.
+    response_handler.return_value = {
+      'result': {},
+      'error': {
+        'code': -32602  # Invalid method params.
+      }
+    }
+    self.assertRaises(tracing_backend.TracingUnexpectedResponseException,
+                      backend.SetMemoryPressureNotificationsSuppressed, True)
diff --git a/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_finder.py b/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_finder.py
index ea1e4f78..b88b2a27 100644
--- a/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_finder.py
+++ b/tools/telemetry/telemetry/internal/backends/mandoline/desktop_mandoline_finder.py
@@ -85,6 +85,7 @@
   return [
       'mandoline-debug',
       'mandoline-debug_x64',
+      'mandoline-default',
       'mandoline-release',
       'mandoline-release_x64',]
 
diff --git a/tools/telemetry/telemetry/internal/browser/browser.py b/tools/telemetry/telemetry/internal/browser/browser.py
index d9b1386..5f26aade 100644
--- a/tools/telemetry/telemetry/internal/browser/browser.py
+++ b/tools/telemetry/telemetry/internal/browser/browser.py
@@ -3,14 +3,11 @@
 # found in the LICENSE file.
 
 import logging
-import os
 import sys
 
 from catapult_base import cloud_storage
 
 from telemetry.core import exceptions
-from telemetry.core import local_server
-from telemetry.core import memory_cache_http_server
 from telemetry.core import profiling_controller
 from telemetry import decorators
 from telemetry.internal import app
@@ -39,9 +36,6 @@
     try:
       self._browser_backend = backend
       self._platform_backend = platform_backend
-      # TODO: move _local_server_controller to Platform.
-      self._local_server_controller = local_server.LocalServerController(
-          platform_backend)
       self._tabs = tab_list.TabList(backend.tab_list_backend)
       self.credentials = browser_credentials.BrowserCredentials()
       self.credentials.credentials_path = credentials_path
@@ -231,7 +225,6 @@
     if self._browser_backend.IsBrowserRunning():
       self._platform_backend.WillCloseBrowser(self, self._browser_backend)
 
-    self._local_server_controller.Close()
     self._browser_backend.profiling_controller_backend.WillCloseBrowser()
     if self._browser_backend.supports_uploading_logs:
       try:
@@ -241,51 +234,6 @@
     self._browser_backend.Close()
     self.credentials = None
 
-  @property
-  def http_server(self):
-    return self._local_server_controller.GetRunningServer(
-        memory_cache_http_server.MemoryCacheHTTPServer, None)
-
-  def SetHTTPServerDirectories(self, paths):
-    """Returns True if the HTTP server was started, False otherwise."""
-    if isinstance(paths, basestring):
-      paths = set([paths])
-    paths = set(os.path.realpath(p) for p in paths)
-
-    # If any path is in a subdirectory of another, remove the subdirectory.
-    duplicates = set()
-    for parent_path in paths:
-      for sub_path in paths:
-        if parent_path == sub_path:
-          continue
-        if os.path.commonprefix((parent_path, sub_path)) == parent_path:
-          duplicates.add(sub_path)
-    paths -= duplicates
-
-    if self.http_server:
-      if paths and self.http_server.paths == paths:
-        return False
-
-      self.http_server.Close()
-
-    if not paths:
-      return False
-
-    server = memory_cache_http_server.MemoryCacheHTTPServer(paths)
-    self.StartLocalServer(server)
-    return True
-
-  def StartLocalServer(self, server):
-    """Starts a LocalServer and associates it with this browser.
-
-    It will be closed when the browser closes.
-    """
-    self._local_server_controller.StartServer(server)
-
-  @property
-  def local_servers(self):
-    """Returns the currently running local servers."""
-    return self._local_server_controller.local_servers
 
   def GetStandardOutput(self):
     return self._browser_backend.GetStandardOutput()
@@ -311,6 +259,16 @@
     return self._browser_backend.DumpMemory(timeout)
 
   @property
+  def supports_overriding_memory_pressure_notifications(self):
+    return (
+        self._browser_backend.supports_overriding_memory_pressure_notifications)
+
+  def SetMemoryPressureNotificationsSuppressed(
+      self, suppressed, timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT):
+    self._browser_backend.SetMemoryPressureNotificationsSuppressed(
+        suppressed, timeout)
+
+  @property
   def supports_cpu_metrics(self):
     return self._browser_backend.supports_cpu_metrics
 
diff --git a/tools/telemetry/telemetry/internal/browser/browser_unittest.py b/tools/telemetry/telemetry/internal/browser/browser_unittest.py
index 60f04cb..21b0b57 100644
--- a/tools/telemetry/telemetry/internal/browser/browser_unittest.py
+++ b/tools/telemetry/telemetry/internal/browser/browser_unittest.py
@@ -175,9 +175,9 @@
   options.output_profile_path = profile_dir
   browser_to_create = browser_finder.FindBrowser(options)
   with browser_to_create.Create(options) as browser:
-    browser.SetHTTPServerDirectories(path.GetUnittestDataDir())
+    browser.platform.SetHTTPServerDirectories(path.GetUnittestDataDir())
     blank_file_path = os.path.join(path.GetUnittestDataDir(), 'blank.html')
-    blank_url = browser.http_server.UrlOf(blank_file_path)
+    blank_url = browser.platform.http_server.UrlOf(blank_file_path)
     browser.foreground_tab.Navigate(blank_url)
     browser.foreground_tab.WaitForDocumentReadyStateToBeComplete()
     for _ in xrange(number_of_tabs - 1):
diff --git a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent.py b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent.py
index 5c4bea86..2be6af4 100644
--- a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent.py
+++ b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent.py
@@ -12,8 +12,10 @@
 from telemetry.internal.platform import tracing_agent
 from telemetry.internal.platform.tracing_agent import (
     chrome_tracing_devtools_manager)
+from telemetry.timeline import tracing_config
 
 _DESKTOP_OS_NAMES = ['linux', 'mac', 'win']
+_STARTUP_TRACING_OS_NAMES = _DESKTOP_OS_NAMES + ['android']
 
 # The trace config file path should be the same as specified in
 # src/components/tracing/startup_tracing.cc
@@ -32,18 +34,40 @@
 class ChromeTracingAgent(tracing_agent.TracingAgent):
   def __init__(self, platform_backend):
     super(ChromeTracingAgent, self).__init__(platform_backend)
+    self._trace_config = None
     self._trace_config_file = None
 
   @property
+  def trace_config(self):
+    # Trace config is also used to check if Chrome tracing is running or not.
+    return self._trace_config
+
+  @property
   def trace_config_file(self):
     return self._trace_config_file
 
   @classmethod
-  def IsSupported(cls, platform_backend):
-    return chrome_tracing_devtools_manager.IsSupported(platform_backend)
+  def IsStartupTracingSupported(cls, platform_backend):
+    if platform_backend.GetOSName() in _STARTUP_TRACING_OS_NAMES:
+      return True
+    else:
+      return False
 
-  def Start(self, trace_options, category_filter, timeout):
-    if not trace_options.enable_chrome_trace:
+  @classmethod
+  def IsSupported(cls, platform_backend):
+    if cls.IsStartupTracingSupported(platform_backend):
+      return True
+    else:
+      return chrome_tracing_devtools_manager.IsSupported(platform_backend)
+
+  def _StartStartupTracing(self, config):
+    if not self.IsStartupTracingSupported(self._platform_backend):
+      return False
+    self._CreateTraceConfigFile(config)
+    return True
+
+  def _StartDevToolsTracing(self, trace_options, category_filter, timeout):
+    if not chrome_tracing_devtools_manager.IsSupported(self._platform_backend):
       return False
     devtools_clients = (chrome_tracing_devtools_manager
         .GetActiveDevToolsClients(self._platform_backend))
@@ -58,7 +82,39 @@
           trace_options, category_filter.filter_string, timeout)
     return True
 
+  def Start(self, trace_options, category_filter, timeout):
+    if not trace_options.enable_chrome_trace:
+      return False
+
+    if self._trace_config:
+      raise ChromeTracingStartedError(
+          'Tracing is already running on platform backend %s.'
+          % self._platform_backend)
+
+    # Chrome tracing Agent needs to start tracing for chrome browsers that are
+    # not yet started, and for the ones that already are. For the former, we
+    # first setup the trace_config_file, which allows browsers that starts after
+    # this point to use it for enabling tracing upon browser startup. For the
+    # latter, we invoke start tracing command through devtools for browsers that
+    # are already started and tracked by chrome_tracing_devtools_manager.
+    config = tracing_config.TracingConfig(trace_options, category_filter)
+    started_startup_tracing = self._StartStartupTracing(config)
+    started_devtools_tracing = self._StartDevToolsTracing(
+        trace_options, category_filter, timeout)
+    if started_startup_tracing or started_devtools_tracing:
+      self._trace_config = config
+      return True
+    return False
+
   def Stop(self, trace_data_builder):
+    if not self._trace_config:
+      raise ChromeTracingStoppedError(
+          'Tracing is not running on platform backend %s.'
+          % self._platform_backend)
+
+    if self.IsStartupTracingSupported(self._platform_backend):
+      self._RemoveTraceConfigFile()
+
     # We get all DevTools clients including the stale ones, so that we get an
     # exception if there is a stale client. This is because we will potentially
     # lose data if there is a stale client.
@@ -74,23 +130,29 @@
           % (client.remote_port,
              ''.join(traceback.format_exception(*sys.exc_info()))))
 
+    self._trace_config = None
     if raised_execption_messages:
       raise ChromeTracingStoppedError(
           'Exceptions raised when trying to stop Chrome devtool tracing:\n' +
           '\n'.join(raised_execption_messages))
 
+  def _CreateTraceConfigFileString(self, config):
+    # See src/components/tracing/trace_config_file.h for the format
+    trace_config_str = config.GetTraceConfigJsonString()
+    return '{"trace_config":' + trace_config_str + '}'
+
   def _CreateTraceConfigFile(self, config):
     assert not self._trace_config_file
     if self._platform_backend.GetOSName() == 'android':
       self._trace_config_file = os.path.join(_CHROME_TRACE_CONFIG_DIR_ANDROID,
                                              _CHROME_TRACE_CONFIG_FILE_NAME)
       self._platform_backend.device.WriteFile(self._trace_config_file,
-          config.GetTraceConfigJsonString(), as_root=True)
+          self._CreateTraceConfigFileString(config), as_root=True)
     elif self._platform_backend.GetOSName() in _DESKTOP_OS_NAMES:
       self._trace_config_file = os.path.join(tempfile.mkdtemp(),
                                              _CHROME_TRACE_CONFIG_FILE_NAME)
       with open(self._trace_config_file, 'w') as f:
-        f.write(config.GetTraceConfigJsonString())
+        f.write(self._CreateTraceConfigFileString(config))
       os.chmod(self._trace_config_file,
                os.stat(self._trace_config_file).st_mode | stat.S_IROTH)
     else:
diff --git a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent_unittest.py b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent_unittest.py
index f3ef5c41c..39a4757 100644
--- a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent_unittest.py
+++ b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_agent_unittest.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 import os
+import platform
 import stat
 import unittest
 
@@ -25,6 +26,8 @@
   def __init__(self):
     self.tracing_controller_backend = FakeTracingControllerBackend()
 
+  def GetOSName(self):
+    return ''
 
 class FakeAndroidPlatformBackend(FakePlatformBackend):
   def __init__(self):
@@ -35,17 +38,15 @@
   def GetOSName(self):
     return 'android'
 
-class FakeLinuxPlatformBackend(FakePlatformBackend):
+class FakeDesktopPlatformBackend(FakePlatformBackend):
   def GetOSName(self):
-    return 'linux'
-
-class FakeMacPlatformBackend(FakePlatformBackend):
-  def GetOSName(self):
-    return 'mac'
-
-class FakeWinPlatformBackend(FakePlatformBackend):
-  def GetOSName(self):
-    return 'win'
+    system = platform.system()
+    if system == 'Linux':
+      return 'linux'
+    if system == 'Darwin':
+      return 'mac'
+    if system == 'Windows':
+      return 'win'
 
 
 class FakeDevtoolsClient(object):
@@ -70,16 +71,6 @@
     return True
 
 
-class FakeTraceOptions(object):
-  def __init__(self):
-    self.enable_chrome_trace = True
-
-
-class FakeCategoryFilter(object):
-  def __init__(self):
-    self.filter_string = 'foo'
-
-
 class ChromeTracingAgentTest(unittest.TestCase):
   def setUp(self):
     self.platform1 = FakePlatformBackend()
@@ -89,10 +80,11 @@
   def StartTracing(self, platform_backend, enable_chrome_trace=True):
     assert chrome_tracing_agent.ChromeTracingAgent.IsSupported(platform_backend)
     agent = chrome_tracing_agent.ChromeTracingAgent(platform_backend)
-    trace_options = FakeTraceOptions()
+    trace_options = tracing_options.TracingOptions()
     trace_options.enable_chrome_trace = enable_chrome_trace
+    category_filter = tracing_category_filter.TracingCategoryFilter('foo')
     agent._platform_backend.tracing_controller_backend.is_tracing_running = True
-    agent.Start(trace_options, FakeCategoryFilter(), 10)
+    agent.Start(trace_options, category_filter, 10)
     return agent
 
   def StopTracing(self, agent):
@@ -110,9 +102,7 @@
 
     tracing_agent_of_platform1 = self.StartTracing(self.platform1)
 
-    with self.assertRaises(
-        chrome_tracing_devtools_manager.RegisterDevToolsClientError):
-      chrome_tracing_devtools_manager.RegisterDevToolsClient(
+    chrome_tracing_devtools_manager.RegisterDevToolsClient(
         FakeDevtoolsClient(4), self.platform1)
     chrome_tracing_devtools_manager.RegisterDevToolsClient(
         FakeDevtoolsClient(5), self.platform2)
@@ -121,7 +111,7 @@
     chrome_tracing_devtools_manager.RegisterDevToolsClient(
         FakeDevtoolsClient(6), self.platform1)
 
-  def testIsSupport(self):
+  def testIsSupportWithoutStartupTracingSupport(self):
     self.assertFalse(
         chrome_tracing_agent.ChromeTracingAgent.IsSupported(self.platform1))
     self.assertFalse(
@@ -146,6 +136,20 @@
     self.assertFalse(
         chrome_tracing_agent.ChromeTracingAgent.IsSupported(self.platform3))
 
+  @decorators.Enabled('linux', 'mac', 'win')
+  def testIsSupportOnDesktopPlatform(self):
+    # Chrome tracing is always supported on desktop platforms because of startup
+    # tracing.
+    desktop_platform = FakeDesktopPlatformBackend()
+    self.assertTrue(
+        chrome_tracing_agent.ChromeTracingAgent.IsSupported(desktop_platform))
+
+    devtool = FakeDevtoolsClient(1)
+    chrome_tracing_devtools_manager.RegisterDevToolsClient(
+        devtool, desktop_platform)
+    self.assertTrue(
+        chrome_tracing_agent.ChromeTracingAgent.IsSupported(desktop_platform))
+
   def testStartAndStopTracing(self):
     devtool1 = FakeDevtoolsClient(1)
     devtool2 = FakeDevtoolsClient(2)
@@ -200,9 +204,13 @@
     self.assertTrue(devtool1.is_tracing_running)
     self.assertTrue(devtool2.is_tracing_running)
 
-    devtool2.will_raise_exception_in_stop_tracing = True
+    devtool1.will_raise_exception_in_stop_tracing = True
     with self.assertRaises(chrome_tracing_agent.ChromeTracingStoppedError):
       self.StopTracing(tracing_agent1)
+    # Tracing is stopped on both devtools clients even if there is exception.
+    self.assertIsNone(tracing_agent1.trace_config)
+    self.assertFalse(devtool1.is_tracing_running)
+    self.assertFalse(devtool2.is_tracing_running)
 
     devtool1.is_alive = False
     devtool2.is_alive = False
@@ -229,7 +237,8 @@
     self.assertTrue(platform_backend.device.PathExists(agent.trace_config_file))
     config_file_str = platform_backend.device.ReadFile(agent.trace_config_file,
                                                        as_root=True)
-    self.assertEqual(config.GetTraceConfigJsonString(), config_file_str.strip())
+    self.assertEqual(agent._CreateTraceConfigFileString(config),
+                     config_file_str.strip())
 
     config_file_path = agent.trace_config_file
     agent._RemoveTraceConfigFile()
@@ -240,7 +249,9 @@
     self.assertFalse(platform_backend.device.PathExists(config_file_path))
     self.assertIsNone(agent.trace_config_file)
 
-  def CreateAndRemoveTraceConfigFileOnDesktop(self, platform_backend):
+  @decorators.Enabled('linux', 'mac', 'win')
+  def testCreateAndRemoveTraceConfigFileOnDesktop(self):
+    platform_backend = FakeDesktopPlatformBackend()
     agent = chrome_tracing_agent.ChromeTracingAgent(platform_backend)
     self.assertIsNone(agent.trace_config_file)
 
@@ -253,7 +264,7 @@
     self.assertTrue(os.stat(agent.trace_config_file).st_mode & stat.S_IROTH)
     with open(agent.trace_config_file, 'r') as f:
       config_file_str = f.read()
-      self.assertEqual(config.GetTraceConfigJsonString(),
+      self.assertEqual(agent._CreateTraceConfigFileString(config),
                        config_file_str.strip())
 
     config_file_path = agent.trace_config_file
@@ -264,15 +275,3 @@
     agent._RemoveTraceConfigFile()
     self.assertFalse(os.path.exists(config_file_path))
     self.assertIsNone(agent.trace_config_file)
-
-  @decorators.Enabled('linux')
-  def testCreateAndRemoveTraceConfigFileOnLinux(self):
-    self.CreateAndRemoveTraceConfigFileOnDesktop(FakeLinuxPlatformBackend())
-
-  @decorators.Enabled('mac')
-  def testCreateAndRemoveTraceConfigFileOnMac(self):
-    self.CreateAndRemoveTraceConfigFileOnDesktop(FakeMacPlatformBackend())
-
-  @decorators.Enabled('win')
-  def testCreateAndRemoveTraceConfigFileOnWin(self):
-    self.CreateAndRemoveTraceConfigFileOnDesktop(FakeWinPlatformBackend())
diff --git a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_devtools_manager.py b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_devtools_manager.py
index de51ea6..ea2bde20 100644
--- a/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_devtools_manager.py
+++ b/tools/telemetry/telemetry/internal/platform/tracing_agent/chrome_tracing_devtools_manager.py
@@ -2,10 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-class RegisterDevToolsClientError(Exception):
-  pass
-
-
 # A singleton map from platform backends to maps of uniquely-identifying
 # remote port (which may be the same as local port) to DevToolsClientBackend.
 # There is no guarantee that the devtools agent is still alive.
@@ -30,11 +26,6 @@
 
   This should only be called from DevToolsClientBackend when it is initialized.
   """
-  if platform_backend.tracing_controller_backend.is_tracing_running:
-    raise RegisterDevToolsClientError(
-        'Cannot add new DevTools client when tracing is running on '
-        'platform backend %s.' % platform_backend)
-
   remote_port = str(devtools_client_backend.remote_port)
   if platform_backend not in _platform_backends_to_devtools_clients_maps:
     _platform_backends_to_devtools_clients_maps[platform_backend] = {}
diff --git a/tools/telemetry/telemetry/internal/platform/tracing_controller_backend.py b/tools/telemetry/telemetry/internal/platform/tracing_controller_backend.py
index 0c66f4a..6e2fff27 100644
--- a/tools/telemetry/telemetry/internal/platform/tracing_controller_backend.py
+++ b/tools/telemetry/telemetry/internal/platform/tracing_controller_backend.py
@@ -50,9 +50,10 @@
 
     self._current_trace_options = trace_options
     self._current_category_filter = category_filter
-    # Hack: chrome tracing agent depends on the number of alive chrome devtools
-    # processes, rather platform, hence we add it to the list of supported
-    # agents here if it was not added.
+    # Hack: chrome tracing agent may only depend on the number of alive chrome
+    # devtools processes, rather platform (when startup tracing is not
+    # supported), hence we add it to the list of supported agents here if it was
+    # not added.
     if (chrome_tracing_agent.ChromeTracingAgent.IsSupported(
         self._platform_backend) and
         not chrome_tracing_agent.ChromeTracingAgent in
@@ -95,3 +96,25 @@
   @property
   def is_tracing_running(self):
     return self._current_trace_options != None
+
+  def _GetActiveChromeTracingAgent(self):
+    if not self.is_tracing_running:
+      return None
+    if not self._current_trace_options.enable_chrome_trace:
+      return None
+    for agent in self._active_agents_instances:
+      if isinstance(agent, chrome_tracing_agent.ChromeTracingAgent):
+        return agent
+    return None
+
+  def GetChromeTraceConfig(self):
+    agent = self._GetActiveChromeTracingAgent()
+    if agent:
+      return agent.trace_config
+    return None
+
+  def GetChromeTraceConfigFile(self):
+    agent = self._GetActiveChromeTracingAgent()
+    if agent:
+      return agent.trace_config_file
+    return None
diff --git a/tools/telemetry/telemetry/internal/story_runner.py b/tools/telemetry/telemetry/internal/story_runner.py
index 79677d9..9fa8874f 100644
--- a/tools/telemetry/telemetry/internal/story_runner.py
+++ b/tools/telemetry/telemetry/internal/story_runner.py
@@ -228,7 +228,7 @@
                 # Later finally-blocks use state, so ensure it is cleared.
                 state = None
             finally:
-              has_existing_exception = sys.exc_info() is not None
+              has_existing_exception = sys.exc_info() != (None, None, None)
               try:
                 if state:
                   _CheckThermalThrottling(state.platform)
@@ -245,7 +245,7 @@
             return
     finally:
       if state:
-        has_existing_exception = sys.exc_info() is not None
+        has_existing_exception = sys.exc_info() != (None, None, None)
         try:
           state.TearDownState()
         except Exception:
diff --git a/tools/telemetry/telemetry/internal/story_runner_unittest.py b/tools/telemetry/telemetry/internal/story_runner_unittest.py
index 4bca54f3..9fc7698 100644
--- a/tools/telemetry/telemetry/internal/story_runner_unittest.py
+++ b/tools/telemetry/telemetry/internal/story_runner_unittest.py
@@ -146,6 +146,10 @@
   return len([run for run in results.all_page_runs if run.ok or run.skipped])
 
 
+class TestOnlyException(Exception):
+  pass
+
+
 class StoryRunnerTest(unittest.TestCase):
 
   def setUp(self):
@@ -381,6 +385,19 @@
     self.assertEquals(0, GetNumberOfSuccessfulPageRuns(self.results))
     self.assertIn('App Foo crashes', self.fake_stdout.getvalue())
 
+  def testExceptionRaisedInSharedStateTearDown(self):
+    self.SuppressExceptionFormatting()
+    story_set = story_module.StorySet()
+    class SharedStoryThatCausesAppCrash(TestSharedPageState):
+      def TearDownState(self):
+        raise TestOnlyException()
+
+    story_set.AddStory(DummyLocalStory(
+          SharedStoryThatCausesAppCrash))
+    with self.assertRaises(TestOnlyException):
+      story_runner.Run(
+          DummyTest(), story_set, self.options, self.results)
+
   def testUnknownExceptionIsFatal(self):
     self.SuppressExceptionFormatting()
     story_set = story_module.StorySet()
diff --git a/tools/telemetry/telemetry/page/action_runner.py b/tools/telemetry/telemetry/page/action_runner.py
index 4c77f72..805e62d6 100644
--- a/tools/telemetry/telemetry/page/action_runner.py
+++ b/tools/telemetry/telemetry/page/action_runner.py
@@ -113,7 +113,7 @@
     the page exists, but before any script on the page itself has executed.
     """
     if urlparse.urlparse(url).scheme == 'file':
-      url = self._tab.browser.http_server.UrlOf(url[7:])
+      url = self._tab.browser.platform.http_server.UrlOf(url[7:])
 
     self._RunAction(NavigateAction(
         url=url,
diff --git a/tools/telemetry/telemetry/page/shared_page_state.py b/tools/telemetry/telemetry/page/shared_page_state.py
index 6b55846..bd879b1 100644
--- a/tools/telemetry/telemetry/page/shared_page_state.py
+++ b/tools/telemetry/telemetry/page/shared_page_state.py
@@ -264,7 +264,7 @@
   def _PreparePage(self):
     self._current_tab = self._test.TabForPage(self._current_page, self.browser)
     if self._current_page.is_file:
-      self.browser.SetHTTPServerDirectories(
+      self.platform.SetHTTPServerDirectories(
           self._current_page.page_set.serving_dirs |
           set([self._current_page.serving_dir]))
 
@@ -310,6 +310,7 @@
       self._migrated_profile = None
 
     self._StopBrowser()
+    self.platform.StopAllLocalServers()
 
   def _StopBrowser(self):
     if self._browser:
diff --git a/tools/telemetry/telemetry/testing/browser_test_case.py b/tools/telemetry/telemetry/testing/browser_test_case.py
index 4d4ec51..3cb1b8d 100644
--- a/tools/telemetry/telemetry/testing/browser_test_case.py
+++ b/tools/telemetry/telemetry/testing/browser_test_case.py
@@ -48,11 +48,12 @@
         cls.tearDownClass()
         raise
     cls._browser = current_browser
+    cls._platform = current_browser.platform
     cls._device = options.device
 
   @classmethod
   def tearDownClass(cls):
-    pass
+    cls._platform.StopAllLocalServers()
 
   @classmethod
   def CustomizeBrowserOptions(cls, options):
@@ -61,6 +62,6 @@
 
   @classmethod
   def UrlOfUnittestFile(cls, filename):
-    cls._browser.SetHTTPServerDirectories(path.GetUnittestDataDir())
+    cls._platform.SetHTTPServerDirectories(path.GetUnittestDataDir())
     file_path = os.path.join(path.GetUnittestDataDir(), filename)
-    return cls._browser.http_server.UrlOf(file_path)
+    return cls._platform.http_server.UrlOf(file_path)
diff --git a/tools/telemetry/telemetry/testing/fakes/__init__.py b/tools/telemetry/telemetry/testing/fakes/__init__.py
index 7e409509..572ec0e 100644
--- a/tools/telemetry/telemetry/testing/fakes/__init__.py
+++ b/tools/telemetry/telemetry/testing/fakes/__init__.py
@@ -53,6 +53,9 @@
   def GetOSVersionName(self):
     raise NotImplementedError
 
+  def StopAllLocalServers(self):
+    pass
+
 
 class FakeLinuxPlatform(FakePlatform):
   @property
diff --git a/tools/telemetry/telemetry/testing/run_tests.py b/tools/telemetry/telemetry/testing/run_tests.py
index ce3a82d..15c7c9bb 100644
--- a/tools/telemetry/telemetry/testing/run_tests.py
+++ b/tools/telemetry/telemetry/testing/run_tests.py
@@ -5,6 +5,7 @@
 import sys
 
 from telemetry.core import util
+from telemetry.core import platform as platform_module
 from telemetry import decorators
 from telemetry.internal.browser import browser_finder
 from telemetry.internal.browser import browser_finder_exceptions
@@ -38,6 +39,8 @@
   def AddCommandLineArgs(cls, parser, _):
     parser.add_option('--repeat-count', type='int', default=1,
                       help='Repeats each a provided number of times.')
+    parser.add_option('--no-browser', action='store_true', default=False,
+                      help='Don\'t require an actual browser to run the tests.')
     parser.add_option('-d', '--also-run-disabled-tests',
                       dest='run_disabled_tests',
                       action='store_true', default=False,
@@ -62,6 +65,9 @@
     if not args.retry_limit and not args.positional_args:
       args.retry_limit = 3
 
+    if args.no_browser:
+      return
+
     try:
       possible_browser = browser_finder.FindBrowser(args)
     except browser_finder_exceptions.BrowserFinderException, ex:
@@ -91,12 +97,17 @@
     return obj.Run(options)
 
   def Run(self, args):
-    possible_browser = browser_finder.FindBrowser(args)
-
     runner = typ.Runner()
     if self.stream:
       runner.host.stdout = self.stream
 
+    if args.no_browser:
+      possible_browser = None
+      platform = platform_module.GetHostPlatform()
+    else:
+      possible_browser = browser_finder.FindBrowser(args)
+      platform = possible_browser.platform
+
     # Telemetry seems to overload the system if we run one test per core,
     # so we scale things back a fair amount. Many of the telemetry tests
     # are long-running, so there's a limit to how much parallelism we
@@ -104,12 +115,12 @@
     #
     # It should be possible to handle multiple devices if we adjust the
     # browser_finder code properly, but for now we only handle one on ChromeOS.
-    if possible_browser.platform.GetOSName() == 'chromeos':
+    if platform.GetOSName() == 'chromeos':
       runner.args.jobs = 1
-    elif possible_browser.platform.GetOSName() == 'android':
+    elif platform.GetOSName() == 'android':
       runner.args.jobs = len(device_finder.GetDevicesMatchingOptions(args))
       print 'Running tests with %d Android device(s).' % runner.args.jobs
-    elif possible_browser.platform.GetOSVersionName() == 'xp':
+    elif platform.GetOSVersionName() == 'xp':
       # For an undiagnosed reason, XP falls over with more parallelism.
       # See crbug.com/388256
       runner.args.jobs = max(int(args.jobs) // 4, 1)
@@ -147,7 +158,22 @@
 
 
 def GetClassifier(args, possible_browser):
-  def ClassifyTest(test_set, test):
+
+  def ClassifyTestWithoutBrowser(test_set, test):
+    name = test.id()
+    if (not args.positional_args
+        or _MatchesSelectedTest(name, args.positional_args,
+                                  args.exact_test_filter)):
+      # TODO(telemetry-team): Make sure that all telemetry unittest that invokes
+      # actual browser are subclasses of browser_test_case.BrowserTestCase
+      # (crbug.com/537428)
+      if issubclass(test.__class__, browser_test_case.BrowserTestCase):
+        test_set.tests_to_skip.append(typ.TestInput(
+            name, msg='Skip the test because it requires a browser.'))
+      else:
+        test_set.parallel_tests.append(typ.TestInput(name))
+
+  def ClassifyTestWithBrowser(test_set, test):
     name = test.id()
     if (not args.positional_args
         or _MatchesSelectedTest(name, args.positional_args,
@@ -162,7 +188,10 @@
       else:
         test_set.parallel_tests.append(typ.TestInput(name))
 
-  return ClassifyTest
+  if possible_browser:
+    return ClassifyTestWithBrowser
+  else:
+    return ClassifyTestWithoutBrowser
 
 
 def _MatchesSelectedTest(name, selected_tests, selected_tests_are_exact):
@@ -194,6 +223,8 @@
 
 
 def _TearDownProcess(child, context): # pylint: disable=W0613
+  # It's safe to call teardown_browser even if we did not start any browser
+  # in any of the tests.
   browser_test_case.teardown_browser()
   options_for_unittests.Pop()
 
diff --git a/tools/telemetry/telemetry/timeline/tracing_config.py b/tools/telemetry/telemetry/timeline/tracing_config.py
index 4ab1c510..e0d5208 100644
--- a/tools/telemetry/telemetry/timeline/tracing_config.py
+++ b/tools/telemetry/telemetry/timeline/tracing_config.py
@@ -15,6 +15,14 @@
     self._tracing_options = tracing_options
     self._tracing_category_filter = tracing_category_filter
 
+  @property
+  def tracing_options(self):
+    return self._tracing_options
+
+  @property
+  def tracing_category_filter(self):
+    return self._tracing_category_filter
+
   def GetTraceConfigJsonString(self):
     result = {}
     result.update(self._tracing_options.GetDictForChromeTracing())
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
index 5f134fe2..3c80ccd 100644
--- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
+++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
@@ -244,21 +244,12 @@
     self._results_wrapper = results_wrapper or _TBMResultWrapper()
 
   def WillRunStory(self, platform):
-    """Set up before running the story.
-
-    Do not use this for now. This is designed to be used for story test instead
-    of page test. WillRunStoryForPageTest and this function will be merged after
-    page_test's hook is deprecated.
-    """
-    pass
-
-  def WillRunStoryForPageTest(self, tracing_controller):
     """Configure and start tracing."""
-    if not tracing_controller.IsChromeTracingSupported():
+    if not platform.tracing_controller.IsChromeTracingSupported():
       raise Exception('Not supported')
 
-    tracing_controller.Start(self._tbm_options.tracing_options,
-                             self._tbm_options.category_filter)
+    platform.tracing_controller.Start(self._tbm_options.tracing_options,
+                                      self._tbm_options.category_filter)
 
   def Measure(self, platform, results):
     """Collect all possible metrics and added them to results."""
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_page_test.py b/tools/telemetry/telemetry/web_perf/timeline_based_page_test.py
index 15a91ef..d517de37 100644
--- a/tools/telemetry/telemetry/web_perf/timeline_based_page_test.py
+++ b/tools/telemetry/telemetry/web_perf/timeline_based_page_test.py
@@ -5,7 +5,14 @@
 from telemetry.page import page_test
 
 class TimelineBasedPageTest(page_test.PageTest):
-  """Page test that collects metrics with TimelineBasedMeasurement."""
+  """Page test that collects metrics with TimelineBasedMeasurement.
+
+  WillRunStory(), Measure() and DidRunStory() are all done in story_runner
+  explicitly. We still need this wrapper around PageTest because it executes
+  some browser related functions in the parent class, which is needed by
+  Timeline Based Measurement benchmarks. This class will be removed after
+  page_test's hooks are fully removed.
+  """
   def __init__(self, tbm):
     super(TimelineBasedPageTest, self).__init__()
     self._measurement = tbm
@@ -14,10 +21,6 @@
   def measurement(self):
     return self._measurement
 
-  def WillNavigateToPage(self, page, tab):
-    tracing_controller = tab.browser.platform.tracing_controller
-    self._measurement.WillRunStoryForPageTest(tracing_controller)
-
   def ValidateAndMeasurePage(self, page, tab, results):
     """Collect all possible metrics and added them to results."""
     # Measurement is done explicitly in story_runner for timeline based page
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index e2799b2..bd6d7dcd 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -78,6 +78,3 @@
 
 # https://crbug.com/530729
 SiteDetailsBrowserTest.ManyCrossSiteIframes
-
-# https://crbug.com/536891
-PhishingDOMFeatureExtractorTest.*
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index d3a1971..757d6b9 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -63,3 +63,6 @@
 
 # https://crbug.com/376668
 TouchActionBrowserTest.DefaultAuto
+
+# https://crbug.com/536881
+IndexedDBBrowserTest.DiskFullOnCommit
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
index 08a678d..482109a 100644
--- a/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
+++ b/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
@@ -32,3 +32,9 @@
 # Test fail: https://crbug.com/349778
 # Valgrind bot purple: https://crbug.com/522692
 TranslateManagerRenderViewHostTest.FetchLanguagesFromTranslateServer*
+
+# Test fail: https://crbug.com/537064
+ExtensionMessageBubbleTest.*
+DesktopMediaListAshTest.*
+ExtensionTestMessageListenerUnittest.*
+SigninErrorNotifierTest.*
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 6a45e41..95cf901 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3474,3 +3474,25 @@
    fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN3net20URLRequestJobFactory15ProtocolHandlerEESt10_Select1stIS6_ESt4lessISsESaIS6_EE14_M_create_nodeIJS6_EEEPSt13_Rb_tree_nodeIS6_EDpOT_
    fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN3net20URLRequestJobFactory15ProtocolHandlerEESt10_Select1stIS6_ESt4lessISsESaIS6_EE10_M_insert_IS6_EESt17_Rb_tree_iteratorIS6_EPKSt18_Rb_tree_node_baseSI_OT_
 }
+{
+   bug=536907
+   Memcheck:Leak
+   fun:_Znw*
+   ...
+   fun:_ZN7content21RenderProcessHostImpl4InitEv
+   fun:_ZN7content22RenderFrameHostManager14InitRenderViewEPNS_18RenderViewHostImplEi
+   fun:_ZN7content22RenderFrameHostManager8NavigateERK4GURLRKNS_20FrameNavigationEntryERKNS_19NavigationEntryImplE
+   fun:_ZN7content13NavigatorImpl15NavigateToEntryEPNS_13FrameTreeNodeERKNS_20FrameNavigationEntryERKNS_19NavigationEntryImplENS_20NavigationController10ReloadTypeEb
+   fun:_ZN7content13NavigatorImpl22NavigateToPendingEntryEPNS_13FrameTreeNodeERKNS_20FrameNavigationEntryENS_20NavigationController10ReloadTypeEb
+   fun:_ZN7content24NavigationControllerImpl30NavigateToPendingEntryInternalENS_20NavigationController10ReloadTypeE
+   fun:_ZN7content24NavigationControllerImpl22NavigateToPendingEntryENS_20NavigationController10ReloadTypeE
+   fun:_ZN7content24NavigationControllerImpl9LoadEntryE10scoped_ptrINS_19NavigationEntryImplEN4base14DefaultDeleterIS2_EEE
+   fun:_ZN7content24NavigationControllerImpl17LoadURLWithParamsERKNS_20NavigationController13LoadURLParamsE
+   fun:_ZN7content5Shell15LoadURLForFrameERK4GURLRKSs
+}
+{
+   bug=537626
+   Memcheck:Leak
+   fun:_Znw*
+   fun:_ZN14message_center*MessageCenterViewTest*
+}
diff --git a/ui/android/java/src/org/chromium/ui/picker/DateTimePickerDialog.java b/ui/android/java/src/org/chromium/ui/picker/DateTimePickerDialog.java
index 90c9f9d..c621a24 100644
--- a/ui/android/java/src/org/chromium/ui/picker/DateTimePickerDialog.java
+++ b/ui/android/java/src/org/chromium/ui/picker/DateTimePickerDialog.java
@@ -22,6 +22,8 @@
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
+// TODO(tkent): fix deprecation warnings crbug.com/537037
+@SuppressWarnings("deprecation")
 public class DateTimePickerDialog extends AlertDialog implements OnClickListener,
         OnDateChangedListener, OnTimeChangedListener {
     private final DatePicker mDatePicker;
diff --git a/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceInflater.java b/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceInflater.java
new file mode 100644
index 0000000..38888dd
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/resources/dynamics/ViewResourceInflater.java
@@ -0,0 +1,376 @@
+// Copyright 2015 The Chromium 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.ui.resources.dynamics;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+/**
+ * ViewResourceInflater is a utility class that facilitates using an Android View as a dynamic
+ * resource, which can be later used as a compositor layer. This class assumes that the View
+ * is defined declaratively, using a XML Layout file, and that the View that is going to be
+ * inflated is the single top-level View of the layout (its root).
+ *
+ * By default, the View is inflated without being attached to the hierarchy, which allows
+ * subclasses to read/modify the View "offscreen", via the method {@link #onFinishInflate()}.
+ * Only when a new snapshot of the View is required, which happens when the method
+ * {@link #invalidate()} is called, and the View is automatically detached from the
+ * hierarchy after the snapshot is captured.
+ *
+ * There's also an option to not attach to the hierarchy at all, by overriding the method
+ * {@link #shouldAttachView()} and making it return false (the default is yes). In this case
+ * the changes to the View will always be "offscreen". By default, an unspecified value of
+ * {@link View.MeasureSpec} will de used to determine the width and height of the View.
+ * It's possible to specify custom size constraints by overriding the methods
+ * {@link #getWidthMeasureSpec()} and {@link #getHeightMeasureSpec()}.
+ */
+public class ViewResourceInflater {
+
+    /**
+     * The id of the XML Layout that describes the View.
+     */
+    private int mLayoutId;
+
+    /**
+     * The id of the View being inflated, which must be the root of the given Layout.
+     */
+    private int mViewId;
+
+    /**
+     * The Context used to inflate the View.
+     */
+    private Context mContext;
+
+    /**
+     * The ViewGroup container used to inflate the View.
+     */
+    private ViewGroup mContainer;
+
+    /**
+     * The DynamicResourceLoader used to manage resources generated dynamically.
+     */
+    private DynamicResourceLoader mResourceLoader;
+
+    /**
+     * The ViewResourceAdapter used to capture snapshots of the View.
+     */
+    private ViewResourceAdapter mResourceAdapter;
+
+    /**
+     * The inflated View.
+     */
+    private View mView;
+
+    /**
+     * Whether the View is invalided.
+     */
+    private boolean mIsInvalidated;
+
+    /**
+     * Whether the View is attached to the hierarchy.
+     */
+    private boolean mIsAttached;
+
+    /**
+     * The ViewInflaterOnDrawListener used to track changes in the View when attached.
+     */
+    private ViewInflaterOnDrawListener mOnDrawListener;
+
+    /**
+     * The invalid ID.
+     */
+    private static final int INVALID_ID = -1;
+
+    /**
+     * @param layoutId          The XML Layout that declares the View.
+     * @param viewId            The id of the root View of the Layout.
+     * @param context           The Android Context used to inflate the View.
+     * @param container         The container View used to inflate the View.
+     * @param resourceLoader    The resource loader that will handle the snapshot capturing.
+     */
+    public ViewResourceInflater(int layoutId,
+                                int viewId,
+                                Context context,
+                                ViewGroup container,
+                                DynamicResourceLoader resourceLoader) {
+        mLayoutId = layoutId;
+        mViewId = viewId;
+        mContext = context;
+        mContainer = container;
+        mResourceLoader = resourceLoader;
+    }
+
+    /**
+     * Inflate the layout.
+     */
+    public void inflate() {
+        if (mView != null) return;
+
+        // Inflate the View without attaching to hierarchy (attachToRoot param is false).
+        mView = LayoutInflater.from(mContext).inflate(mLayoutId, mContainer, false);
+
+        // Make sure the View we just inflated is the right one.
+        assert mView.getId() == mViewId;
+
+        // Allow subclasses to access/modify the View before it's attached
+        // to the hierarchy (if allowed) or snapshots are captured.
+        onFinishInflate();
+
+        registerResource();
+    }
+
+    /**
+     * Invalidate the inflated View, causing a snapshot of the View to be captured.
+     */
+    public void invalidate() {
+        // View must be inflated at this point. If it's not, do it now.
+        if (mView == null) {
+            inflate();
+        }
+
+        mIsInvalidated = true;
+
+        // If the View is already attached, we don't need to do anything because the
+        // snapshot will be captured automatically when the View is drawn.
+        if (!mIsAttached) {
+            if (shouldAttachView()) {
+                // TODO(pedrosimonetti): investigate if complex views can be rendered offline.
+                // NOTE(pedrosimonetti): it seems that complex views don't get rendered
+                // properly if not attached to the hierarchy. The problem seem to be related
+                // to the use of the property "layout_gravity: end", possibly in combination
+                // of other things like elastic views (layout_weight: 1) and/or fading edges.
+                attachView();
+            } else {
+                // When the View is not attached, we need to manually layout the View
+                // and invalidate the resource in order to capture a new snapshot.
+                layout();
+                invalidateResource();
+            }
+        }
+    }
+
+    /**
+     * Destroy the instance.
+     */
+    public void destroy() {
+        if (mView == null) return;
+
+        unregisterResource();
+
+        detachView();
+        mView = null;
+
+        mLayoutId = INVALID_ID;
+        mViewId = INVALID_ID;
+
+        mContext = null;
+        mContainer = null;
+        mResourceLoader = null;
+    }
+
+    /**
+     * @return The measured width of the inflated View.
+     */
+    public int getMeasuredWidth() {
+        // View must be inflated at this point.
+        assert mView != null;
+
+        return mView.getMeasuredWidth();
+    }
+
+    /**
+     * @return The measured height of the inflated View.
+     */
+    public int getMeasuredHeight() {
+        // View must be inflated at this point.
+        assert mView != null;
+
+        return mView.getMeasuredHeight();
+    }
+
+    /**
+     * @return The id of View, which is used as an identifier for the resource loader.
+     */
+    public int getViewId() {
+        return mViewId;
+    }
+
+    /**
+     * The callback called after inflating the View, allowing subclasses to access/modify
+     * the View before it's attached to the hierarchy (if allowed) or snapshots are captured.
+     */
+    protected void onFinishInflate() {}
+
+    /**
+     * NOTE(pedrosimonetti): Complex views don't fully work when not attached to the hierarchy.
+     * @return Whether the View should be attached to the hierarchy after being inflated.
+     *         Subclasses should override this method to change the default behavior.
+     */
+    protected boolean shouldAttachView() {
+        return true;
+    }
+
+    /**
+     * @return Whether the View should be detached from the hierarchy after being captured.
+     *         Subclasses should override this method to change the default behavior.
+     */
+    protected boolean shouldDetachViewAfterCapturing() {
+        return true;
+    }
+
+    /**
+     * @return The MeasureSpec used for calculating the width of the offscreen View.
+     *         Subclasses should override this method to specify measurements.
+     *         By default, this method returns an unspecified MeasureSpec.
+     */
+    protected int getWidthMeasureSpec() {
+        return getUnspecifiedMeasureSpec();
+    }
+
+    /**
+     * @return The MeasureSpec used for calculating the height of the offscreen View.
+     *         Subclasses should override this method to specify measurements.
+     *         By default, this method returns an unspecified MeasureSpec.
+     */
+    protected int getHeightMeasureSpec() {
+        return getUnspecifiedMeasureSpec();
+    }
+
+    /**
+     * @return The View resource.
+     */
+    protected View getView() {
+        return mView;
+    }
+
+    /**
+     * Attach the View to the hierarchy.
+     */
+    private void attachView() {
+        if (!mIsAttached) {
+            assert mView.getParent() == null;
+            mContainer.addView(mView);
+            mIsAttached = true;
+
+            if (mOnDrawListener == null) {
+                // Add a draw listener. For now on, changes in the View will cause a
+                // new snapshot to be captured, if the ViewResourceInflater was invalidated.
+                mOnDrawListener = new ViewInflaterOnDrawListener();
+                mView.getViewTreeObserver().addOnDrawListener(mOnDrawListener);
+            }
+        }
+    }
+
+    /**
+     * Detach the View from the hierarchy.
+     */
+    private void detachView() {
+        if (mIsAttached) {
+            if (mOnDrawListener != null) {
+                mView.getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
+                mOnDrawListener = null;
+            }
+
+            assert mView.getParent() != null;
+            mContainer.removeView(mView);
+            mIsAttached = false;
+        }
+    }
+
+    /**
+     * Layout the View. This is to be used when the View is not attached to the hierarchy.
+     */
+    private void layout() {
+        // View must be inflated at this point.
+        assert mView != null;
+
+        mView.measure(getWidthMeasureSpec(), getHeightMeasureSpec());
+        mView.layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
+    }
+
+    /**
+     * @return An unspecified MeasureSpec value.
+     */
+    private int getUnspecifiedMeasureSpec() {
+        return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+    }
+
+    /**
+     * Register the resource and creates an adapter for it.
+     */
+    private void registerResource() {
+        if (mResourceAdapter == null) {
+            mResourceAdapter = new ViewInflaterAdapter(mView.findViewById(mViewId));
+        }
+
+        if (mResourceLoader != null) {
+            mResourceLoader.registerResource(mViewId, mResourceAdapter);
+        }
+    }
+
+    /**
+     * Unregister the resource and destroys the adapter.
+     */
+    private void unregisterResource() {
+        if (mResourceLoader != null) {
+            mResourceLoader.unregisterResource(mViewId);
+        }
+
+        mResourceAdapter = null;
+    }
+
+    /**
+     * Invalidate the resource, which will cause a new snapshot to be captured.
+     */
+    private void invalidateResource() {
+        if (mIsInvalidated && mView != null && mResourceAdapter != null) {
+            mIsInvalidated = false;
+            mResourceAdapter.invalidate(null);
+        }
+    }
+
+    /**
+     * A custom {@link ViewResourceAdapter} that calls the method {@link #onCaptureEnd()}.
+     */
+    private class ViewInflaterAdapter extends ViewResourceAdapter {
+        public ViewInflaterAdapter(View view) {
+            super(view);
+        }
+
+        @Override
+        protected void onCaptureEnd() {
+            ViewResourceInflater.this.onCaptureEnd();
+        }
+    }
+
+    /**
+     * Called when a snapshot is captured.
+     */
+    private void onCaptureEnd() {
+        if (shouldDetachViewAfterCapturing()) {
+            detachView();
+        }
+    }
+
+    /**
+     * A custom {@link ViewTreeObserver.OnDrawListener} that calls the method {@link #onDraw()}.
+     */
+    private class ViewInflaterOnDrawListener implements ViewTreeObserver.OnDrawListener {
+        @Override
+        public void onDraw() {
+            ViewResourceInflater.this.onDraw();
+        }
+    }
+
+    /**
+     * Called when the View is drawn,
+     */
+    private void onDraw() {
+        invalidateResource();
+    }
+}
diff --git a/ui/android/javatests/src/org/chromium/ui/picker/DateTimePickerDialogTest.java b/ui/android/javatests/src/org/chromium/ui/picker/DateTimePickerDialogTest.java
index 6e2a43e0..251ab4d 100644
--- a/ui/android/javatests/src/org/chromium/ui/picker/DateTimePickerDialogTest.java
+++ b/ui/android/javatests/src/org/chromium/ui/picker/DateTimePickerDialogTest.java
@@ -12,6 +12,8 @@
  * Tests for DateTimePickerDialog.
  */
 public class DateTimePickerDialogTest extends InstrumentationTestCase {
+    //TODO(tkent): fix deprecation warnings crbug.com/537037
+    @SuppressWarnings("deprecation")
     @SmallTest
     public void testOnTimeChanged() {
         int september = 8;
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 6cde8c2..c67c0a8a 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -10,7 +10,6 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -714,10 +713,6 @@
 }
 
 void Window::SetVisible(bool visible) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 Window::SetVisible"));
-
   if (visible == layer()->GetTargetVisibility())
     return;  // No change.
 
diff --git a/ui/base/OWNERS b/ui/base/OWNERS
new file mode 100644
index 0000000..b444384
--- /dev/null
+++ b/ui/base/OWNERS
@@ -0,0 +1,7 @@
+per-file *.isolate=maruel@chromium.org
+per-file *.isolate=tandrii@chromium.org
+per-file *.isolate=vadimsh@chromium.org
+
+# If you're doing structural changes get a review from one of the ui/OWNERS.
+per-file *.gyp*=*
+per-file BUILD.gn=*
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc
index 7db88b6..df75bb2 100644
--- a/ui/base/ime/input_method_win.cc
+++ b/ui/base/ime/input_method_win.cc
@@ -6,7 +6,6 @@
 
 #include "base/auto_reset.h"
 #include "base/basictypes.h"
-#include "base/profiler/scoped_tracker.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/ime/win/tsf_input_scope.h"
 #include "ui/events/event.h"
@@ -218,10 +217,6 @@
                                WPARAM wparam,
                                LPARAM lparam,
                                BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnChar"));
-
   *handled = TRUE;
 
   if (suppress_next_char_) {
@@ -260,11 +255,6 @@
                                         WPARAM wparam,
                                         LPARAM lparam,
                                         BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 InputMethodWin::OnImeSetContext"));
-
   if (!!wparam) {
     imm32_manager_.CreateImeWindow(window_handle);
     if (system_toplevel_window_focused()) {
@@ -288,11 +278,6 @@
                                               WPARAM wparam,
                                               LPARAM lparam,
                                               BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 InputMethodWin::OnImeStartComposition"));
-
   // We have to prevent WTL from calling ::DefWindowProc() because the function
   // calls ::ImmSetCompositionWindow() and ::ImmSetCandidateWindow() to
   // over-write the position of IME windows.
@@ -310,11 +295,6 @@
                                          WPARAM wparam,
                                          LPARAM lparam,
                                          BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 InputMethodWin::OnImeComposition"));
-
   // We have to prevent WTL from calling ::DefWindowProc() because we do not
   // want for the IMM (Input Method Manager) to send WM_IME_CHAR messages.
   *handled = TRUE;
@@ -348,11 +328,6 @@
                                             WPARAM wparam,
                                             LPARAM lparam,
                                             BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 InputMethodWin::OnImeEndComposition"));
-
   // Let WTL call ::DefWindowProc() and release its resources.
   *handled = FALSE;
 
@@ -370,10 +345,6 @@
                                     WPARAM wparam,
                                     LPARAM lparam,
                                     BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnImeNotify"));
-
   *handled = FALSE;
 
   // Update |is_candidate_popup_open_|, whether a candidate window is open.
@@ -393,10 +364,6 @@
                                      WPARAM wparam,
                                      LPARAM lparam,
                                      BOOL* handled) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 InputMethodWin::OnImeRequest"));
-
   *handled = FALSE;
 
   // Should not receive WM_IME_REQUEST message, if IME is disabled.
diff --git a/ui/base/win/foreground_helper.cc b/ui/base/win/foreground_helper.cc
index 605deb043..7283012 100644
--- a/ui/base/win/foreground_helper.cc
+++ b/ui/base/win/foreground_helper.cc
@@ -5,7 +5,6 @@
 #include "ui/base/win/foreground_helper.h"
 
 #include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
 #include "ui/gfx/win/window_impl.h"
 
 namespace ui {
@@ -75,10 +74,6 @@
 
 // Handle the registered Hotkey being pressed.
 void ForegroundHelper::OnHotKey(int id, UINT vcode, UINT modifiers) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 ForegroundHelper::OnHotKey"));
-
   SetForegroundWindow(window_);
 }
 
diff --git a/ui/chromeos/network/network_icon.cc b/ui/chromeos/network/network_icon.cc
index 97c6261..6f61a00 100644
--- a/ui/chromeos/network/network_icon.cc
+++ b/ui/chromeos/network/network_icon.cc
@@ -600,9 +600,10 @@
 
 bool NetworkIconImpl::UpdatePortalState(const NetworkState* network) {
   bool behind_captive_portal = false;
-  if (network && NetworkPortalDetector::IsInitialized()) {
+  if (network && chromeos::network_portal_detector::IsInitialized()) {
     NetworkPortalDetector::CaptivePortalState state =
-        NetworkPortalDetector::Get()->GetCaptivePortalState(network->guid());
+        chromeos::network_portal_detector::GetInstance()->GetCaptivePortalState(
+            network->guid());
     behind_captive_portal =
         state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL;
   }
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 0e17b54..4fdd821 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -24,14 +24,11 @@
 namespace {
 
 // Delay between adjustment sounds.
-const base::TimeDelta kSoundDelay = base::TimeDelta::FromMilliseconds(150);
-
-// Delay before corner passthrough activates.
-const base::TimeDelta kCornerPassthroughDelay =
-    base::TimeDelta::FromMilliseconds(700);
+const int kSoundDelayInMS = 150;
 
 // In ChromeOS, VKEY_LWIN is synonymous for the search key.
 const ui::KeyboardCode kChromeOSSearchKey = ui::VKEY_LWIN;
+
 }  // namespace
 
 TouchExplorationController::TouchExplorationController(
@@ -44,7 +41,7 @@
       prev_state_(NO_FINGERS_DOWN),
       VLOG_on_(true),
       tick_clock_(NULL) {
-  CHECK(root_window);
+  DCHECK(root_window);
   root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
   InitializeSwipeGestureMaps();
 }
@@ -529,11 +526,11 @@
     // If the fingers have moved too far from their original locations,
     // the user can no longer split tap.
     ui::TouchEvent* original_touch;
-    if (event.touch_id() == last_touch_exploration_->touch_id())
+    if (event.touch_id() == last_touch_exploration_->touch_id()) {
       original_touch = last_touch_exploration_.get();
-    else if (event.touch_id() == initial_press_->touch_id())
+    } else if (event.touch_id() == initial_press_->touch_id()) {
       original_touch = initial_press_.get();
-    else {
+    } else {
       NOTREACHED();
       SET_STATE(WAIT_FOR_NO_FINGERS);
       return ui::EVENT_REWRITE_DISCARD;
@@ -559,7 +556,7 @@
     // If the touch exploration finger is lifted, there is no option to return
     // to touch explore anymore. The remaining finger acts as a pending
     // tap or long tap for the last touch explore location.
-    if (event.touch_id() == last_touch_exploration_->touch_id()){
+    if (event.touch_id() == last_touch_exploration_->touch_id()) {
       SET_STATE(TOUCH_RELEASE_PENDING);
       return EVENT_REWRITE_DISCARD;
     }
@@ -614,7 +611,7 @@
   }
 
   // There should not be more than one finger down.
-  DCHECK(current_touch_ids_.size() <= 1);
+  DCHECK_LE(current_touch_ids_.size(), 1U);
 
   // Allows user to return to the edge to adjust the sound if they have left the
   // boundaries.
@@ -630,8 +627,7 @@
   // continue adjusting the sound.
   if (!sound_timer_.IsRunning()) {
     sound_timer_.Start(FROM_HERE,
-                       kSoundDelay,
-                       this,
+                       base::TimeDelta::FromMilliseconds(kSoundDelayInMS), this,
                        &ui::TouchExplorationController::PlaySoundForTimer);
     delegate_->PlayVolumeAdjustEarcon();
   }
@@ -849,7 +845,7 @@
             << "\n Location = " << location.ToString()
             << "\n Bounds = " << root_window_->bounds().right();
   }
-  delegate_->SetOutputLevel(int(volume));
+  delegate_->SetOutputLevel(static_cast<int>(volume));
 }
 
 void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
@@ -859,7 +855,7 @@
   // there will also be a menu for users to pick custom mappings.
   GestureEventDetails event_details = swipe_gesture->details();
   int num_fingers = event_details.touch_points();
-  if(VLOG_on_)
+  if (VLOG_on_)
     VLOG(0) << "\nSwipe with " << num_fingers << " fingers.";
 
   if (num_fingers > 4)
@@ -947,7 +943,7 @@
   ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags);
   DispatchEvent(&key_down);
   DispatchEvent(&key_up);
-  if(VLOG_on_) {
+  if (VLOG_on_) {
     VLOG(0) << "\nKey down: key code : " << key_down.key_code()
             << ", flags: " << key_down.flags()
             << "\nKey up: key code : " << key_up.key_code()
@@ -1050,17 +1046,15 @@
   if (!VLOG_on_)
     return;
 
-  if (prev_event_ != NULL &&
-      prev_event_->type() == touch_event.type() &&
-      prev_event_->touch_id() == touch_event.touch_id()){
+  if (prev_event_ && prev_event_->type() == touch_event.type() &&
+      prev_event_->touch_id() == touch_event.touch_id()) {
     return;
   }
   // The above statement prevents events of the same type and id from being
   // printed in a row. However, if two fingers are down, they would both be
   // moving and alternating printing move events unless we check for this.
-  if (prev_event_ != NULL &&
-      prev_event_->type() == ET_TOUCH_MOVED &&
-      touch_event.type() == ET_TOUCH_MOVED){
+  if (prev_event_ && prev_event_->type() == ET_TOUCH_MOVED &&
+      touch_event.type() == ET_TOUCH_MOVED) {
     return;
   }
 
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index d96fb7f..b331017 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -213,6 +213,8 @@
     modifiers |= blink::WebInputEvent::CapsLockOn;
   if (flags & EF_IS_REPEAT)
     modifiers |= blink::WebInputEvent::IsAutoRepeat;
+  if (flags & ui::EF_TOUCH_ACCESSIBILITY)
+    modifiers |= blink::WebInputEvent::IsTouchAccessibility;
 
   return modifiers;
 }
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index d55f19e..94122ca6 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -343,7 +343,7 @@
   width: 16px;
 }
 
-.dialog-header paper-button::shadow > paper-material {
+.dialog-header paper-button {
   padding: 0 8px;
   line-height: 32px;
 }
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index d85c6f7d..727aca2 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -419,8 +419,9 @@
           '', str('UNMOUNT_FAILED'), null, null, null);
     };
 
-    var volumeInfo = CommandUtil.getElementVolumeInfo(
-        event.target, fileManager);
+    var volumeInfo =
+        CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
+        CommandUtil.getCurrentVolumeInfo(fileManager);
     if (!volumeInfo) {
       errorCallback();
       return;
@@ -436,8 +437,9 @@
    * @this {CommandHandler}
    */
   canExecute: function(event, fileManager) {
-    var volumeInfo = CommandUtil.getElementVolumeInfo(
-        event.target, fileManager);
+    var volumeInfo =
+        CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
+        CommandUtil.getCurrentVolumeInfo(fileManager);
     if (!volumeInfo) {
       event.canExecute = false;
       event.command.setHidden(true);
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index b0caf15..b241ae3 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -424,15 +424,18 @@
     "vector_icons/account_child_invert.icon",
     "vector_icons/apps.icon",
     "vector_icons/autofill.icon",
+    "vector_icons/autologin.icon",
     "vector_icons/bar_close.1x.icon",
     "vector_icons/bar_close.icon",
     "vector_icons/blocked_badge.icon",
     "vector_icons/check_circle.icon",
+    "vector_icons/chrome_product.icon",
     "vector_icons/code.icon",
     "vector_icons/cookie.icon",
     "vector_icons/crashed_tab.icon",
     "vector_icons/error_circle.icon",
     "vector_icons/extension.icon",
+    "vector_icons/extension_crashed.icon",
     "vector_icons/file_download.icon",
     "vector_icons/file_download_incognito.1x.icon",
     "vector_icons/file_download_incognito.icon",
@@ -638,7 +641,9 @@
     "//ui/resources:ui_test_pak",
   ]
 
-  data_deps = [ "//ui/resources:ui_test_pak" ]
+  data_deps = [
+    "//ui/resources:ui_test_pak",
+  ]
 
   if (!is_mac && !is_ios) {
     sources += [
diff --git a/ui/gfx/icon_util.cc b/ui/gfx/icon_util.cc
index 94a77bb..f9758d3 100644
--- a/ui/gfx/icon_util.cc
+++ b/ui/gfx/icon_util.cc
@@ -8,6 +8,7 @@
 #include "base/files/important_file_writer.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/trace_event/trace_event.h"
 #include "base/win/resource_util.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/scoped_handle.h"
@@ -452,7 +453,8 @@
 // static
 bool IconUtil::CreateIconFileFromImageFamily(
     const gfx::ImageFamily& image_family,
-    const base::FilePath& icon_path) {
+    const base::FilePath& icon_path,
+    WriteType write_type) {
   // Creating a set of bitmaps corresponding to the icon images we'll end up
   // storing in the icon file. Each bitmap is created by resizing the most
   // appropriate image from |image_family| to the desired size.
@@ -516,8 +518,19 @@
 
   DCHECK_EQ(offset, buffer_size);
 
-  std::string data(buffer.begin(), buffer.end());
-  return base::ImportantFileWriter::WriteFileAtomically(icon_path, data);
+  if (write_type == NORMAL_WRITE) {
+    auto saved_size =
+        base::WriteFile(icon_path, reinterpret_cast<const char*>(&buffer[0]),
+                        static_cast<int>(buffer.size()));
+    if (saved_size == static_cast<int>(buffer.size()))
+      return true;
+    bool delete_success = base::DeleteFile(icon_path, false);
+    DCHECK(delete_success);
+    return false;
+  } else {
+    std::string data(buffer.begin(), buffer.end());
+    return base::ImportantFileWriter::WriteFileAtomically(icon_path, data);
+  }
 }
 
 bool IconUtil::PixelsHaveAlpha(const uint32* pixels, size_t num_pixels) {
diff --git a/ui/gfx/icon_util.h b/ui/gfx/icon_util.h
index a3dc30d..1a48304 100644
--- a/ui/gfx/icon_util.h
+++ b/ui/gfx/icon_util.h
@@ -58,6 +58,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 class GFX_EXPORT IconUtil {
  public:
+  // ATOMIC_WRITE ensures that a partially written icon won't be created even if
+  // Chrome crashes part way through, but ATOMIC_WRITE is more expensive than
+  // NORMAL_WRITE. See CreateIconFileFromImageFamily. ATOMIC_WRITE is the
+  // default for historical reasons.
+  enum WriteType { ATOMIC_WRITE, NORMAL_WRITE };
   // The size of the large icon entries in .ico files on Windows Vista+.
   static const int kLargeIconSize = 256;
   // The size of icons in the medium icons view on Windows Vista+. This is the
@@ -126,7 +131,8 @@
   // |image_family| is empty.
   static bool CreateIconFileFromImageFamily(
       const gfx::ImageFamily& image_family,
-      const base::FilePath& icon_path);
+      const base::FilePath& icon_path,
+      WriteType write_type = ATOMIC_WRITE);
 
   // Creates a cursor of the specified size from the DIB passed in.
   // Returns the cursor on success or NULL on failure.
@@ -139,7 +145,7 @@
   // The icon format is published in the MSDN but there is no definition of
   // the icon file structures in any of the Windows header files so we need to
   // define these structure within the class. We must make sure we use 2 byte
-  // packing so that the structures are layed out properly within the file.
+  // packing so that the structures are laid out properly within the file.
   // See: http://msdn.microsoft.com/en-us/library/ms997538.aspx
 #pragma pack(push)
 #pragma pack(2)
diff --git a/ui/gfx/image/image_mac_unittest.mm b/ui/gfx/image/image_mac_unittest.mm
index 5f706c7..c3439ee 100644
--- a/ui/gfx/image/image_mac_unittest.mm
+++ b/ui/gfx/image/image_mac_unittest.mm
@@ -197,10 +197,12 @@
 
   // Convert to ImageSkia to check pixel contents of NSImageReps.
   gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
-  EXPECT_TRUE(gt::IsEqual(bytes1x,
-      image_skia.GetRepresentation(1.0f).sk_bitmap()));
-  EXPECT_TRUE(gt::IsEqual(bytes2x,
-      image_skia.GetRepresentation(2.0f).sk_bitmap()));
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+      bytes1x, image_skia.GetRepresentation(1.0f).sk_bitmap(),
+      gt::MaxColorSpaceConversionColorShift()));
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
+      image_skia.GetRepresentation(2.0f).sk_bitmap(),
+      gt::MaxColorSpaceConversionColorShift()));
 }
 
 } // namespace
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc
index 45f80a6..7c8d95f 100644
--- a/ui/gfx/image/image_unittest.cc
+++ b/ui/gfx/image/image_unittest.cc
@@ -222,7 +222,9 @@
       kSize2x, kSize2x), 2.0f));
   gfx::Image image(image_skia);
 
-  EXPECT_TRUE(gt::IsEqual(image.As1xPNGBytes(), bitmap_1x));
+  EXPECT_TRUE(
+      gt::ArePNGBytesCloseToBitmap(image.As1xPNGBytes(), bitmap_1x,
+                                   gt::MaxColorSpaceConversionColorShift()));
   EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
 }
 
@@ -242,10 +244,12 @@
   scales.push_back(1.0f);
   scales.push_back(2.0f);
   gfx::ImageSkia image_skia = image.AsImageSkia();
-  EXPECT_TRUE(gt::IsEqual(bytes1x,
-      image_skia.GetRepresentation(1.0f).sk_bitmap()));
-  EXPECT_TRUE(gt::IsEqual(bytes2x,
-      image_skia.GetRepresentation(2.0f).sk_bitmap()));
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes1x,
+      image_skia.GetRepresentation(1.0f).sk_bitmap(),
+      gt::MaxColorSpaceConversionColorShift()));
+  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
+      image_skia.GetRepresentation(2.0f).sk_bitmap(),
+      gt::MaxColorSpaceConversionColorShift()));
   EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
                                             scales));
 #if !defined(OS_IOS)
@@ -279,13 +283,18 @@
   std::vector<float> scales = gfx::ImageSkia::GetSupportedScales();
   EXPECT_EQ(scales.size(), 1U);
   if (scales[0] == 1.0f)
-    EXPECT_TRUE(gt::IsEqual(bytes1x, from_platform.AsBitmap()));
+    EXPECT_TRUE(
+        gt::ArePNGBytesCloseToBitmap(bytes1x, from_platform.AsBitmap(),
+                                     gt::MaxColorSpaceConversionColorShift()));
   else if (scales[0] == 2.0f)
-    EXPECT_TRUE(gt::IsEqual(bytes2x, from_platform.AsBitmap()));
+    EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x, from_platform.AsBitmap(),
+                gt::MaxColorSpaceConversionColorShift()));
   else
     ADD_FAILURE() << "Unexpected platform scale factor.";
 #else
-  EXPECT_TRUE(gt::IsEqual(bytes1x, from_platform.AsBitmap()));
+  EXPECT_TRUE(
+      gt::ArePNGBytesCloseToBitmap(bytes1x, from_platform.AsBitmap(),
+                                   gt::MaxColorSpaceConversionColorShift()));
 #endif  // defined(OS_IOS)
 }
 
@@ -321,7 +330,9 @@
   gfx::Image from_platform(gt::CopyPlatformType(from_png));
 
   EXPECT_TRUE(gt::IsPlatformImageValid(gt::ToPlatformType(from_platform)));
-  EXPECT_TRUE(gt::IsEqual(png_bytes, from_platform.AsBitmap()));
+  EXPECT_TRUE(
+      gt::ArePNGBytesCloseToBitmap(png_bytes, from_platform.AsBitmap(),
+                                   gt::MaxColorSpaceConversionColorShift()));
 }
 
 TEST_F(ImageTest, PNGEncodeFromPlatformDecodeToSkia) {
@@ -333,7 +344,9 @@
   image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f));
   gfx::Image from_png(image_png_reps);
 
-  EXPECT_TRUE(gt::IsEqual(from_platform.AsBitmap(), from_png.AsBitmap()));
+  EXPECT_TRUE(gt::AreBitmapsClose(
+      from_platform.AsBitmap(), from_png.AsBitmap(),
+      gt::MaxColorSpaceConversionColorShift()));
 }
 
 TEST_F(ImageTest, PNGDecodeToSkiaFailure) {
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc
index daca53f5..551409e 100644
--- a/ui/gfx/image/image_unittest_util.cc
+++ b/ui/gfx/image/image_unittest_util.cc
@@ -30,18 +30,30 @@
 
 namespace {
 
-bool ColorComponentsClose(SkColor component1, SkColor component2) {
+// The maximum color shift in the red, green, and blue components caused by
+// converting a gfx::Image between colorspaces. Color shifts occur when
+// converting between NSImage & UIImage to ImageSkia. Determined by trial and
+// error.
+const int kMaxColorSpaceConversionColorShift = 40;
+
+bool ColorComponentsClose(SkColor component1,
+                          SkColor component2,
+                          int max_deviation) {
   int c1 = static_cast<int>(component1);
   int c2 = static_cast<int>(component2);
-  return std::abs(c1 - c2) <= 40;
+  return std::abs(c1 - c2) <= max_deviation;
 }
 
-bool ColorsClose(SkColor color1, SkColor color2) {
+bool ColorsClose(SkColor color1, SkColor color2, int max_deviation) {
   // Be tolerant of floating point rounding and lossy color space conversions.
-  return ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2)) &&
-         ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2)) &&
-         ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2)) &&
-         ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2));
+  return ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2),
+                              max_deviation) &&
+         ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2),
+                              max_deviation) &&
+         ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2),
+                              max_deviation) &&
+         ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2),
+                              max_deviation);
 }
 
 }  // namespace
@@ -79,7 +91,13 @@
   return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
 }
 
-bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
+bool AreImagesEqual(const gfx::Image& img1, const gfx::Image& img2) {
+  return AreImagesClose(img1, img2, 0);
+}
+
+bool AreImagesClose(const gfx::Image& img1,
+                    const gfx::Image& img2,
+                    int max_deviation) {
   img1.AsImageSkia().EnsureRepsForSupportedScales();
   img2.AsImageSkia().EnsureRepsForSupportedScales();
   std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
@@ -91,14 +109,21 @@
     float scale = img1_reps[i].scale();
     const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
     if (image_rep2.scale() != scale ||
-        !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
+        !AreBitmapsClose(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap(),
+                         max_deviation)) {
       return false;
     }
   }
   return true;
 }
 
-bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
+bool AreBitmapsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
+  return AreBitmapsClose(bmp1, bmp2, 0);
+}
+
+bool AreBitmapsClose(const SkBitmap& bmp1,
+                     const SkBitmap& bmp2,
+                     int max_deviation) {
   if (bmp1.isNull() && bmp2.isNull())
     return true;
 
@@ -116,7 +141,7 @@
 
   for (int y = 0; y < bmp1.height(); ++y) {
     for (int x = 0; x < bmp1.width(); ++x) {
-      if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y)))
+      if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y), max_deviation))
         return false;
     }
   }
@@ -124,15 +149,21 @@
   return true;
 }
 
-bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
-             const SkBitmap& bitmap) {
+bool ArePNGBytesCloseToBitmap(
+    const scoped_refptr<base::RefCountedMemory>& bytes,
+    const SkBitmap& bitmap,
+    int max_deviation) {
   SkBitmap decoded;
   if (!bytes.get() ||
       !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) {
     return bitmap.isNull();
   }
 
-  return IsEqual(bitmap, decoded);
+  return AreBitmapsClose(bitmap, decoded, max_deviation);
+}
+
+int MaxColorSpaceConversionColorShift() {
+  return kMaxColorSpaceConversionColorShift;
 }
 
 void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) {
@@ -238,7 +269,7 @@
 #endif
 
 void CheckColors(SkColor color1, SkColor color2) {
-  EXPECT_TRUE(ColorsClose(color1, color2));
+  EXPECT_TRUE(ColorsClose(color1, color2, MaxColorSpaceConversionColorShift()));
 }
 
 void CheckIsTransparent(SkColor color) {
diff --git a/ui/gfx/image/image_unittest_util.h b/ui/gfx/image/image_unittest_util.h
index cac8015..985506b 100644
--- a/ui/gfx/image/image_unittest_util.h
+++ b/ui/gfx/image/image_unittest_util.h
@@ -40,12 +40,34 @@
 
 // Returns true if the images are equal. Converts the images to ImageSkia to
 // compare them.
-bool IsEqual(const gfx::Image& image1, const gfx::Image& image2);
+bool AreImagesEqual(const gfx::Image& image1, const gfx::Image& image2);
 
-bool IsEqual(const SkBitmap& bitmap1, const SkBitmap& bitmap2);
+// Returns true if the images are visually similar. |max_deviation| is the
+// maximum color shift in each of the red, green, and blue components for the
+// images to be considered similar. Converts to ImageSkia to compare the images.
+bool AreImagesClose(const gfx::Image& image1,
+                    const gfx::Image& image2,
+                    int max_deviation);
 
-bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
-             const SkBitmap& bitmap);
+// Returns true if the bitmaps are equal.
+bool AreBitmapsEqual(const SkBitmap& bitmap1, const SkBitmap& bitmap2);
+
+// Returns true if the bitmaps are visually similar.
+bool AreBitmapsClose(const SkBitmap& bitmap1,
+                     const SkBitmap& bitmap2,
+                     int max_deviation);
+
+// Returns true if the passed in PNG bitmap is visually similar to the passed in
+// SkBitmap.
+bool ArePNGBytesCloseToBitmap(
+    const scoped_refptr<base::RefCountedMemory>& bytes,
+    const SkBitmap& bitmap,
+    int max_deviation);
+
+// Returns the maximum color shift in the red, green, and blue components caused
+// by converting a gfx::Image between colorspaces. Color shifts occur when
+// converting between NSImage & UIImage to ImageSkia.
+int MaxColorSpaceConversionColorShift();
 
 // An image which was not successfully decoded to PNG should be a red bitmap.
 // Fails if the bitmap is not red.
diff --git a/ui/gfx/nine_image_painter.cc b/ui/gfx/nine_image_painter.cc
index d9cae91..42d5cc0 100644
--- a/ui/gfx/nine_image_painter.cc
+++ b/ui/gfx/nine_image_painter.cc
@@ -132,9 +132,6 @@
   int i6w = ImageWidthInPixels(images_[6], scale_x);
   int i8w = ImageWidthInPixels(images_[8], scale_x);
 
-  int i4x = std::min(std::min(i0w, i3w), i6w);
-  int i4w = width_in_pixels - i4x - std::min(std::min(i2w, i5w), i8w);
-
   int i0h = ImageHeightInPixels(images_[0], scale_y);
   int i1h = ImageHeightInPixels(images_[1], scale_y);
   int i2h = ImageHeightInPixels(images_[2], scale_y);
@@ -142,14 +139,27 @@
   int i7h = ImageHeightInPixels(images_[7], scale_y);
   int i8h = ImageHeightInPixels(images_[8], scale_y);
 
-  int i4y = std::min(std::min(i0h, i1h), i2h);
-  int i4h = height_in_pixels - i4y - std::min(std::min(i6h, i7h), i8h);
+  bool has_room_for_border =
+      i0w + i2w <= width_in_pixels && i3w + i5w <= width_in_pixels &&
+      i6w + i8w <= width_in_pixels && i0h + i6h <= height_in_pixels &&
+      i1h + i7h <= height_in_pixels && i2h + i8h <= height_in_pixels;
+
+  int i4x = has_room_for_border ? std::min(std::min(i0w, i3w), i6w) : 0;
+  int i4w = width_in_pixels -
+            (has_room_for_border ? i4x + std::min(std::min(i2w, i5w), i8w) : 0);
+
+  int i4y = has_room_for_border ? std::min(std::min(i0h, i1h), i2h) : 0;
+  int i4h = height_in_pixels -
+            (has_room_for_border ? i4y + std::min(std::min(i6h, i7h), i8h) : 0);
 
   SkPaint paint;
   paint.setAlpha(alpha);
 
   Fill(canvas, images_[4], i4x, i4y, i4w, i4h, paint);
 
+  if (!has_room_for_border)
+    return;
+
   Fill(canvas, images_[0], 0, 0, i0w, i0h, paint);
 
   Fill(canvas, images_[1], i0w, 0, width_in_pixels - i0w - i2w, i1h, paint);
diff --git a/ui/gfx/nine_image_painter_unittest.cc b/ui/gfx/nine_image_painter_unittest.cc
index 1bece362..6b2f10a 100644
--- a/ui/gfx/nine_image_painter_unittest.cc
+++ b/ui/gfx/nine_image_painter_unittest.cc
@@ -66,4 +66,41 @@
   }
 }
 
+TEST(NineImagePainterTest, PaintStaysInBounds) {
+  // In this test the bounds rect is 1x1 but each image is 2x2.
+  // The NineImagePainter should not paint outside the bounds.
+
+  SkBitmap src;
+  src.allocN32Pixels(6, 6);
+  src.eraseColor(SK_ColorRED);
+
+  gfx::ImageSkia image(gfx::ImageSkiaRep(src, 0.0f));
+  gfx::Insets insets(2, 2, 2, 2);
+  gfx::NineImagePainter painter(image, insets);
+
+  int image_scale = 1;
+  bool is_opaque = true;
+  gfx::Canvas canvas(gfx::Size(3, 3), image_scale, is_opaque);
+  canvas.DrawColor(SK_ColorBLACK);
+
+  gfx::Rect bounds(1, 1, 1, 1);
+  painter.Paint(&canvas, bounds);
+
+  SkBitmap result;
+  const SkISize size = canvas.sk_canvas()->getDeviceSize();
+  result.allocN32Pixels(size.width(), size.height());
+  canvas.sk_canvas()->readPixels(&result, 0, 0);
+
+  EXPECT_EQ(SK_ColorRED, result.getColor(1, 1));
+
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(0, 0));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(0, 1));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(0, 2));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(1, 0));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(1, 2));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(2, 0));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(2, 1));
+  EXPECT_EQ(SK_ColorBLACK, result.getColor(2, 2));
+}
+
 }  // namespace gfx
diff --git a/ui/gfx/vector_icons/autologin.icon b/ui/gfx/vector_icons/autologin.icon
new file mode 100644
index 0000000..5007f2a0
--- /dev/null
+++ b/ui/gfx/vector_icons/autologin.icon
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+MOVE_TO, 15.6f, 23,
+CUBIC_TO, 13.56f, 23, 12, 20.76f, 12, 18.75f,
+LINE_TO, 12, 9.64f,
+CUBIC_TO, 12, 7.63f, 13.65f, 6, 15.69f, 6,
+LINE_TO, 32.31f, 6,
+CUBIC_TO, 34.35f, 6, 36, 7.63f, 36, 9.64f,
+LINE_TO, 36, 18.75f,
+CUBIC_TO, 36, 20.76f, 34.44f, 23, 32.4f, 23,
+LINE_TO, 28, 23,
+LINE_TO, 28, 37.11f,
+LINE_TO, 25.87f, 42,
+LINE_TO, 23.01f, 42,
+LINE_TO, 20, 40.78f,
+LINE_TO, 20, 23,
+LINE_TO, 15.6f, 23,
+CLOSE,
+MOVE_TO, 24, 25,
+LINE_TO, 24, 37,
+LINE_TO, 22, 37,
+LINE_TO, 22, 25,
+LINE_TO, 24, 25,
+CLOSE,
+MOVE_TO, 18, 9,
+LINE_TO, 30, 9,
+LINE_TO, 30, 13,
+LINE_TO, 18, 13,
+LINE_TO, 18, 9,
+LINE_TO, 18, 9,
+CLOSE,
+END
diff --git a/ui/gfx/vector_icons/chrome_product.icon b/ui/gfx/vector_icons/chrome_product.icon
new file mode 100644
index 0000000..b7cc06d
--- /dev/null
+++ b/ui/gfx/vector_icons/chrome_product.icon
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 12, 7.5f,
+R_H_LINE_TO, 8.9f,
+CUBIC_TO, 19.3f, 4.2f, 15.9f, 2, 12, 2,
+CUBIC_TO, 8.9f, 2, 6.1f, 3.4f, 4.3f, 5.6f,
+R_LINE_TO, 3.3f, 5.7f,
+R_CUBIC_TO, 0.3f, -2.1f, 2.2f, -3.8f, 4.4f, -3.8f,
+CLOSE,
+R_MOVE_TO, 0, 9,
+R_CUBIC_TO, -1.7f, 0, -3.1f, -0.9f, -3.9f, -2.3f,
+LINE_TO, 3.6f, 6.5f,
+CUBIC_TO, 2.6f, 8.1f, 2, 10, 2, 12,
+R_CUBIC_TO, 0, 5, 3.6f, 9.1f, 8.4f, 9.9f,
+R_LINE_TO, 3.3f, -5.7f,
+R_CUBIC_TO, -0.6f, 0.2f, -1.1f, 0.3f, -1.7f, 0.3f,
+CLOSE,
+R_MOVE_TO, 4.5f, -4.5f,
+R_CUBIC_TO, 0, 0.8f, -0.2f, 1.6f, -0.6f, 2.2f,
+LINE_TO, 11.4f, 22,
+R_H_LINE_TO, 0.6f,
+R_CUBIC_TO, 5.5f, 0, 10, -4.5f, 10, -10,
+R_CUBIC_TO, 0, -1.2f, -0.2f, -2.4f, -0.6f, -3.5f,
+R_H_LINE_TO, -6.6f,
+R_CUBIC_TO, 1, 0.8f, 1.7f, 2.1f, 1.7f, 3.5f,
+CLOSE,
+CIRCLE, 12, 12, 3.5,
+END
diff --git a/ui/gfx/vector_icons/extension_crashed.icon b/ui/gfx/vector_icons/extension_crashed.icon
new file mode 100644
index 0000000..6a88cb6
--- /dev/null
+++ b/ui/gfx/vector_icons/extension_crashed.icon
@@ -0,0 +1,36 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+MOVE_TO, 37, 23,
+LINE_TO, 40, 23,
+CUBIC_TO, 42.76f, 23, 45, 25.24f, 45, 28,
+CUBIC_TO, 45, 30.76f, 42.76f, 33, 40, 33,
+LINE_TO, 37, 33,
+LINE_TO, 37, 41,
+CUBIC_TO, 37, 43.2f, 35.2f, 45, 33, 45,
+LINE_TO, 25.4f, 45,
+LINE_TO, 25.4f, 42,
+CUBIC_TO, 25.4f, 39.02f, 22.98f, 36.6f, 20, 36.6f,
+CUBIC_TO, 17.02f, 36.6f, 14.6f, 39.02f, 14.6f, 42,
+LINE_TO, 14.6f, 45,
+LINE_TO, 7, 45,
+CUBIC_TO, 4.8f, 45, 3, 43.2f, 3, 41,
+LINE_TO, 3, 33.4f,
+LINE_TO, 6, 33.4f,
+CUBIC_TO, 8.98f, 33.4f, 11.4f, 30.98f, 11.4f, 28,
+CUBIC_TO, 11.4f, 25.02f, 8.98f, 22.6f, 6, 22.6f,
+LINE_TO, 3.02f, 22.6f,
+LINE_TO, 3.02f, 15,
+CUBIC_TO, 3.02f, 12.8f, 4.8f, 11, 7, 11,
+LINE_TO, 15, 11,
+LINE_TO, 15, 8,
+CUBIC_TO, 15, 5.24f, 17.24f, 3, 20, 3,
+CUBIC_TO, 22.76f, 3, 25, 5.24f, 25, 8,
+LINE_TO, 25, 11,
+LINE_TO, 29.5f, 11,
+LINE_TO, 16, 31.5f,
+LINE_TO, 37, 17.5f,
+LINE_TO, 37, 23,
+CLOSE,
+END
diff --git a/ui/gfx/win/hwnd_util.cc b/ui/gfx/win/hwnd_util.cc
index 5700ccf..f02a312 100644
--- a/ui/gfx/win/hwnd_util.cc
+++ b/ui/gfx/win/hwnd_util.cc
@@ -6,7 +6,6 @@
 
 #include "base/i18n/rtl.h"
 #include "base/strings/string_util.h"
-#include "base/tracked_objects.h"
 #include "base/win/metro.h"
 #include "base/win/win_util.h"
 #include "ui/gfx/geometry/point.h"
@@ -224,13 +223,8 @@
     flags |= TPM_RIGHTALIGN;
   HMENU menu = GetSystemMenu(window, FALSE);
 
-  // Use task stopwatch to exclude the time while the context menu is open from
-  // the current task, if any.
-  tracked_objects::TaskStopwatch stopwatch;
-  stopwatch.Start();
   const int command =
       TrackPopupMenu(menu, flags, point.x(), point.y(), 0, window, NULL);
-  stopwatch.Stop();
 
   if (command)
     SendMessage(window, WM_SYSCOMMAND, command, 0);
diff --git a/ui/gfx/win/window_impl.cc b/ui/gfx/win/window_impl.cc
index 375434f9..bc0cb00 100644
--- a/ui/gfx/win/window_impl.cc
+++ b/ui/gfx/win/window_impl.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/debug/alias.h"
 #include "base/memory/singleton.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/lock.h"
 #include "base/win/wrapped_window_proc.h"
@@ -283,10 +282,6 @@
                                      UINT message,
                                      WPARAM w_param,
                                      LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WindowImpl::WndProc"));
-
   if (message == WM_NCCREATE) {
     CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param);
     WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams);
diff --git a/ui/message_center/fake_message_center.cc b/ui/message_center/fake_message_center.cc
index 946b2c7..f6c3f86c 100644
--- a/ui/message_center/fake_message_center.cc
+++ b/ui/message_center/fake_message_center.cc
@@ -140,4 +140,6 @@
 
 void FakeMessageCenter::DisableTimersForTest() {}
 
+void FakeMessageCenter::DisableChangeQueueForTest() {}
+
 }  // namespace message_center
diff --git a/ui/message_center/fake_message_center.h b/ui/message_center/fake_message_center.h
index 604453c..454b0f9 100644
--- a/ui/message_center/fake_message_center.h
+++ b/ui/message_center/fake_message_center.h
@@ -67,6 +67,7 @@
 
  protected:
   void DisableTimersForTest() override;
+  void DisableChangeQueueForTest() override;
 
  private:
   const NotificationList::Notifications empty_notifications_;
diff --git a/ui/message_center/message_center.h b/ui/message_center/message_center.h
index 05de0448..f626893 100644
--- a/ui/message_center/message_center.h
+++ b/ui/message_center/message_center.h
@@ -177,9 +177,11 @@
  protected:
   friend class ::DownloadNotification;
   friend class MessageCenterImplTest;
+  friend class MessageCenterImplTestWithoutChangeQueue;
   friend class TrayViewControllerTest;
   friend class test::MessagePopupCollectionTest;
   virtual void DisableTimersForTest() = 0;
+  virtual void DisableChangeQueueForTest() = 0;
 
   MessageCenter();
   virtual ~MessageCenter();
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index eb8807fc..515b91b 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -7,9 +7,11 @@
 #include <algorithm>
 #include <deque>
 
+#include "base/command_line.h"
 #include "base/memory/scoped_vector.h"
 #include "base/observer_list.h"
 #include "ui/message_center/message_center_style.h"
+#include "ui/message_center/message_center_switches.h"
 #include "ui/message_center/message_center_types.h"
 #include "ui/message_center/notification.h"
 #include "ui/message_center/notification_blocker.h"
@@ -351,7 +353,11 @@
       popup_timers_controller_(new PopupTimersController(this)),
       settings_provider_(NULL) {
   notification_list_.reset(new NotificationList());
-  notification_queue_.reset(new internal::ChangeQueue());
+
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableMessageCenterChangesWhileOpen)) {
+    notification_queue_.reset(new internal::ChangeQueue());
+  }
 }
 
 MessageCenterImpl::~MessageCenterImpl() {
@@ -430,8 +436,10 @@
         MessageCenterObserver, observer_list_, OnNotificationUpdated(id));
   }
 
-  if (visibility == VISIBILITY_TRANSIENT)
+  if (notification_queue_ &&
+      visibility == VISIBILITY_TRANSIENT) {
     notification_queue_->ApplyChanges(this);
+  }
 
   FOR_EACH_OBSERVER(MessageCenterObserver,
                     observer_list_,
@@ -481,7 +489,8 @@
 }
 
 void MessageCenterImpl::ForceNotificationFlush(const std::string& id) {
-  notification_queue_->ApplyChangesForId(this, id);
+  if (notification_queue_)
+    notification_queue_->ApplyChangesForId(this, id);
 }
 
 //------------------------------------------------------------------------------
@@ -492,7 +501,8 @@
   for (size_t i = 0; i < blockers_.size(); ++i)
     blockers_[i]->CheckState();
 
-  if (notification_list_->is_message_center_visible()) {
+  if (notification_queue_ &&
+      notification_list_->is_message_center_visible()) {
     notification_queue_->AddNotification(notification.Pass());
     return;
   }
@@ -527,7 +537,8 @@
   for (size_t i = 0; i < blockers_.size(); ++i)
     blockers_[i]->CheckState();
 
-  if (notification_list_->is_message_center_visible()) {
+  if (notification_queue_ &&
+      notification_list_->is_message_center_visible()) {
     // We will allow notifications that are progress types (and stay progress
     // types) to be updated even if the message center is open.  There are 3
     // requirements here:
@@ -574,7 +585,8 @@
 
 void MessageCenterImpl::RemoveNotification(const std::string& id,
                                            bool by_user) {
-  if (!by_user && notification_list_->is_message_center_visible()) {
+  if (notification_queue_ && !by_user &&
+      notification_list_->is_message_center_visible()) {
     notification_queue_->EraseNotification(id, by_user);
     return;
   }
@@ -655,8 +667,10 @@
 void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id,
                                             const gfx::Image& image) {
   bool updated = false;
-  Notification* queue_notification = notification_queue_->GetLatestNotification(
-      notification_id);
+  Notification* queue_notification =
+      notification_queue_
+          ? notification_queue_->GetLatestNotification(notification_id)
+          : NULL;
 
   if (queue_notification) {
     queue_notification->set_icon(image);
@@ -674,8 +688,10 @@
 void MessageCenterImpl::SetNotificationImage(const std::string& notification_id,
                                              const gfx::Image& image) {
   bool updated = false;
-  Notification* queue_notification = notification_queue_->GetLatestNotification(
-      notification_id);
+  Notification* queue_notification =
+      notification_queue_
+          ? notification_queue_->GetLatestNotification(notification_id)
+          : NULL;
 
   if (queue_notification) {
     queue_notification->set_image(image);
@@ -694,8 +710,10 @@
     const std::string& notification_id, int button_index,
     const gfx::Image& image) {
   bool updated = false;
-  Notification* queue_notification = notification_queue_->GetLatestNotification(
-      notification_id);
+  Notification* queue_notification =
+      notification_queue_
+          ? notification_queue_->GetLatestNotification(notification_id)
+          : NULL;
 
   if (queue_notification) {
     queue_notification->SetButtonIcon(button_index, image);
@@ -848,4 +866,8 @@
   popup_timers_controller_.reset();
 }
 
+void MessageCenterImpl::DisableChangeQueueForTest() {
+  notification_queue_.reset();
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/message_center_impl.h b/ui/message_center/message_center_impl.h
index c9c531f..72cd0d4 100644
--- a/ui/message_center/message_center_impl.h
+++ b/ui/message_center/message_center_impl.h
@@ -100,6 +100,7 @@
 
  protected:
   void DisableTimersForTest() override;
+  void DisableChangeQueueForTest() override;
 
  private:
   struct NotificationCache {
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc
index 8cbe6b9..8fc43bc6 100644
--- a/ui/message_center/message_center_impl_unittest.cc
+++ b/ui/message_center/message_center_impl_unittest.cc
@@ -100,6 +100,20 @@
   DISALLOW_COPY_AND_ASSIGN(MessageCenterImplTest);
 };
 
+class MessageCenterImplTestWithoutChangeQueue : public MessageCenterImplTest {
+ public:
+  MessageCenterImplTestWithoutChangeQueue() {}
+  ~MessageCenterImplTestWithoutChangeQueue() override {}
+
+  void SetUp() override {
+    MessageCenterImplTest::SetUp();
+    message_center()->DisableChangeQueueForTest();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MessageCenterImplTestWithoutChangeQueue);
+};
+
 namespace {
 
 class ToggledNotificationBlocker : public NotificationBlocker {
@@ -1093,5 +1107,59 @@
   ASSERT_EQ(0u, message_center()->NotificationCount());
 }
 
+TEST_F(MessageCenterImplTestWithoutChangeQueue,
+       UpdateWhileMessageCenterVisible) {
+  std::string id("id1");
+  std::string id2("id2");
+  NotifierId notifier_id1(NotifierId::APPLICATION, "app1");
+
+  // First, add and update a notification to ensure updates happen
+  // normally.
+  scoped_ptr<Notification> notification(CreateSimpleNotification(id));
+  message_center()->AddNotification(notification.Pass());
+  notification.reset(CreateSimpleNotification(id2));
+  message_center()->UpdateNotification(id, notification.Pass());
+  EXPECT_TRUE(message_center()->FindVisibleNotificationById(id2));
+  EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
+
+  // Then open the message center.
+  message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
+
+  // Then update a notification; the update should have propagated.
+  notification.reset(CreateSimpleNotification(id));
+  message_center()->UpdateNotification(id2, notification.Pass());
+  EXPECT_FALSE(message_center()->FindVisibleNotificationById(id2));
+  EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
+}
+
+TEST_F(MessageCenterImplTestWithoutChangeQueue, AddWhileMessageCenterVisible) {
+  std::string id("id1");
+
+  // Then open the message center.
+  message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
+
+  // Add a notification and confirm the adding should have propagated.
+  scoped_ptr<Notification> notification(CreateSimpleNotification(id));
+  message_center()->AddNotification(notification.Pass());
+  EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
+}
+
+TEST_F(MessageCenterImplTestWithoutChangeQueue,
+       RemoveWhileMessageCenterVisible) {
+  std::string id("id1");
+
+  // First, add a notification to ensure updates happen normally.
+  scoped_ptr<Notification> notification(CreateSimpleNotification(id));
+  message_center()->AddNotification(notification.Pass());
+  EXPECT_TRUE(message_center()->FindVisibleNotificationById(id));
+
+  // Then open the message center.
+  message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER);
+
+  // Then update a notification; the update should have propagated.
+  message_center()->RemoveNotification(id, false);
+  EXPECT_FALSE(message_center()->FindVisibleNotificationById(id));
+}
+
 }  // namespace internal
 }  // namespace message_center
diff --git a/ui/message_center/message_center_switches.cc b/ui/message_center/message_center_switches.cc
index 4f82c1a..d42fc78 100644
--- a/ui/message_center/message_center_switches.cc
+++ b/ui/message_center/message_center_switches.cc
@@ -6,6 +6,11 @@
 
 namespace switches {
 
+// Enables notification changes while the message center opens. This flag will
+// removed once the feature gets stable.
+const char kEnableMessageCenterChangesWhileOpen[] =
+    "enable-message-center-changes-while-open";
+
 // Enables message center to always move other notifications upwards when a
 // notification is removed, no matter whether the message center is displayed
 // top down or not.
diff --git a/ui/message_center/message_center_switches.h b/ui/message_center/message_center_switches.h
index be4692e..43029a9 100644
--- a/ui/message_center/message_center_switches.h
+++ b/ui/message_center/message_center_switches.h
@@ -10,6 +10,7 @@
 
 namespace switches {
 
+MESSAGE_CENTER_EXPORT extern const char kEnableMessageCenterChangesWhileOpen[];
 MESSAGE_CENTER_EXPORT extern const char
     kEnableMessageCenterAlwaysScrollUpUponNotificationRemoval[];
 
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc
index 486feebd..ccdb0437 100644
--- a/ui/message_center/views/message_center_view.cc
+++ b/ui/message_center/views/message_center_view.cc
@@ -455,6 +455,15 @@
   if (view_iter == notification_views_.end())
     return;
   NotificationView* view = view_iter->second;
+  // Set the item on the mouse cursor as the reposition target so that it
+  // should stick to the current position over the update.
+  for (const auto& hover_id_view : notification_views_) {
+    NotificationView* hover_view = hover_id_view.second;
+    if (hover_view->is_hover()) {
+      message_list_view_->SetRepositionTarget(hover_view->bounds());
+      break;
+    }
+  }
   // TODO(dimich): add MessageCenter::GetVisibleNotificationById(id)
   const NotificationList::Notifications& notifications =
       message_center_->GetVisibleNotifications();
diff --git a/ui/message_center/views/message_center_view_unittest.cc b/ui/message_center/views/message_center_view_unittest.cc
index 0953f531..5ea3f2ee 100644
--- a/ui/message_center/views/message_center_view_unittest.cc
+++ b/ui/message_center/views/message_center_view_unittest.cc
@@ -9,15 +9,20 @@
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/message_center/fake_message_center.h"
+#include "ui/message_center/message_center_style.h"
 #include "ui/message_center/notification.h"
 #include "ui/message_center/notification_list.h"
 #include "ui/message_center/notification_types.h"
 #include "ui/message_center/views/message_center_controller.h"
 #include "ui/message_center/views/message_center_view.h"
+#include "ui/message_center/views/message_list_view.h"
 #include "ui/message_center/views/notification_view.h"
 
 namespace message_center {
 
+static const char* kNotificationId1 = "notification id 1";
+static const char* kNotificationId2 = "notification id 2";
+
 /* Types **********************************************************************/
 
 enum CallType {
@@ -78,6 +83,17 @@
   NotificationView::Layout();
 }
 
+class FakeMessageCenterImpl : public FakeMessageCenter {
+ public:
+  const NotificationList::Notifications& GetVisibleNotifications() override {
+    return visible_notifications_;
+  }
+  void SetVisibleNotifications(NotificationList::Notifications notifications) {
+    visible_notifications_ = notifications;
+  }
+  NotificationList::Notifications visible_notifications_;
+};
+
 /* Test fixture ***************************************************************/
 
 class MessageCenterViewTest : public testing::Test,
@@ -91,8 +107,15 @@
   void TearDown() override;
 
   MessageCenterView* GetMessageCenterView();
+  MessageListView* GetMessageListView();
+  NotificationView* GetNotificationView(const std::string& id);
+  views::BoundsAnimator* GetAnimator();
   int GetNotificationCount();
   int GetCallCount(CallType type);
+  int GetCalculatedMessageListViewHeight();
+  void AddNotification(scoped_ptr<Notification> notification);
+  void UpdateNotification(const std::string& notification_id,
+                          scoped_ptr<Notification> notification);
 
  // Overridden from MessageCenterController:
   void ClickOnNotification(const std::string& notification_id) override;
@@ -113,9 +136,11 @@
  private:
   views::View* MakeParent(views::View* child1, views::View* child2);
 
+  base::MessageLoopForUI message_loop_;
 
+  NotificationList::Notifications notifications_;
   scoped_ptr<MessageCenterView> message_center_view_;
-  FakeMessageCenter message_center_;
+  FakeMessageCenterImpl message_center_;
   std::map<CallType,int> callCounts_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest);
@@ -129,30 +154,36 @@
 
 void MessageCenterViewTest::SetUp() {
   // Create a dummy notification.
-  Notification notification(
-      NOTIFICATION_TYPE_SIMPLE, std::string("notification id"),
-      base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message"), gfx::Image(),
+  Notification* notification1 = new Notification(
+      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
+      base::UTF8ToUTF16("title"), base::UTF8ToUTF16("message1"), gfx::Image(),
+      base::UTF8ToUTF16("display source"), GURL(),
+      NotifierId(NotifierId::APPLICATION, "extension_id"),
+      message_center::RichNotificationData(), NULL);
+
+  Notification* notification2 = new Notification(
+      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
+      base::UTF8ToUTF16("title2"), base::UTF8ToUTF16("message2"), gfx::Image(),
       base::UTF8ToUTF16("display source"), GURL(),
       NotifierId(NotifierId::APPLICATION, "extension_id"),
       message_center::RichNotificationData(), NULL);
 
   // ...and a list for it.
-  NotificationList::Notifications notifications;
-  notifications.insert(&notification);
+  notifications_.insert(notification1);
+  notifications_.insert(notification2);
+  message_center_.SetVisibleNotifications(notifications_);
 
   // Then create a new MessageCenterView with that single notification.
   base::string16 title;
   message_center_view_.reset(new MessageCenterView(
       &message_center_, NULL, 100, false, /*top_down =*/false, title));
-  message_center_view_->SetNotifications(notifications);
+  GetMessageListView()->quit_message_loop_after_animation_for_test_ = true;
+  GetMessageCenterView()->SetBounds(0, 0, 380, 600);
+  message_center_view_->SetNotifications(notifications_);
 
-  // Remove and delete the NotificationView now owned by the MessageCenterView's
-  // MessageListView and replace it with an instrumented MockNotificationView
-  // that will become owned by the MessageListView.
-  MockNotificationView* mock;
-  mock = new MockNotificationView(this, notification, this);
-  message_center_view_->notification_views_[notification.id()] = mock;
-  message_center_view_->SetNotificationViewForTest(mock);
+  // Wait until the animation finishes if available.
+  if (GetAnimator()->IsAnimating())
+    base::MessageLoop::current()->Run();
 }
 
 void MessageCenterViewTest::TearDown() {
@@ -163,8 +194,25 @@
   return message_center_view_.get();
 }
 
+MessageListView* MessageCenterViewTest::GetMessageListView() {
+  return message_center_view_->message_list_view_.get();
+}
+
+NotificationView* MessageCenterViewTest::GetNotificationView(
+    const std::string& id) {
+  return message_center_view_->notification_views_[id];
+}
+
+int MessageCenterViewTest::GetCalculatedMessageListViewHeight() {
+  return GetMessageListView()->GetHeightForWidth(GetMessageListView()->width());
+}
+
+views::BoundsAnimator* MessageCenterViewTest::GetAnimator() {
+  return &GetMessageListView()->animator_;
+}
+
 int MessageCenterViewTest::GetNotificationCount() {
-  return 1;
+  return 2;
 }
 
 int MessageCenterViewTest::GetCallCount(CallType type) {
@@ -177,11 +225,41 @@
   NOTREACHED();
 }
 
+void MessageCenterViewTest::AddNotification(
+    scoped_ptr<Notification> notification) {
+  std::string notification_id = notification->id();
+  notifications_.insert(notification.release());
+  message_center_.SetVisibleNotifications(notifications_);
+  message_center_view_->OnNotificationAdded(notification_id);
+}
+
+void MessageCenterViewTest::UpdateNotification(
+    const std::string& notification_id,
+    scoped_ptr<Notification> notification) {
+  for (auto it = notifications_.begin(); it != notifications_.end(); it++) {
+    if ((*it)->id() == notification_id) {
+      notifications_.erase(it);
+      break;
+    }
+  }
+  // |notifications| is a "set" container so we don't need to be aware the
+  // order.
+  notifications_.insert(notification.release());
+  message_center_.SetVisibleNotifications(notifications_);
+  message_center_view_->OnNotificationUpdated(notification_id);
+}
+
 void MessageCenterViewTest::RemoveNotification(
     const std::string& notification_id,
     bool by_user) {
-  // For this test, this method should not be invoked.
-  NOTREACHED();
+  for (auto it = notifications_.begin(); it != notifications_.end(); it++) {
+    if ((*it)->id() == notification_id) {
+      notifications_.erase(it);
+      break;
+    }
+  }
+  message_center_.SetVisibleNotifications(notifications_);
+  message_center_view_->OnNotificationRemoved(notification_id, by_user);
 }
 
 scoped_ptr<ui::MenuModel> MessageCenterViewTest::CreateMenuModel(
@@ -221,10 +299,13 @@
 
 /* Unit tests *****************************************************************/
 
-TEST_F(MessageCenterViewTest, CallTest) {
-  // Exercise (with size values that just need to be large enough).
-  GetMessageCenterView()->SetBounds(0, 0, 100, 100);
-
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_CallTest DISABLED_CallTest
+#else
+#define MAYBE_CallTest CallTest
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_CallTest) {
   // Verify that this didn't generate more than 2 Layout() call per descendant
   // NotificationView or more than a total of 20 GetPreferredSize() and
   // GetHeightForWidth() calls per descendant NotificationView. 20 is a very
@@ -236,4 +317,174 @@
             GetNotificationCount() * 20);
 }
 
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_Size DISABLED_Size
+#else
+#define MAYBE_Size Size
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_Size) {
+  EXPECT_EQ(2, GetMessageListView()->child_count());
+  EXPECT_EQ(GetMessageListView()->height(),
+            GetCalculatedMessageListViewHeight());
+
+  int width =
+      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
+  EXPECT_EQ(
+      GetMessageListView()->height(),
+      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
+          (kMarginBetweenItems - MessageView::GetShadowInsets().bottom()) +
+          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
+          GetMessageListView()->GetInsets().height());
+}
+
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_SizeAfterUpdate DISABLED_SizeAfterUpdate
+#else
+#define MAYBE_SizeAfterUpdate SizeAfterUpdate
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_SizeAfterUpdate) {
+  EXPECT_EQ(2, GetMessageListView()->child_count());
+  int width =
+      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
+
+  scoped_ptr<Notification> notification(new Notification(
+      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
+      base::UTF8ToUTF16("title2"),
+      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
+      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+      NotifierId(NotifierId::APPLICATION, "extension_id"),
+      message_center::RichNotificationData(), NULL));
+
+  EXPECT_EQ(
+      GetMessageListView()->height(),
+      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
+          (kMarginBetweenItems - MessageView::GetShadowInsets().bottom()) +
+          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
+          GetMessageListView()->GetInsets().height());
+
+  int previous_height = GetMessageListView()->height();
+
+  UpdateNotification(kNotificationId2, notification.Pass());
+
+  // Wait until the animation finishes if available.
+  if (GetAnimator()->IsAnimating())
+    base::MessageLoop::current()->Run();
+
+  EXPECT_EQ(2, GetMessageListView()->child_count());
+  EXPECT_EQ(GetMessageListView()->height(),
+            GetCalculatedMessageListViewHeight());
+
+  // The size must be changed, since the new string is longer than the old one.
+  EXPECT_NE(previous_height, GetMessageListView()->height());
+
+  EXPECT_EQ(
+      GetMessageListView()->height(),
+      GetNotificationView(kNotificationId1)->GetHeightForWidth(width) +
+          (kMarginBetweenItems - MessageView::GetShadowInsets().bottom()) +
+          GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
+          GetMessageListView()->GetInsets().height());
+}
+
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_SizeAfterRemove DISABLED_SizeAfterRemove
+#else
+#define MAYBE_SizeAfterRemove SizeAfterRemove
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_SizeAfterRemove) {
+  EXPECT_EQ(2, GetMessageListView()->child_count());
+  RemoveNotification(kNotificationId1, false);
+
+  // Wait until the animation finishes if available.
+  if (GetAnimator()->IsAnimating())
+    base::MessageLoop::current()->Run();
+
+  EXPECT_EQ(1, GetMessageListView()->child_count());
+
+  int width =
+      GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
+  EXPECT_FALSE(GetNotificationView(kNotificationId1));
+  EXPECT_TRUE(GetNotificationView(kNotificationId2));
+  EXPECT_EQ(GetMessageListView()->height(),
+            GetNotificationView(kNotificationId2)->GetHeightForWidth(width) +
+                GetMessageListView()->GetInsets().height());
+}
+
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_PositionAfterUpdate DISABLED_PositionAfterUpdate
+#else
+#define MAYBE_PositionAfterUpdate PositionAfterUpdate
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_PositionAfterUpdate) {
+  // Make sure that the notification 2 is placed above the notification 1.
+  EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
+            GetNotificationView(kNotificationId1)->bounds().y());
+
+  int previous_vertical_pos_from_bottom =
+      GetMessageListView()->height() -
+      GetNotificationView(kNotificationId1)->bounds().y();
+  GetMessageListView()->SetRepositionTargetForTest(
+      GetNotificationView(kNotificationId1)->bounds());
+
+  scoped_ptr<Notification> notification(new Notification(
+      NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
+      base::UTF8ToUTF16("title2"),
+      base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
+      gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+      NotifierId(NotifierId::APPLICATION, "extension_id"),
+      message_center::RichNotificationData(), NULL));
+  UpdateNotification(kNotificationId2, notification.Pass());
+
+  // Wait until the animation finishes if available.
+  if (GetAnimator()->IsAnimating())
+    base::MessageLoop::current()->Run();
+
+  // The vertical position of the target from bottom should be kept over change.
+  int current_vertical_pos_from_bottom =
+      GetMessageListView()->height() -
+      GetNotificationView(kNotificationId1)->bounds().y();
+  EXPECT_EQ(previous_vertical_pos_from_bottom,
+            current_vertical_pos_from_bottom);
+}
+
+// TODO(yoshiki): Fix this test on Linux ASAN http://crbug.com/537265
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_PositionAfterRemove DISABLED_PositionAfterRemove
+#else
+#define MAYBE_PositionAfterRemove PositionAfterRemove
+#endif  // ADDRESS_SANITIZER
+TEST_F(MessageCenterViewTest, MAYBE_PositionAfterRemove) {
+  // Make sure that the notification 2 is placed above the notification 1.
+  EXPECT_LT(GetNotificationView(kNotificationId2)->bounds().y(),
+            GetNotificationView(kNotificationId1)->bounds().y());
+
+  GetMessageListView()->SetRepositionTargetForTest(
+      GetNotificationView(kNotificationId2)->bounds());
+  int previous_height = GetMessageListView()->height();
+  int previous_notification2_y =
+      GetNotificationView(kNotificationId2)->bounds().y();
+
+  EXPECT_EQ(2, GetMessageListView()->child_count());
+  RemoveNotification(kNotificationId2, false);
+
+  // Wait until the animation finishes if available.
+  if (GetAnimator()->IsAnimating())
+    base::MessageLoop::current()->Run();
+
+  EXPECT_EQ(1, GetMessageListView()->child_count());
+
+  // Confirm that notification 1 is moved up to the place on which the
+  // notification 2 was.
+  EXPECT_EQ(previous_notification2_y,
+            GetNotificationView(kNotificationId1)->bounds().y());
+  // The size should be kept.
+  EXPECT_EQ(previous_height, GetMessageListView()->height());
+
+  EXPECT_FALSE(GetNotificationView(kNotificationId2));
+  EXPECT_TRUE(GetNotificationView(kNotificationId1));
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index 505fe1c..0291b7a 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -29,6 +29,7 @@
       clear_all_started_(false),
       top_down_(top_down),
       animator_(this),
+      quit_message_loop_after_animation_for_test_(false),
       weak_ptr_factory_(this) {
   views::BoxLayout* layout =
       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1);
@@ -126,15 +127,10 @@
 }
 
 gfx::Size MessageListView::GetPreferredSize() const {
-  int width = 0;
-  for (int i = 0; i < child_count(); i++) {
-    const views::View* child = child_at(i);
-    if (IsValidChild(child))
-      width = std::max(width, child->GetPreferredSize().width());
-  }
-
-  return gfx::Size(width + GetInsets().width(),
-                   GetHeightForWidth(width + GetInsets().width()));
+  // Just returns the current size. All size change must be done in
+  // |DoUpdateIfPossible()| with animation , because we don't want to change
+  // the size in unexpected timing.
+  return size();
 }
 
 int MessageListView::GetHeightForWidth(int width) const {
@@ -174,7 +170,7 @@
 }
 
 void MessageListView::SetRepositionTarget(const gfx::Rect& target) {
-  reposition_top_ = target.y();
+  reposition_top_ = std::max(target.y(), 0);
   fixed_height_ = GetHeightForWidth(width());
 }
 
@@ -236,6 +232,9 @@
 
   if (GetWidget())
     GetWidget()->SynthesizeMouseMoveEvent();
+
+  if (quit_message_loop_after_animation_for_test_)
+    base::MessageLoop::current()->Quit();
 }
 
 bool MessageListView::IsValidChild(const views::View* child) const {
@@ -261,6 +260,9 @@
     return;
   }
 
+  int new_height = GetHeightForWidth(child_area.width() + GetInsets().width());
+  SetSize(gfx::Size(child_area.width() + GetInsets().width(), new_height));
+
   if (top_down_ ||
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableMessageCenterAlwaysScrollUpUponNotificationRemoval))
@@ -270,64 +272,121 @@
 
   adding_views_.clear();
   deleting_views_.clear();
+
+  if (!animator_.IsAnimating() && GetWidget())
+    GetWidget()->SynthesizeMouseMoveEvent();
 }
 
 void MessageListView::AnimateNotificationsBelowTarget() {
-  int last_index = -1;
-  for (int i = 0; i < child_count(); ++i) {
-    views::View* child = child_at(i);
-    if (!IsValidChild(child)) {
-      AnimateChild(child, child->y(), child->height());
-    } else if (reposition_top_ < 0 || child->y() > reposition_top_) {
-      // Find first notification below target (or all notifications if no
-      // target).
-      last_index = i;
-      break;
+  int target_index = -1;
+  int padding = kMarginBetweenItems - MessageView::GetShadowInsets().bottom();
+  gfx::Rect child_area = GetContentsBounds();
+  if (reposition_top_ >= 0) {
+    for (int i = 0; i < child_count(); ++i) {
+      views::View* child = child_at(i);
+      if (child->y() >= reposition_top_) {
+        // Find the target.
+        target_index = i;
+        break;
+      }
     }
   }
-  if (last_index > 0) {
-    int between_items =
-        kMarginBetweenItems - MessageView::GetShadowInsets().bottom();
-    int top = (reposition_top_ > 0) ? reposition_top_ : GetInsets().top();
-
-    for (int i = last_index; i < child_count(); ++i) {
-      // Animate notifications below target upwards.
-      views::View* child = child_at(i);
-      if (AnimateChild(child, top, child->height()))
-        top += child->height() + between_items;
+  int top;
+  if (target_index != -1) {
+    // Layout the target.
+    int y = reposition_top_;
+    views::View* target = child_at(target_index);
+    int target_height = target->GetHeightForWidth(child_area.width());
+    if (AnimateChild(target, y - target_height, target_height,
+                     false /* animate_on_move */)) {
+      y -= target_height + padding;
     }
+
+    // Layout the items above the target.
+    for (int i = target_index - 1; i >= 0; --i) {
+      views::View* child = child_at(i);
+      int height = child->GetHeightForWidth(child_area.width());
+      if (AnimateChild(child, y - height, height, false /* animate_on_move */))
+        y -= height + padding;
+    }
+
+    top = reposition_top_ + target_height + padding;
+  } else {
+    target_index = -1;
+    top = GetInsets().top();
+  }
+
+  // Layout the items below the target (or all items if target is unavailable).
+  for (int i = target_index + 1; i < child_count(); ++i) {
+    views::View* child = child_at(i);
+    int height = child->GetHeightForWidth(child_area.width());
+    if (AnimateChild(child, top, height, true /* animate_on_move */))
+      top += height + padding;
   }
 }
 
 void MessageListView::AnimateNotificationsAboveTarget() {
-  int last_index = -1;
-  for (int i = child_count() - 1; i >= 0; --i) {
-    views::View* child = child_at(i);
-    if (!IsValidChild(child)) {
-      AnimateChild(child, child->y(), child->height());
-    } else if (reposition_top_ < 0 || child->y() < reposition_top_) {
-      // Find first notification above target (or all notifications if no
-      // target).
-      last_index = i;
-      break;
+  int target_index = -1;
+  int padding = kMarginBetweenItems - MessageView::GetShadowInsets().bottom();
+  gfx::Rect child_area = GetContentsBounds();
+  if (reposition_top_ >= 0) {
+    for (int i = 0; i < child_count(); ++i) {
+      views::View* child = child_at(i);
+      if (child->y() >= reposition_top_) {
+        // Find the target.
+        target_index = i;
+        break;
+      }
     }
   }
-  if (last_index >= 0) {
-    int between_items =
-        kMarginBetweenItems - MessageView::GetShadowInsets().bottom();
-    int bottom = (reposition_top_ > 0)
-                     ? reposition_top_ + child_at(last_index)->height()
-                     : GetHeightForWidth(width()) - GetInsets().bottom();
-    for (int i = last_index; i >= 0; --i) {
-      // Animate notifications above target downwards.
+  int bottom;
+  if (target_index != -1) {
+    // Calculate the vertical length between the top of message list and the top
+    // of target.
+    int vertical_gap_to_target_from_top = GetInsets().height();
+    for (int i = target_index - 1; i >= 0; --i) {
       views::View* child = child_at(i);
-      if (AnimateChild(child, bottom - child->height(), child->height()))
-        bottom -= child->height() + between_items;
+      int height = child->GetHeightForWidth(child_area.width());
+      vertical_gap_to_target_from_top += height + padding;
     }
+
+    // If the calculated length is changed from |repositon_top_|, some of items
+    // above the targe are updated and their height are changed. Adjust the
+    // vertical length above the target.
+    if (reposition_top_ != vertical_gap_to_target_from_top) {
+      fixed_height_ -= reposition_top_ - vertical_gap_to_target_from_top;
+      reposition_top_ = vertical_gap_to_target_from_top;
+    }
+
+    // Match the top with |reposition_top_|.
+    int y = reposition_top_;
+    // Layout the target and the items below the target.
+    for (int i = target_index; i < child_count(); i++) {
+      views::View* child = child_at(i);
+      int height = child->GetHeightForWidth(child_area.width());
+      if (AnimateChild(child, y, height, false /* animate_on_move */))
+        y += height + padding;
+    }
+
+    bottom = reposition_top_ - padding;
+  } else {
+    target_index = child_count();
+    bottom = height() - GetInsets().bottom();
+  }
+
+  // Layout the items above the target (or all items if target is unavailable).
+  for (int i = target_index - 1; i >= 0; --i) {
+    views::View* child = child_at(i);
+    int height = child->GetHeightForWidth(child_area.width());
+    if (AnimateChild(child, bottom - height, height, true))
+      bottom -= height + padding;
   }
 }
 
-bool MessageListView::AnimateChild(views::View* child, int top, int height) {
+bool MessageListView::AnimateChild(views::View* child,
+                                   int top,
+                                   int height,
+                                   bool animate_on_move) {
   gfx::Rect child_area = GetContentsBounds();
   if (adding_views_.find(child) != adding_views_.end()) {
     child->SetBounds(child_area.right(), top, child_area.width(), height);
@@ -341,7 +400,7 @@
     return false;
   } else {
     gfx::Rect target(child_area.x(), top, child_area.width(), height);
-    if (child->bounds().origin() != target.origin())
+    if (child->bounds().origin() != target.origin() && animate_on_move)
       animator_.AnimateViewTo(child, target);
     else
       child->SetBoundsRect(target);
@@ -372,4 +431,8 @@
   }
 }
 
+void MessageListView::SetRepositionTargetForTest(const gfx::Rect& target_rect) {
+  SetRepositionTarget(target_rect);
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/views/message_list_view.h b/ui/message_center/views/message_list_view.h
index 9512b5306..b961cf8 100644
--- a/ui/message_center/views/message_list_view.h
+++ b/ui/message_center/views/message_list_view.h
@@ -11,6 +11,7 @@
 #include "ui/compositor/paint_context.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/message_center/message_center_export.h"
 #include "ui/message_center/notification.h"
 #include "ui/views/animation/bounds_animator.h"
 #include "ui/views/animation/bounds_animator_observer.h"
@@ -46,6 +47,9 @@
   void ResetRepositionSession();
   void ClearAllNotifications(const gfx::Rect& visible_scroll_rect);
 
+  MESSAGE_CENTER_EXPORT void SetRepositionTargetForTest(
+      const gfx::Rect& target_rect);
+
  protected:
   // Overridden from views::View.
   void Layout() override;
@@ -59,6 +63,8 @@
   void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
 
  private:
+  friend class MessageCenterViewTest;
+
   bool IsValidChild(const views::View* child) const;
   void DoUpdateIfPossible();
 
@@ -71,7 +77,10 @@
 
   // Schedules animation for a child to the specified position. Returns false
   // if |child| will disappear after the animation.
-  bool AnimateChild(views::View* child, int top, int height);
+  bool AnimateChild(views::View* child,
+                    int top,
+                    int height,
+                    bool animate_even_on_move);
 
   // Animate clearing one notification.
   void AnimateClearingOneNotification();
@@ -91,8 +100,12 @@
   std::set<views::View*> deleted_when_done_;
   std::list<views::View*> clearing_all_views_;
   views::BoundsAnimator animator_;
-  base::WeakPtrFactory<MessageListView> weak_ptr_factory_;
 
+  // If true, the message loop will be quitted after the animation finishes.
+  // This is just for tests and has no setter.
+  bool quit_message_loop_after_animation_for_test_;
+
+  base::WeakPtrFactory<MessageListView> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(MessageListView);
 };
 
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index 62e2993..7e501d4 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -46,7 +46,8 @@
       notifier_id_(notifier_id),
       background_view_(NULL),
       scroller_(NULL),
-      display_source_(display_source) {
+      display_source_(display_source),
+      is_hover_(false) {
   SetFocusable(true);
 
   // Create the opaque background that's above the view's shadow.
@@ -84,6 +85,15 @@
 MessageView::~MessageView() {
 }
 
+// views::View
+void MessageView::OnMouseEntered(const ui::MouseEvent& event) {
+  is_hover_ = true;
+}
+
+void MessageView::OnMouseExited(const ui::MouseEvent& event) {
+  is_hover_ = false;
+}
+
 void MessageView::UpdateWithNotification(const Notification& notification) {
   small_image_view_->SetImage(notification.small_image().AsImageSkia());
   display_source_ = notification.display_source();
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index 28cd607..cf0ef4fc 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -82,6 +82,8 @@
   void OnFocus() override;
   void OnBlur() override;
   void Layout() override;
+  void OnMouseEntered(const ui::MouseEvent& event) override;
+  void OnMouseExited(const ui::MouseEvent& event) override;
 
   // Overridden from ui::EventHandler:
   void OnGestureEvent(ui::GestureEvent* event) override;
@@ -94,6 +96,8 @@
   NotifierId notifier_id() { return notifier_id_; }
   const base::string16& display_source() const { return display_source_; }
 
+  bool is_hover() { return is_hover_; }
+
  protected:
   // Overridden from views::SlideOutView:
   void OnSlideOut() override;
@@ -115,6 +119,9 @@
 
   base::string16 display_source_;
 
+  // True if the mouse cursor is on this view. False if not.
+  bool is_hover_;
+
   scoped_ptr<views::Painter> focus_painter_;
 
   // Changes the background color being used by |background_view_| and schedules
diff --git a/ui/ozone/common/gpu/ozone_gpu_message_params.cc b/ui/ozone/common/gpu/ozone_gpu_message_params.cc
index 0a7e7e59..77633c57 100644
--- a/ui/ozone/common/gpu/ozone_gpu_message_params.cc
+++ b/ui/ozone/common/gpu/ozone_gpu_message_params.cc
@@ -19,8 +19,7 @@
 
 DisplaySnapshot_Params::~DisplaySnapshot_Params() {}
 
-OverlayCheck_Params::OverlayCheck_Params() {
-}
+OverlayCheck_Params::OverlayCheck_Params() {}
 
 OverlayCheck_Params::OverlayCheck_Params(
     const OverlayCandidatesOzone::OverlaySurfaceCandidate& candidate)
@@ -29,7 +28,8 @@
       format(candidate.format),
       display_rect(gfx::ToNearestRect(candidate.display_rect)),
       crop_rect(candidate.crop_rect),
-      plane_z_order(candidate.plane_z_order) {}
+      plane_z_order(candidate.plane_z_order),
+      weight(0) {}
 
 OverlayCheck_Params::~OverlayCheck_Params() {
 }
diff --git a/ui/ozone/common/gpu/ozone_gpu_message_params.h b/ui/ozone/common/gpu/ozone_gpu_message_params.h
index 1764502..ae9e83f 100644
--- a/ui/ozone/common/gpu/ozone_gpu_message_params.h
+++ b/ui/ozone/common/gpu/ozone_gpu_message_params.h
@@ -59,6 +59,12 @@
   gfx::Rect display_rect;
   gfx::RectF crop_rect;
   int plane_z_order = 0;
+  // Higher the value, the more important it is to ensure that this
+  // overlay candidate finds a compatible free hardware plane to use.
+  uint32_t weight;
+  // Will be set in GPU process. These are unique plane ids of primary display
+  // supporting this configuration.
+  std::vector<uint32_t> plane_ids;
 };
 
 }  // namespace ui
diff --git a/ui/ozone/common/gpu/ozone_gpu_messages.h b/ui/ozone/common/gpu/ozone_gpu_messages.h
index 11b6536..aa93245 100644
--- a/ui/ozone/common/gpu/ozone_gpu_messages.h
+++ b/ui/ozone/common/gpu/ozone_gpu_messages.h
@@ -69,6 +69,8 @@
   IPC_STRUCT_TRAITS_MEMBER(display_rect)
   IPC_STRUCT_TRAITS_MEMBER(crop_rect)
   IPC_STRUCT_TRAITS_MEMBER(plane_z_order)
+  IPC_STRUCT_TRAITS_MEMBER(weight)
+  IPC_STRUCT_TRAITS_MEMBER(plane_ids)
 IPC_STRUCT_TRAITS_END()
 
 // clang-format on
@@ -173,7 +175,8 @@
 IPC_MESSAGE_CONTROL1(OzoneHostMsg_DisplayControlRelinquished,
                      bool /* success */)
 
-// Response for OzoneGpuMsg_CheckOverlayCapabilities
+// Response to OzoneGpuMsg_CheckOverlayCapabilities. Returns list of supported
+// params.
 IPC_MESSAGE_CONTROL2(OzoneHostMsg_OverlayCapabilitiesReceived,
                      gfx::AcceleratedWidget /* widget */,
-                     bool /* result */)
+                     std::vector<ui::OverlayCheck_Params> /* overlays */)
diff --git a/ui/ozone/platform/cast/BUILD.gn b/ui/ozone/platform/cast/BUILD.gn
index 98b3d52f..ba6908f9 100644
--- a/ui/ozone/platform/cast/BUILD.gn
+++ b/ui/ozone/platform/cast/BUILD.gn
@@ -28,7 +28,7 @@
   deps = [
     "//base",
     "//chromecast/graphics:libcast_graphics",
-    "//chromecast/media:libcast_media",
+    "//chromecast/media/base:libcast_media_1.0",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/ozone:ozone_base",
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.cc b/ui/ozone/platform/drm/gpu/crtc_controller.cc
index 8871a17..adc3c84 100644
--- a/ui/ozone/platform/drm/gpu/crtc_controller.cc
+++ b/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -113,6 +113,11 @@
   return true;
 }
 
+std::vector<uint32_t> CrtcController::GetCompatibleHardwarePlaneIds(
+    const OverlayPlane& plane) const {
+  return drm_->plane_manager()->GetCompatibleHardwarePlaneIds(plane, crtc_);
+}
+
 void CrtcController::PageFlipFailed() {
   pending_planes_.clear();
   SignalPageFlipRequest();
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.h b/ui/ozone/platform/drm/gpu/crtc_controller.h
index 5d3c6b1..6d05ce6 100644
--- a/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -54,6 +54,10 @@
                         bool test_only,
                         scoped_refptr<PageFlipRequest> page_flip_request);
 
+  // Returns list of plane id's which can support |plane| configuration.
+  std::vector<uint32_t> GetCompatibleHardwarePlaneIds(
+      const OverlayPlane& plane) const;
+
   // Called if the page flip for this CRTC fails after being scheduled.
   void PageFlipFailed();
 
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc
index b7ad1e9..32b78eff 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -4,6 +4,8 @@
 
 #include "ui/ozone/platform/drm/gpu/drm_window.h"
 
+#include <drm_fourcc.h>
+
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -32,6 +34,20 @@
 void EmptyFlipCallback(gfx::SwapResult) {
 }
 
+// TODO(kalyank): We now have this switch statement in GBMBuffer and here.
+// It would be nice to have it in one place.
+uint32_t GetFourCCFormatFromBufferFormat(gfx::BufferFormat format) {
+  switch (format) {
+    case gfx::BufferFormat::BGRA_8888:
+      return DRM_FORMAT_ARGB8888;
+    case gfx::BufferFormat::BGRX_8888:
+      return DRM_FORMAT_XRGB8888;
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
 void UpdateCursorImage(DrmBuffer* cursor, const SkBitmap& image) {
   SkRect damage;
   image.getBounds(&damage);
@@ -143,35 +159,81 @@
   }
 }
 
-bool DrmWindow::TestPageFlip(const std::vector<OverlayCheck_Params>& overlays,
-                             ScanoutBufferGenerator* buffer_generator) {
-  if (!controller_)
-    return true;
+std::vector<OverlayCheck_Params> DrmWindow::TestPageFlip(
+    const std::vector<OverlayCheck_Params>& overlays,
+    ScanoutBufferGenerator* buffer_generator) {
+  std::vector<OverlayCheck_Params> params;
+  if (!controller_) {
+    // Nothing much we can do here.
+    return params;
+  }
+
+  OverlayPlaneList compatible_test_list;
+  scoped_refptr<DrmDevice> drm = controller_->GetAllocationDrmDevice();
   for (const auto& overlay : overlays) {
+    OverlayCheck_Params overlay_params(overlay);
     // It is possible that the cc rect we get actually falls off the edge of
     // the screen. Usually this is prevented via things like status bars
     // blocking overlaying or cc clipping it, but in case it wasn't properly
     // clipped (since GL will render this situation fine) just ignore it here.
     // This should be an extremely rare occurrance.
-    if (overlay.plane_z_order != 0 && !bounds().Contains(overlay.display_rect))
-      return false;
-  }
+    if (overlay.plane_z_order != 0 &&
+        !bounds().Contains(overlay.display_rect)) {
+      continue;
+    }
 
-  scoped_refptr<DrmDevice> drm = controller_->GetAllocationDrmDevice();
-  OverlayPlaneList planes;
-  for (const auto& overlay : overlays) {
     gfx::Size size =
         (overlay.plane_z_order == 0) ? bounds().size() : overlay.buffer_size;
-    scoped_refptr<ScanoutBuffer> buffer =
-        buffer_generator->Create(drm, overlay.format, size);
+    scoped_refptr<ScanoutBuffer> buffer;
+    // Check if we can re-use existing buffers.
+    for (const auto& plane : last_submitted_planes_) {
+      uint32_t format = GetFourCCFormatFromBufferFormat(overlay.format);
+      // We always use a storage type of XRGB, even if the pixel format
+      // is ARGB.
+      if (format == DRM_FORMAT_ARGB8888)
+        format = DRM_FORMAT_XRGB8888;
+
+      if (plane.buffer->GetFramebufferPixelFormat() == format &&
+          plane.z_order == overlay.plane_z_order &&
+          plane.display_bounds == overlay.display_rect &&
+          plane.buffer->GetSize() == size) {
+        buffer = plane.buffer;
+        break;
+      }
+    }
+
     if (!buffer)
-      return false;
-    planes.push_back(OverlayPlane(buffer, overlay.plane_z_order,
-                                  overlay.transform, overlay.display_rect,
-                                  overlay.crop_rect));
+      buffer = buffer_generator->Create(drm, overlay.format, size);
+
+    if (!buffer)
+      continue;
+
+    OverlayPlane plane(buffer, overlay.plane_z_order, overlay.transform,
+                       overlay.display_rect, overlay.crop_rect);
+
+    // Buffer for Primary plane should always be present for compatibility test.
+    if (!compatible_test_list.size() && overlay.plane_z_order != 0) {
+      compatible_test_list.push_back(
+          *OverlayPlane::GetPrimaryPlane(last_submitted_planes_));
+    }
+
+    compatible_test_list.push_back(plane);
+
+    bool page_flip_succeeded = controller_->SchedulePageFlip(
+        compatible_test_list, true /* test_only */,
+        base::Bind(&EmptyFlipCallback));
+
+    if (page_flip_succeeded) {
+      overlay_params.plane_ids =
+          controller_->GetCompatibleHardwarePlaneIds(plane);
+      params.push_back(overlay_params);
+    }
+
+    if (compatible_test_list.size() > 1)
+      compatible_test_list.pop_back();
   }
-  return controller_->SchedulePageFlip(planes, true /* test_only */,
-                                       base::Bind(&EmptyFlipCallback));
+
+  return params;
 }
 
 const OverlayPlane* DrmWindow::GetLastModesetBuffer() {
diff --git a/ui/ozone/platform/drm/gpu/drm_window.h b/ui/ozone/platform/drm/gpu/drm_window.h
index 761b175..a7f4507 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/ui/ozone/platform/drm/gpu/drm_window.h
@@ -85,8 +85,9 @@
 
   void SchedulePageFlip(const std::vector<OverlayPlane>& planes,
                         const SwapCompletionCallback& callback);
-  bool TestPageFlip(const std::vector<OverlayCheck_Params>& planes,
-                    ScanoutBufferGenerator* buffer_generator);
+  std::vector<OverlayCheck_Params> TestPageFlip(
+      const std::vector<OverlayCheck_Params>& planes,
+      ScanoutBufferGenerator* buffer_generator);
 
   // Returns the last buffer associated with this window.
   const OverlayPlane* GetLastModesetBuffer();
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index adc0c6d..fde972c2 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -116,6 +116,26 @@
   return status;
 }
 
+std::vector<uint32_t> HardwareDisplayController::GetCompatibleHardwarePlaneIds(
+    const OverlayPlane& plane) const {
+  std::vector<uint32_t> plane_ids =
+      crtc_controllers_[0]->GetCompatibleHardwarePlaneIds(plane);
+
+  if (plane_ids.empty())
+    return plane_ids;
+
+  for (size_t i = 1; i < crtc_controllers_.size(); ++i) {
+    // Make sure all mirrored displays have overlays to support this
+    // plane.
+    if (crtc_controllers_[i]->GetCompatibleHardwarePlaneIds(plane).empty())
+      return std::vector<uint32_t>();
+  }
+
+  // TODO(kalyank): We Should ensure that this list doesn't contain any planes
+  // which mirrored displays share with primary.
+  return plane_ids;
+}
+
 bool HardwareDisplayController::SetCursor(
     const scoped_refptr<ScanoutBuffer>& buffer) {
   bool status = true;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 4031e489..093a42e 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -127,6 +127,9 @@
                         bool test_only,
                         const PageFlipCallback& callback);
 
+  std::vector<uint32_t> GetCompatibleHardwarePlaneIds(
+      const OverlayPlane& plane) const;
+
   // Set the hardware cursor to show the contents of |surface|.
   bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
 
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index bad3700..24f4c73 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -144,11 +144,10 @@
 HardwareDisplayPlane* HardwareDisplayPlaneManager::FindNextUnusedPlane(
     size_t* index,
     uint32_t crtc_index,
-    uint32_t format) {
+    const OverlayPlane& overlay) const {
   for (size_t i = *index; i < planes_.size(); ++i) {
     auto plane = planes_[i];
-    if (!plane->in_use() && plane->CanUseForCrtc(crtc_index) &&
-        plane->IsSupportedFormat(format)) {
+    if (!plane->in_use() && IsCompatible(plane, overlay, crtc_index)) {
       *index = i + 1;
       return plane;
     }
@@ -156,13 +155,29 @@
   return nullptr;
 }
 
-int HardwareDisplayPlaneManager::LookupCrtcIndex(uint32_t crtc_id) {
+int HardwareDisplayPlaneManager::LookupCrtcIndex(uint32_t crtc_id) const {
   for (size_t i = 0; i < crtcs_.size(); ++i)
     if (crtcs_[i] == crtc_id)
       return i;
   return -1;
 }
 
+bool HardwareDisplayPlaneManager::IsCompatible(HardwareDisplayPlane* plane,
+                                               const OverlayPlane& overlay,
+                                               uint32_t crtc_index) const {
+  if (!plane->CanUseForCrtc(crtc_index))
+    return false;
+
+  if (!plane->IsSupportedFormat(overlay.buffer->GetFramebufferPixelFormat()))
+    return false;
+
+  // TODO(kalyank): We should check for z-order and any needed transformation
+  // support. Driver doesn't expose any property to check for z-order, can we
+  // rely on the sorting we do based on plane ids ?
+
+  return true;
+}
+
 void HardwareDisplayPlaneManager::BeginFrame(
     HardwareDisplayPlaneList* plane_list) {
   for (auto* plane : plane_list->old_plane_list) {
@@ -183,8 +198,8 @@
 
   size_t plane_idx = 0;
   for (const auto& plane : overlay_list) {
-    HardwareDisplayPlane* hw_plane = FindNextUnusedPlane(
-        &plane_idx, crtc_index, plane.buffer->GetFramebufferPixelFormat());
+    HardwareDisplayPlane* hw_plane =
+        FindNextUnusedPlane(&plane_idx, crtc_index, plane);
     if (!hw_plane) {
       LOG(ERROR) << "Failed to find a free plane for crtc " << crtc_id;
       return false;
@@ -218,4 +233,23 @@
   return true;
 }
 
+std::vector<uint32_t>
+HardwareDisplayPlaneManager::GetCompatibleHardwarePlaneIds(
+    const OverlayPlane& plane,
+    uint32_t crtc_id) const {
+  int crtc_index = LookupCrtcIndex(crtc_id);
+  if (crtc_index < 0) {
+    LOG(ERROR) << "Cannot find crtc " << crtc_id;
+    return std::vector<uint32_t>();
+  }
+
+  std::vector<uint32_t> plane_ids;
+  for (auto* hardware_plane : planes_) {
+    if (IsCompatible(hardware_plane, plane, crtc_index))
+      plane_ids.push_back(hardware_plane->plane_id());
+  }
+
+  return plane_ids;
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index 94e50c79..99c7ed7 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -94,6 +94,9 @@
 
   const ScopedVector<HardwareDisplayPlane>& planes() { return planes_; }
 
+  std::vector<uint32_t> GetCompatibleHardwarePlaneIds(const OverlayPlane& plane,
+                                                      uint32_t crtc_id) const;
+
  protected:
   virtual bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
                             HardwareDisplayPlane* hw_plane,
@@ -109,10 +112,16 @@
   // be used with |crtc_index|.
   HardwareDisplayPlane* FindNextUnusedPlane(size_t* index,
                                             uint32_t crtc_index,
-                                            uint32_t format);
+                                            const OverlayPlane& overlay) const;
 
   // Convert |crtc_id| into an index, returning -1 if the ID couldn't be found.
-  int LookupCrtcIndex(uint32_t crtc_id);
+  int LookupCrtcIndex(uint32_t crtc_id) const;
+
+  // Returns true if |plane| can support |overlay| and compatible with
+  // |crtc_index|.
+  bool IsCompatible(HardwareDisplayPlane* plane,
+                    const OverlayPlane& overlay,
+                    uint32_t crtc_index) const;
 
   // Object containing the connection to the graphics device and wraps the API
   // calls to control it. Not owned.
diff --git a/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc b/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
index 2fcbe8c9..b13ff81 100644
--- a/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
+++ b/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
@@ -42,6 +42,13 @@
   return l.buffer_size.height() < r.buffer_size.height();
 }
 
+DrmOverlayCandidatesHost::HardwareDisplayPlaneProxy::HardwareDisplayPlaneProxy(
+    uint32_t id)
+    : plane_id(id) {}
+
+DrmOverlayCandidatesHost::HardwareDisplayPlaneProxy::
+    ~HardwareDisplayPlaneProxy() {}
+
 DrmOverlayCandidatesHost::DrmOverlayCandidatesHost(
     gfx::AcceleratedWidget widget,
     DrmGpuPlatformSupportHost* platform_support)
@@ -57,46 +64,68 @@
 
 void DrmOverlayCandidatesHost::CheckOverlaySupport(
     OverlaySurfaceCandidateList* candidates) {
-  if (candidates->size() == 2)
-    CheckSingleOverlay(candidates);
-}
+  uint32_t compatible_candidates = 0;
+  uint32_t planes_in_use = 0;
+  bool force_validation = false;
+  std::vector<OverlayCheck_Params> new_candidates;
+  for (auto& candidate : *candidates) {
+    if (!CanHandleCandidate(candidate))
+      continue;
 
-void DrmOverlayCandidatesHost::CheckSingleOverlay(
-    OverlaySurfaceCandidateList* candidates) {
-  OverlayCandidatesOzone::OverlaySurfaceCandidate* first = &(*candidates)[0];
-  OverlayCandidatesOzone::OverlaySurfaceCandidate* second = &(*candidates)[1];
-  OverlayCandidatesOzone::OverlaySurfaceCandidate* overlay;
-  if (first->plane_z_order == 0) {
-    overlay = second;
-  } else if (second->plane_z_order == 0) {
-    overlay = first;
-  } else {
+    OverlayCheck_Params lookup(candidate);
+    if (!force_validation) {
+      CompatibleParams::const_iterator last_iter =
+          in_use_compatible_params_.find(lookup);
+      if (last_iter != in_use_compatible_params_.end()) {
+        candidate.overlay_handled = last_iter->second;
+        compatible_candidates++;
+        if (candidate.overlay_handled)
+          planes_in_use++;
+
+        continue;
+      }
+    }
+
+    auto iter = cache_.Get(lookup);
+    if (iter == cache_.end()) {
+      lookup.weight = CalculateCandidateWeight(candidate);
+      new_candidates.push_back(lookup);
+      cache_.Put(lookup, false);
+    } else if (iter->second) {
+      force_validation = true;
+    }
+  }
+
+  // We have new candidates whose configuration needs to be validated in GPU
+  // side.
+  if (!new_candidates.empty())
+    SendRequest(new_candidates);
+
+  if (compatible_candidates > planes_in_use &&
+      planes_in_use < hardware_plane_proxy_.size()) {
+    force_validation = true;
+  }
+
+  if (!force_validation) {
+    DCHECK(planes_in_use <= hardware_plane_proxy_.size())
+        << "Total layers promoted to use Overlay:" << planes_in_use
+        << "While the maximum layers which can be actually supported are:"
+        << hardware_plane_proxy_.size();
     return;
   }
-  // 0.01 constant chosen to match DCHECKs in gfx::ToNearestRect and avoid
-  // that code asserting on quads that we accept.
-  if (!gfx::IsNearestRectWithinDistance(overlay->display_rect, 0.01f))
-    return;
-  if (overlay->transform == gfx::OVERLAY_TRANSFORM_INVALID)
-    return;
-  if (overlay->is_clipped &&
-      !overlay->clip_rect.Contains(overlay->quad_rect_in_target_space))
-    return;
 
-  OverlayCheck_Params lookup(*overlay);
-  auto iter = cache_.Get(lookup);
-  if (iter == cache_.end()) {
-    cache_.Put(lookup, false);
-    SendRequest(*candidates, lookup);
-  } else {
-    overlay->overlay_handled = iter->second;
-  }
+  // A new layer has been added or removed from the last validation. We expect
+  // this to be very rare situation, hence not fully optimized. We always
+  // validate the new combination of layers.
+  ValidateCandidates(candidates);
 }
 
 void DrmOverlayCandidatesHost::OnChannelEstablished(
     int host_id,
     scoped_refptr<base::SingleThreadTaskRunner> send_runner,
     const base::Callback<void(IPC::Message*)>& sender) {
+  // Reset any old cache.
+  ResetCache();
 }
 
 void DrmOverlayCandidatesHost::OnChannelDestroyed(int host_id) {
@@ -112,33 +141,152 @@
 }
 
 void DrmOverlayCandidatesHost::SendRequest(
-    const OverlaySurfaceCandidateList& candidates,
-    const OverlayCheck_Params& check) {
+    const std::vector<OverlayCheck_Params>& list) {
   if (!platform_support_->IsConnected())
     return;
-  pending_checks_.push_back(check);
-  std::vector<OverlayCheck_Params> list;
-  for (const auto& candidate : candidates)
-    list.push_back(OverlayCheck_Params(candidate));
+
   platform_support_->Send(
       new OzoneGpuMsg_CheckOverlayCapabilities(widget_, list));
 }
 
-void DrmOverlayCandidatesHost::OnOverlayResult(bool* handled,
-                                               gfx::AcceleratedWidget widget,
-                                               bool result) {
+void DrmOverlayCandidatesHost::OnOverlayResult(
+    bool* handled,
+    gfx::AcceleratedWidget widget,
+    const std::vector<OverlayCheck_Params>& params) {
   if (widget != widget_)
     return;
+
   *handled = true;
-  DCHECK(!pending_checks_.empty());
-  ProcessResult(pending_checks_.front(), result);
-  pending_checks_.pop_front();
+  for (const auto& check : params) {
+    // We expect params to contain only supported configurations.
+    cache_.Put(check, true);
+    for (const auto& plane_id : check.plane_ids) {
+      bool plane_found = false;
+      for (const auto* plane : hardware_plane_proxy_) {
+        if (plane->plane_id == plane_id) {
+          plane_found = true;
+          break;
+        }
+      }
+
+      if (!plane_found) {
+        hardware_plane_proxy_.push_back(
+            make_scoped_ptr(new HardwareDisplayPlaneProxy(plane_id)));
+      }
+    }
+  }
 }
 
-void DrmOverlayCandidatesHost::ProcessResult(const OverlayCheck_Params& check,
-                                             bool result) {
-  if (result)
-    cache_.Put(check, true);
+bool DrmOverlayCandidatesHost::CanHandleCandidate(
+    const OverlaySurfaceCandidate& candidate) const {
+  // 0.01 constant chosen to match DCHECKs in gfx::ToNearestRect and avoid
+  // that code asserting on quads that we accept.
+  if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f))
+    return false;
+
+  if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID)
+    return false;
+
+  if (candidate.plane_z_order != 0 && candidate.buffer_size.IsEmpty())
+    return false;
+
+  if (candidate.is_clipped &&
+      !candidate.clip_rect.Contains(candidate.quad_rect_in_target_space))
+    return false;
+
+  return true;
+}
+
+uint32_t DrmOverlayCandidatesHost::CalculateCandidateWeight(
+    const OverlaySurfaceCandidate& candidate) const {
+  uint32_t weight = 0;
+  if (candidate.plane_z_order == 0) {
+    // Make sure primary plane is always first in the list.
+    weight = 100;
+  } else {
+    // Make sure we first try to find hardware planes supporting special
+    // requirements.
+    if (candidate.transform != gfx::OVERLAY_TRANSFORM_NONE)
+      weight++;
+
+    if (candidate.format != gfx::BufferFormat::BGRA_8888 &&
+        candidate.format != gfx::BufferFormat::BGRX_8888) {
+      weight++;
+    }
+
+    // TODO(kalyank): We want to consider size based on power benefits.
+  }
+
+  return weight;
+}
+
+void DrmOverlayCandidatesHost::ValidateCandidates(
+    OverlaySurfaceCandidateList* candidates) {
+  in_use_compatible_params_.clear();
+  typedef std::pair<OverlaySurfaceCandidate*, OverlayCheck_Params>
+      CandidatePair;
+  std::vector<CandidatePair> compatible_candidates;
+  for (auto& candidate : *candidates) {
+    candidate.overlay_handled = false;
+
+    if (!CanHandleCandidate(candidate))
+      continue;
+
+    OverlayCheck_Params lookup(candidate);
+    auto iter = cache_.Peek(lookup);
+    DCHECK(iter != cache_.end());
+    if (!iter->second)
+      continue;
+
+    in_use_compatible_params_[iter->first] = false;
+    compatible_candidates.push_back(std::make_pair(&candidate, iter->first));
+  }
+
+  uint32_t available_overlays = hardware_plane_proxy_.size();
+  for (auto* plane : hardware_plane_proxy_)
+    plane->in_use = false;
+
+  // Sort in decending order w.r.t weight.
+  std::sort(compatible_candidates.begin(), compatible_candidates.end(),
+            [](const CandidatePair& l, const CandidatePair& r) {
+              return l.second.weight > r.second.weight;
+            });
+
+  // Make sure we don't handle more candidates than what we can support in
+  // GPU side.
+  for (const auto& candidate : compatible_candidates) {
+    for (auto* plane : hardware_plane_proxy_) {
+      // Plane is already in use.
+      if (plane->in_use)
+        continue;
+
+      for (const auto& plane_id : candidate.second.plane_ids) {
+        if (plane->plane_id == plane_id) {
+          available_overlays--;
+          auto iter = in_use_compatible_params_.find(candidate.second);
+          DCHECK(iter != in_use_compatible_params_.end());
+          iter->second = true;
+          candidate.first->overlay_handled = true;
+          plane->in_use = true;
+          break;
+        }
+      }
+
+      // We have succefully found a plane.
+      if (plane->in_use)
+        break;
+    }
+
+    // We dont have any free hardware resources.
+    if (!available_overlays)
+      break;
+  }
+}
+
+void DrmOverlayCandidatesHost::ResetCache() {
+  cache_.Clear();
+  in_use_compatible_params_.clear();
+  hardware_plane_proxy_.clear();
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h b/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
index 2f00cac..dca0b7c 100644
--- a/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
+++ b/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/containers/mru_cache.h"
+#include "base/memory/scoped_vector.h"
 #include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/overlay_candidates_ozone.h"
@@ -54,28 +55,47 @@
   bool OnMessageReceived(const IPC::Message& message) override;
 
  private:
-  void SendRequest(const OverlaySurfaceCandidateList& candidates,
-                   const OverlayCheck_Params& check);
+  struct HardwareDisplayPlaneProxy {
+    HardwareDisplayPlaneProxy(uint32_t id);
+    ~HardwareDisplayPlaneProxy();
+
+    bool in_use = false;
+    uint32_t plane_id;
+  };
+
+  void SendRequest(const std::vector<OverlayCheck_Params>& list);
   void OnOverlayResult(bool* handled,
                        gfx::AcceleratedWidget widget,
-                       bool result);
-  void ProcessResult(const OverlayCheck_Params& check, bool result);
-
-  void CheckSingleOverlay(OverlaySurfaceCandidateList* candidates);
+                       const std::vector<OverlayCheck_Params>& params);
+  bool CanHandleCandidate(const OverlaySurfaceCandidate& candidate) const;
+  uint32_t CalculateCandidateWeight(
+      const OverlaySurfaceCandidate& candidate) const;
+  void ValidateCandidates(OverlaySurfaceCandidateList* candidates);
+  void ResetCache();
 
   gfx::AcceleratedWidget widget_;
   DrmGpuPlatformSupportHost* platform_support_;  // Not owned.
 
-  std::deque<OverlayCheck_Params> pending_checks_;
-
   template <class KeyType, class ValueType>
   struct OverlayMap {
     typedef std::map<KeyType, ValueType, OverlayCompare> Type;
   };
+  // List of all OverlayCheck_Params which have been validated in GPU side. If
+  // this value is true, it means the particular param is compatible and
+  // corresponding candidate can be promoted to use Hardware Overlays.
   base::MRUCacheBase<OverlayCheck_Params,
                      bool,
                      base::MRUCacheNullDeletor<bool>,
                      OverlayMap> cache_;
+  // List of all OverlayCheck_Params currently in use by various candidates. If
+  // the value is true, it means the correspnding candidate has been promoted to
+  // use overlay.
+  typedef std::map<OverlayCheck_Params, bool, OverlayCompare> CompatibleParams;
+  CompatibleParams in_use_compatible_params_;
+  // Used to get best possible approximation of plane usage in GPU side. We use
+  // this to make sure we don't handle more candidates than what we can support
+  // in GPU side.
+  ScopedVector<HardwareDisplayPlaneProxy> hardware_plane_proxy_;
 
   DISALLOW_COPY_AND_ASSIGN(DrmOverlayCandidatesHost);
 };
diff --git a/ui/platform_window/win/win_window.cc b/ui/platform_window/win/win_window.cc
index 8dd2c1c..718a4093 100644
--- a/ui/platform_window/win/win_window.cc
+++ b/ui/platform_window/win/win_window.cc
@@ -4,7 +4,6 @@
 
 #include "ui/platform_window/win/win_window.h"
 
-#include "base/profiler/scoped_tracker.h"
 #include "base/strings/string16.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
@@ -119,10 +118,6 @@
 }
 
 LRESULT WinWindow::OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnMouseRange"));
-
   MSG msg = { hwnd(), message, w_param, l_param,
               static_cast<DWORD>(GetMessageTime()),
               { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
@@ -138,19 +133,11 @@
 LRESULT WinWindow::OnCaptureChanged(UINT message,
                                     WPARAM w_param,
                                     LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnCaptureChanged"));
-
   delegate_->OnLostCapture();
   return 0;
 }
 
 LRESULT WinWindow::OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnKeyEvent"));
-
   MSG msg = { hwnd(), message, w_param, l_param };
   KeyEvent event(msg);
   delegate_->DispatchEvent(&event);
@@ -159,45 +146,25 @@
 }
 
 LRESULT WinWindow::OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnNCActivate"));
-
   delegate_->OnActivationChanged(!!w_param);
   return DefWindowProc(hwnd(), message, w_param, l_param);
 }
 
 void WinWindow::OnClose() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnClose"));
-
   delegate_->OnCloseRequest();
 }
 
 LRESULT WinWindow::OnCreate(CREATESTRUCT* create_struct) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnCreate"));
-
   // TODO(sky): provide real scale factor.
   delegate_->OnAcceleratedWidgetAvailable(hwnd(), 1.f);
   return 0;
 }
 
 void WinWindow::OnDestroy() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnDestroy"));
-
   delegate_->OnClosed();
 }
 
 void WinWindow::OnPaint(HDC) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnPaint"));
-
   gfx::Rect damage_rect;
   RECT update_rect = {0};
   if (GetUpdateRect(hwnd(), &update_rect, FALSE))
@@ -207,10 +174,6 @@
 }
 
 void WinWindow::OnWindowPosChanged(WINDOWPOS* window_pos) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 WinWindow::OnWindowPosChanged"));
-
   if (!(window_pos->flags & SWP_NOSIZE) ||
       !(window_pos->flags & SWP_NOMOVE)) {
     RECT cr;
diff --git a/ui/touch_selection/BUILD.gn b/ui/touch_selection/BUILD.gn
index 7dd5eddc..dd40269 100644
--- a/ui/touch_selection/BUILD.gn
+++ b/ui/touch_selection/BUILD.gn
@@ -37,6 +37,7 @@
 
   if (use_aura) {
     deps += [
+      "//skia:skia",
       "//ui/aura:aura",
       "//ui/aura_extra:aura_extra",
       "//ui/compositor:compositor",
diff --git a/ui/touch_selection/ui_touch_selection.gyp b/ui/touch_selection/ui_touch_selection.gyp
index f191639..5bb9e2a 100644
--- a/ui/touch_selection/ui_touch_selection.gyp
+++ b/ui/touch_selection/ui_touch_selection.gyp
@@ -12,6 +12,7 @@
       'type': '<(component)',
       'dependencies': [
         '../../base/base.gyp:base',
+        '../../skia/skia.gyp:skia',
         '../base/ui_base.gyp:ui_base',
         '../events/events.gyp:events',
         '../events/events.gyp:gesture_detection',
diff --git a/ui/views/controls/button/menu_button.h b/ui/views/controls/button/menu_button.h
index dbff53c1..1881fd2 100644
--- a/ui/views/controls/button/menu_button.h
+++ b/ui/views/controls/button/menu_button.h
@@ -62,7 +62,7 @@
   void set_menu_offset(int x, int y) { menu_offset_.SetPoint(x, y); }
 
   // Activate the button (called when the button is pressed).
-  virtual bool Activate();
+  bool Activate();
 
   // Overridden from View:
   gfx::Size GetPreferredSize() const override;
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc
index 2a488a22..0161c12 100644
--- a/ui/views/controls/combobox/combobox_unittest.cc
+++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -17,61 +17,18 @@
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/views/controls/combobox/combobox_listener.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/menu/menu_runner_handler.h"
-#include "ui/views/test/menu_runner_test_api.h"
+#include "ui/views/test/combobox_test_api.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
 
 using base::ASCIIToUTF16;
 
 namespace views {
-namespace test {
-
-class ComboboxTestApi {
- public:
-  explicit ComboboxTestApi(Combobox* combobox) : combobox_(combobox) {}
-
-  void PerformActionAt(int index) { menu_model()->ActivatedAt(index); }
-  void InstallTestMenuRunner(int* menu_show_count);
-
-  gfx::Size content_size() { return combobox_->content_size_; }
-  ui::MenuModel* menu_model() { return combobox_->menu_model_adapter_.get(); }
-
- private:
-  Combobox* combobox_;
-
-  DISALLOW_COPY_AND_ASSIGN(ComboboxTestApi);
-};
-
-}  // namespace test
 
 using test::ComboboxTestApi;
 
 namespace {
 
-// An dummy implementation of MenuRunnerHandler to check if the dropdown menu is
-// shown or not.
-class TestMenuRunnerHandler : public MenuRunnerHandler {
- public:
-  explicit TestMenuRunnerHandler(int* show_counter)
-      : show_counter_(show_counter) {}
-  MenuRunner::RunResult RunMenuAt(Widget* parent,
-                                  MenuButton* button,
-                                  const gfx::Rect& bounds,
-                                  MenuAnchorPosition anchor,
-                                  ui::MenuSourceType source_type,
-                                  int32 types) override {
-    *show_counter_ += 1;
-    return MenuRunner::NORMAL_EXIT;
-  }
-
- private:
-  int* show_counter_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler);
-};
-
 // A wrapper of Combobox to intercept the result of OnKeyPressed() and
 // OnKeyReleased() methods.
 class TestCombobox : public Combobox {
@@ -226,14 +183,6 @@
 
 }  // namespace
 
-void ComboboxTestApi::InstallTestMenuRunner(int* menu_show_count) {
-  combobox_->menu_runner_.reset(
-      new MenuRunner(menu_model(), MenuRunner::COMBOBOX));
-  test::MenuRunnerTestAPI test_api(combobox_->menu_runner_.get());
-  test_api.SetMenuRunnerHandler(
-      make_scoped_ptr(new TestMenuRunnerHandler(menu_show_count)));
-}
-
 class ComboboxTest : public ViewsTestBase {
  public:
   ComboboxTest() : widget_(NULL), combobox_(NULL) {}
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc
index 654098fc..372a4f1 100644
--- a/ui/views/controls/link.cc
+++ b/ui/views/controls/link.cc
@@ -96,7 +96,8 @@
 }
 
 bool Link::OnKeyPressed(const ui::KeyEvent& event) {
-  bool activate = ((event.key_code() == ui::VKEY_SPACE) ||
+  bool activate = (((event.key_code() == ui::VKEY_SPACE) &&
+                    (event.flags() & ui::EF_ALT_DOWN) == 0) ||
                    (event.key_code() == ui::VKEY_RETURN));
   if (!activate)
     return false;
diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc
index 6ca0b30c..4d0a67a 100644
--- a/ui/views/controls/menu/native_menu_win.cc
+++ b/ui/views/controls/menu/native_menu_win.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/win/wrapped_window_proc.h"
diff --git a/ui/views/test/combobox_test_api.cc b/ui/views/test/combobox_test_api.cc
new file mode 100644
index 0000000..57a5bdb
--- /dev/null
+++ b/ui/views/test/combobox_test_api.cc
@@ -0,0 +1,62 @@
+// Copyright 2015 The Chromium Authors. 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/views/test/combobox_test_api.h"
+
+#include "ui/base/models/menu_model.h"
+#include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/controls/menu/menu_runner_handler.h"
+#include "ui/views/test/menu_runner_test_api.h"
+
+namespace views {
+namespace test {
+namespace {
+
+// An dummy implementation of MenuRunnerHandler to check if the dropdown menu is
+// shown or not.
+class TestMenuRunnerHandler : public MenuRunnerHandler {
+ public:
+  explicit TestMenuRunnerHandler(int* show_counter)
+      : show_counter_(show_counter) {}
+  MenuRunner::RunResult RunMenuAt(Widget* parent,
+                                  MenuButton* button,
+                                  const gfx::Rect& bounds,
+                                  MenuAnchorPosition anchor,
+                                  ui::MenuSourceType source_type,
+                                  int32 types) override {
+    *show_counter_ += 1;
+    return MenuRunner::NORMAL_EXIT;
+  }
+
+ private:
+  int* show_counter_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestMenuRunnerHandler);
+};
+
+}  // namespace
+
+void ComboboxTestApi::PerformActionAt(int index) {
+  menu_model()->ActivatedAt(index);
+}
+
+void ComboboxTestApi::InstallTestMenuRunner(int* menu_show_count) {
+  combobox_->menu_runner_.reset(
+      new MenuRunner(menu_model(), MenuRunner::COMBOBOX));
+  test::MenuRunnerTestAPI test_api(combobox_->menu_runner_.get());
+  test_api.SetMenuRunnerHandler(
+      make_scoped_ptr(new TestMenuRunnerHandler(menu_show_count)));
+}
+
+gfx::Size ComboboxTestApi::content_size() {
+  return combobox_->content_size_;
+}
+
+ui::MenuModel* ComboboxTestApi::menu_model() {
+  return combobox_->menu_model_adapter_.get();
+}
+
+}  // test
+}  // views
diff --git a/ui/views/test/combobox_test_api.h b/ui/views/test/combobox_test_api.h
new file mode 100644
index 0000000..725ef35
--- /dev/null
+++ b/ui/views/test/combobox_test_api.h
@@ -0,0 +1,50 @@
+// Copyright 2015 The Chromium Authors. 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_VIEWS_TEST_COMBOBOX_TEST_API_H_
+#define UI_VIEWS_TEST_COMBOBOX_TEST_API_H_
+
+#include "base/macros.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace ui {
+class MenuModel;
+}
+
+namespace views {
+class Combobox;
+
+namespace test {
+
+// A wrapper of Combobox to access private members for testing.
+class ComboboxTestApi {
+ public:
+  explicit ComboboxTestApi(Combobox* combobox) : combobox_(combobox) {}
+
+  // Activates the Combobox menu item at |index|, as if selected by the user.
+  void PerformActionAt(int index);
+
+  // Installs a testing views::MenuRunnerHandler to test when a menu should be
+  // shown. The test runner will immediately dismiss itself and increment the
+  // given |menu_show_count| by one.
+  void InstallTestMenuRunner(int* menu_show_count);
+
+  // Accessors for private data members of Combobox.
+  gfx::Size content_size();
+  ui::MenuModel* menu_model();
+
+ private:
+  Combobox* combobox_;
+
+  DISALLOW_COPY_AND_ASSIGN(ComboboxTestApi);
+};
+
+}  // namespace test
+
+}  // namespace views
+
+#endif  // UI_VIEWS_TEST_MENU_RUNNER_TEST_API_H_
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 2f603496..3112c12 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -478,6 +478,8 @@
       'controls/textfield/textfield_test_api.h',
       'test/capture_tracking_view.cc',
       'test/capture_tracking_view.h',
+      'test/combobox_test_api.cc',
+      'test/combobox_tesa_api.h',
       'test/desktop_test_views_delegate.h',
       'test/desktop_test_views_delegate_mac.mm',
       'test/event_generator_delegate_mac.h',
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
index 8afa69b..1549b2e 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -5,7 +5,6 @@
 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h"
 
 #include "base/metrics/histogram_macros.h"
-#include "base/tracked_objects.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drag_source_win.h"
 #include "ui/base/dragdrop/drop_target_event.h"
@@ -52,13 +51,9 @@
   UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Start", source,
                             ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT);
 
-  // Use task stopwatch to exclude the drag-drop time current task, if any.
-  tracked_objects::TaskStopwatch stopwatch;
-  stopwatch.Start();
   HRESULT result = DoDragDrop(
       ui::OSExchangeDataProviderWin::GetIDataObject(data), drag_source_.Get(),
       ui::DragDropTypes::DragOperationToDropEffect(operation), &effect);
-  stopwatch.Stop();
   drag_source_copy->set_data(nullptr);
 
   if (alive)
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 5560aca..5348080 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -11,9 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/debug/alias.h"
-#include "base/profiler/scoped_tracker.h"
 #include "base/trace_event/trace_event.h"
-#include "base/tracked_objects.h"
 #include "base/win/scoped_gdi_object.h"
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
@@ -884,22 +882,12 @@
 LRESULT HWNDMessageHandler::OnWndProc(UINT message,
                                       WPARAM w_param,
                                       LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile1(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnWndProc1"));
-
   HWND window = hwnd();
   LRESULT result = 0;
 
   if (delegate_ && delegate_->PreHandleMSG(message, w_param, l_param, &result))
     return result;
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile2(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnWndProc2"));
-
   // Otherwise we handle everything else.
   // NOTE: We inline ProcessWindowMessage() as 'this' may be destroyed during
   // dispatch and ProcessWindowMessage() doesn't deal with that well.
@@ -912,11 +900,6 @@
   msg_handled_ = old_msg_handled;
 
   if (!processed) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile3(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::OnWndProc3"));
-
     result = DefWindowProc(window, message, w_param, l_param);
     // DefWindowProc() may have destroyed the window and/or us in a nested
     // message loop.
@@ -925,24 +908,13 @@
   }
 
   if (delegate_) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile4(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::OnWndProc4"));
-
     delegate_->PostHandleMSG(message, w_param, l_param);
     if (message == WM_NCDESTROY)
       delegate_->HandleDestroyed();
   }
 
-  if (message == WM_ACTIVATE && IsTopLevelWindow(window)) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile5(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::OnWndProc5"));
-
+  if (message == WM_ACTIVATE && IsTopLevelWindow(window))
     PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param));
-  }
   return result;
 }
 
@@ -1024,11 +996,6 @@
 }
 
 void HWNDMessageHandler::OnAppbarAutohideEdgesChanged() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnAppbarAutohideEdgesChanged"));
-
   // This triggers querying WM_NCCALCSIZE again.
   RECT client;
   GetWindowRect(hwnd(), &client);
@@ -1247,11 +1214,6 @@
 // Message handlers ------------------------------------------------------------
 
 void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnActivateApp"));
-
   if (delegate_->IsWidgetWindow() && !active &&
       thread_id != GetCurrentThreadId()) {
     delegate_->HandleAppDeactivated();
@@ -1265,11 +1227,6 @@
                                       short command,
                                       WORD device,
                                       int keystate) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnAppCommand"));
-
   BOOL handled = !!delegate_->HandleAppCommand(command);
   SetMsgHandled(handled);
   // Make sure to return TRUE if the event was handled or in some cases the
@@ -1279,40 +1236,22 @@
 }
 
 void HWNDMessageHandler::OnCancelMode() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnCancelMode"));
-
   delegate_->HandleCancelMode();
   // Need default handling, otherwise capture and other things aren't canceled.
   SetMsgHandled(FALSE);
 }
 
 void HWNDMessageHandler::OnCaptureChanged(HWND window) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnCaptureChanged"));
-
   delegate_->HandleCaptureLost();
 }
 
 void HWNDMessageHandler::OnClose() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnClose"));
-
   delegate_->HandleClose();
 }
 
 void HWNDMessageHandler::OnCommand(UINT notification_code,
                                    int command,
                                    HWND window) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCommand"));
-
   // If the notification code is > 1 it means it is control specific and we
   // should ignore it.
   if (notification_code > 1 || delegate_->HandleAppCommand(command))
@@ -1320,16 +1259,7 @@
 }
 
 LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile1(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate1"));
-
   if (window_ex_style() &  WS_EX_COMPOSITED) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile2(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::OnCreate2"));
-
     if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
       // This is part of the magic to emulate layered windows with Aura
       // see the explanation elsewere when we set WS_EX_COMPOSITED style.
@@ -1340,10 +1270,6 @@
 
   fullscreen_handler_->set_hwnd(hwnd());
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile3(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate3"));
-
   // This message initializes the window so that focus border are shown for
   // windows.
   SendMessage(hwnd(),
@@ -1352,20 +1278,11 @@
               0);
 
   if (remove_standard_frame_) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile4(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::OnCreate4"));
-
     SetWindowLong(hwnd(), GWL_STYLE,
                   GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION);
     SendFrameChanged();
   }
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile5(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate5"));
-
   // Get access to a modifiable copy of the system menu.
   GetSystemMenu(hwnd(), false);
 
@@ -1373,25 +1290,13 @@
       ui::AreTouchEventsEnabled())
     RegisterTouchWindow(hwnd(), TWF_WANTPALM);
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile6(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate6"));
-
   // We need to allow the delegate to size its contents since the window may not
   // receive a size notification when its initial bounds are specified at window
   // creation time.
   ClientAreaSizeChanged();
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile7(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate7"));
-
   delegate_->HandleCreate();
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile8(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnCreate8"));
-
   windows_session_change_observer_.reset(new WindowsSessionChangeObserver(
       base::Bind(&HWNDMessageHandler::OnSessionChange,
                  base::Unretained(this))));
@@ -1401,32 +1306,18 @@
 }
 
 void HWNDMessageHandler::OnDestroy() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnDestroy"));
-
   windows_session_change_observer_.reset(nullptr);
   delegate_->HandleDestroying();
 }
 
 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
                                          const gfx::Size& screen_size) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnDisplayChange"));
-
   delegate_->HandleDisplayChange();
 }
 
 LRESULT HWNDMessageHandler::OnDwmCompositionChanged(UINT msg,
                                                     WPARAM w_param,
                                                     LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnDwmCompositionChanged"));
-
   if (!delegate_->IsWidgetWindow()) {
     SetMsgHandled(FALSE);
     return 0;
@@ -1437,21 +1328,11 @@
 }
 
 void HWNDMessageHandler::OnEnterMenuLoop(BOOL from_track_popup_menu) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnEnterMenuLoop"));
-
   if (menu_depth_++ == 0)
     delegate_->HandleMenuLoop(true);
 }
 
 void HWNDMessageHandler::OnEnterSizeMove() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnEnterSizeMove"));
-
   // Please refer to the comments in the OnSize function about the scrollbar
   // hack.
   // Hide the Windows scrollbar if the scroll styles are present to ensure
@@ -1469,22 +1350,12 @@
 }
 
 void HWNDMessageHandler::OnExitMenuLoop(BOOL is_shortcut_menu) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnExitMenuLoop"));
-
   if (--menu_depth_ == 0)
     delegate_->HandleMenuLoop(false);
   DCHECK_GE(0, menu_depth_);
 }
 
 void HWNDMessageHandler::OnExitSizeMove() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnExitSizeMove"));
-
   delegate_->HandleEndWMSizeMove();
   SetMsgHandled(FALSE);
   // Please refer to the notes in the OnSize function for information about
@@ -1497,11 +1368,6 @@
 }
 
 void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnGetMinMaxInfo"));
-
   gfx::Size min_window_size;
   gfx::Size max_window_size;
   delegate_->GetMinMaxSize(&min_window_size, &max_window_size);
@@ -1540,11 +1406,6 @@
 LRESULT HWNDMessageHandler::OnGetObject(UINT message,
                                         WPARAM w_param,
                                         LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnGetObject"));
-
   LRESULT reference_result = static_cast<LRESULT>(0L);
 
   // Only the lower 32 bits of l_param are valid when checking the object id
@@ -1568,11 +1429,6 @@
 LRESULT HWNDMessageHandler::OnImeMessages(UINT message,
                                           WPARAM w_param,
                                           LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnImeMessages"));
-
   LRESULT result = 0;
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
   const bool msg_handled =
@@ -1583,11 +1439,6 @@
 }
 
 void HWNDMessageHandler::OnInitMenu(HMENU menu) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnInitMenu"));
-
   bool is_fullscreen = fullscreen_handler_->fullscreen();
   bool is_minimized = IsMinimized();
   bool is_maximized = IsMaximized();
@@ -1611,22 +1462,12 @@
 
 void HWNDMessageHandler::OnInputLangChange(DWORD character_set,
                                            HKL input_language_id) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnInputLangChange"));
-
   delegate_->HandleInputLanguageChange(character_set, input_language_id);
 }
 
 LRESULT HWNDMessageHandler::OnKeyEvent(UINT message,
                                        WPARAM w_param,
                                        LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnKeyEvent"));
-
   MSG msg = {
       hwnd(), message, w_param, l_param, static_cast<DWORD>(GetMessageTime())};
   ui::KeyEvent key(msg);
@@ -1637,11 +1478,6 @@
 }
 
 void HWNDMessageHandler::OnKillFocus(HWND focused_window) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnKillFocus"));
-
   delegate_->HandleNativeBlur(focused_window);
   SetMsgHandled(FALSE);
 }
@@ -1649,11 +1485,6 @@
 LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
                                             WPARAM w_param,
                                             LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnMouseActivate"));
-
   // Please refer to the comments in the header for the touch_down_contexts_
   // member for the if statement below.
   if (touch_down_contexts_)
@@ -1698,39 +1529,21 @@
 LRESULT HWNDMessageHandler::OnMouseRange(UINT message,
                                          WPARAM w_param,
                                          LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnMouseRange"));
-
   return HandleMouseEventInternal(message, w_param, l_param, true);
 }
 
 void HWNDMessageHandler::OnMove(const gfx::Point& point) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnMove"));
-
   delegate_->HandleMove();
   SetMsgHandled(FALSE);
 }
 
 void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnMoving"));
-
   delegate_->HandleMove();
 }
 
 LRESULT HWNDMessageHandler::OnNCActivate(UINT message,
                                          WPARAM w_param,
                                          LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnNCActivate"));
-
   // Per MSDN, w_param is either TRUE or FALSE. However, MSDN also hints that:
   // "If the window is minimized when this message is received, the application
   // should pass the message to the DefWindowProc function."
@@ -1783,11 +1596,6 @@
 }
 
 LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnNCCalcSize"));
-
   // We only override the default handling if we need to specify a custom
   // non-client edge width. Note that in most cases "no insets" means no
   // custom width, but in fullscreen mode or when the NonClientFrameView
@@ -1886,11 +1694,6 @@
 }
 
 LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnNCHitTest"));
-
   if (!delegate_->IsWidgetWindow()) {
     SetMsgHandled(FALSE);
     return 0;
@@ -1965,10 +1768,6 @@
 }
 
 void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnNCPaint"));
-
   // We only do non-client painting if we're not using the native frame.
   // It's required to avoid some native painting artifacts from appearing when
   // the window is resized.
@@ -2022,11 +1821,6 @@
 LRESULT HWNDMessageHandler::OnNCUAHDrawCaption(UINT message,
                                                WPARAM w_param,
                                                LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnNCUAHDrawCaption"));
-
   // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
   // an explanation about why we need to handle this message.
   SetMsgHandled(delegate_->IsUsingCustomFrame());
@@ -2036,11 +1830,6 @@
 LRESULT HWNDMessageHandler::OnNCUAHDrawFrame(UINT message,
                                              WPARAM w_param,
                                              LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnNCUAHDrawFrame"));
-
   // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
   // an explanation about why we need to handle this message.
   SetMsgHandled(delegate_->IsUsingCustomFrame());
@@ -2048,20 +1837,12 @@
 }
 
 LRESULT HWNDMessageHandler::OnNotify(int w_param, NMHDR* l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnNotify"));
-
   LRESULT l_result = 0;
   SetMsgHandled(delegate_->HandleTooltipNotify(w_param, l_param, &l_result));
   return l_result;
 }
 
 void HWNDMessageHandler::OnPaint(HDC dc) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnPaint"));
-
   // Call BeginPaint()/EndPaint() around the paint handling, as that seems
   // to do more to actually validate the window's drawing region. This only
   // appears to matter for Windows that have the WS_EX_COMPOSITED style set
@@ -2104,11 +1885,6 @@
 LRESULT HWNDMessageHandler::OnScrollMessage(UINT message,
                                             WPARAM w_param,
                                             LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnScrollMessage"));
-
   MSG msg = {
       hwnd(), message, w_param, l_param, static_cast<DWORD>(GetMessageTime())};
   ui::ScrollEvent event(msg);
@@ -2119,11 +1895,6 @@
 LRESULT HWNDMessageHandler::OnSetCursor(UINT message,
                                         WPARAM w_param,
                                         LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnSetCursor"));
-
   // Reimplement the necessary default behavior here. Calling DefWindowProc can
   // trigger weird non-client painting for non-glass windows with custom frames.
   // Using a ScopedRedrawLock to prevent caption rendering artifacts may allow
@@ -2165,41 +1936,23 @@
 }
 
 void HWNDMessageHandler::OnSetFocus(HWND last_focused_window) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnSetFocus"));
-
   delegate_->HandleNativeFocus(last_focused_window);
   SetMsgHandled(FALSE);
 }
 
 LRESULT HWNDMessageHandler::OnSetIcon(UINT size_type, HICON new_icon) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnSetIcon"));
-
   // Use a ScopedRedrawLock to avoid weird non-client painting.
   return DefWindowProcWithRedrawLock(WM_SETICON, size_type,
                                      reinterpret_cast<LPARAM>(new_icon));
 }
 
 LRESULT HWNDMessageHandler::OnSetText(const wchar_t* text) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnSetText"));
-
   // Use a ScopedRedrawLock to avoid weird non-client painting.
   return DefWindowProcWithRedrawLock(WM_SETTEXT, NULL,
                                      reinterpret_cast<LPARAM>(text));
 }
 
 void HWNDMessageHandler::OnSettingChange(UINT flags, const wchar_t* section) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnSettingChange"));
-
   if (!GetParent(hwnd()) && (flags == SPI_SETWORKAREA) &&
       !delegate_->WillProcessWorkAreaChange()) {
     // Fire a dummy SetWindowPos() call, so we'll trip the code in
@@ -2215,10 +1968,6 @@
 }
 
 void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION("440919 HWNDMessageHandler::OnSize"));
-
   RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
   // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
   // invoked OnSize we ensure the RootView has been laid out.
@@ -2240,11 +1989,6 @@
 
 void HWNDMessageHandler::OnSysCommand(UINT notification_code,
                                       const gfx::Point& point) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnSysCommand"));
-
   if (!delegate_->ShouldHandleSystemCommands())
     return;
 
@@ -2295,19 +2039,10 @@
     // with the mouse/touch/keyboard, we flag as being in a size loop.
     if ((notification_code & sc_mask) == SC_SIZE)
       in_size_loop_ = true;
-    const bool runs_nested_loop = ((notification_code & sc_mask) == SC_SIZE) ||
-                                  ((notification_code & sc_mask) == SC_MOVE);
     base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
 
-    // Use task stopwatch to exclude the time spend in the move/resize loop from
-    // the current task, if any.
-    tracked_objects::TaskStopwatch stopwatch;
-    if (runs_nested_loop)
-      stopwatch.Start();
     DefWindowProc(hwnd(), WM_SYSCOMMAND, notification_code,
                   MAKELPARAM(point.x(), point.y()));
-    if (runs_nested_loop)
-      stopwatch.Stop();
 
     if (!ref.get())
       return;
@@ -2316,22 +2051,12 @@
 }
 
 void HWNDMessageHandler::OnThemeChanged() {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnThemeChanged"));
-
   ui::NativeThemeWin::instance()->CloseHandles();
 }
 
 LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
                                          WPARAM w_param,
                                          LPARAM l_param) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnTouchEvent"));
-
   // Handle touch events only on Aura for now.
   int num_points = LOWORD(w_param);
   scoped_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
@@ -2404,11 +2129,6 @@
 }
 
 void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnWindowPosChanging"));
-
   if (ignore_window_pos_changes_) {
     // If somebody's trying to toggle our visibility, change the nonclient area,
     // change our Z-order, or activate us, we should probably let it go through.
@@ -2500,11 +2220,6 @@
 }
 
 void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnWindowPosChanged"));
-
   if (DidClientAreaSizeChange(window_pos))
     ClientAreaSizeChanged();
   if (remove_standard_frame_ && window_pos->flags & SWP_FRAMECHANGED &&
@@ -2530,11 +2245,6 @@
 }
 
 void HWNDMessageHandler::OnSessionChange(WPARAM status_code) {
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::OnSessionChange"));
-
   // Direct3D presents are ignored while the screen is locked, so force the
   // window to be redrawn on unlock.
   if (status_code == WTS_SESSION_UNLOCK)
@@ -2558,22 +2268,12 @@
   if (!touch_ids_.empty())
     return 0;
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile1(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::HandleMouseEventInternal1"));
-
   // We handle touch events on Windows Aura. Windows generates synthesized
   // mouse messages in response to touch which we should ignore. However touch
   // messages are only received for the client area. We need to ignore the
   // synthesized mouse messages for all points in the client area and places
   // which return HTNOWHERE.
   if (ui::IsMouseEventFromTouch(message)) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile2(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal2"));
-
     LPARAM l_param_ht = l_param;
     // For mouse events (except wheel events), location is in window coordinates
     // and should be converted to screen coordinates for WM_NCHITTEST.
@@ -2600,11 +2300,6 @@
   }
 
   if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile3(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal3"));
-
     is_right_mouse_pressed_on_caption_ = false;
     ReleaseCapture();
     // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
@@ -2648,11 +2343,6 @@
     SetCapture();
   }
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile4(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::HandleMouseEventInternal4"));
-
   long message_time = GetMessageTime();
   MSG msg = { hwnd(), message, w_param, l_param,
               static_cast<DWORD>(message_time),
@@ -2662,11 +2352,6 @@
     event.set_flags(event.flags() | ui::EF_FROM_TOUCH);
 
   if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture() && track_mouse) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile5(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal5"));
-
     // Windows only fires WM_MOUSELEAVE events if the application begins
     // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
     // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
@@ -2678,31 +2363,16 @@
     // OnMouseEvent.
     active_mouse_tracking_flags_ = 0;
   } else if (event.type() == ui::ET_MOUSEWHEEL) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile6(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal6"));
-
     // Reroute the mouse wheel to the window under the pointer if applicable.
     return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
             delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1;
   }
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile7(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::HandleMouseEventInternal7"));
-
   // There are cases where the code handling the message destroys the window,
   // so use the weak ptr to check if destruction occured or not.
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
   bool handled = delegate_->HandleMouseEvent(event);
 
-  // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-  tracked_objects::ScopedTracker tracking_profile8(
-      FROM_HERE_WITH_EXPLICIT_FUNCTION(
-          "440919 HWNDMessageHandler::HandleMouseEventInternal8"));
-
   if (!ref.get())
     return 0;
 
@@ -2714,11 +2384,6 @@
 
   if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU &&
       delegate_->IsUsingCustomFrame()) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile9(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal9"));
-
     // TODO(msw): Eliminate undesired painting, or re-evaluate this workaround.
     // DefWindowProc for WM_NCLBUTTONDOWN does weird non-client painting, so we
     // need to call it inside a ScopedRedrawLock. This may cause other negative
@@ -2727,14 +2392,8 @@
     handled = true;
   }
 
-  if (ref.get()) {
-    // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
-    tracked_objects::ScopedTracker tracking_profile10(
-        FROM_HERE_WITH_EXPLICIT_FUNCTION(
-            "440919 HWNDMessageHandler::HandleMouseEventInternal10"));
-
+  if (ref.get())
     SetMsgHandled(handled);
-  }
   return 0;
 }
 
diff --git a/ui/webui/resources/cr_elements/v1_0/network/cr_network_icon.js b/ui/webui/resources/cr_elements/v1_0/network/cr_network_icon.js
index c6bce8770..ed5eb56 100644
--- a/ui/webui/resources/cr_elements/v1_0/network/cr_network_icon.js
+++ b/ui/webui/resources/cr_elements/v1_0/network/cr_network_icon.js
@@ -53,12 +53,13 @@
 
   properties: {
     /**
-     * If set, the ONC state properties will be used to display the icon.
-     * @type {?CrOnc.NetworkStateProperties}
+     * If set, the ONC properties will be used to display the icon. This may
+     * either be the complete set of NetworkProperties or the subset of
+     * NetworkStateProperties.
+     * @type {!CrOnc.NetworkProperties|!CrOnc.NetworkStateProperties|undefined}
      */
     networkState: {
       type: Object,
-      value: null,
       observer: 'networkStateChanged_'
     },
 
@@ -120,7 +121,7 @@
     this.networkType = null;
     this.iconType_ = getIconTypeFromNetworkType(this.networkState.Type);
     var strength = /** @type {number} */ (
-        CrOnc.getTypeProperty(this.networkState, 'SignalStrength') || 0);
+        CrOnc.getActiveTypeValue(this.networkState, 'SignalStrength') || 0);
     var params = /** @type {NetworkIconParamType} */ {
       showBadges: true,
       showDisconnected: !this.isListItem,
@@ -138,7 +139,7 @@
     if (!this.networkType)
       return;
 
-    this.networkState = null;
+    this.networkState = undefined;
     this.iconType_ = getIconTypeFromNetworkType(this.networkType);
     var params = /** @type {NetworkIconParamType} */ {
       showBadges: false,
@@ -242,7 +243,7 @@
         (params.showBadges && networkState) ? networkState.Type : '';
     if (type == CrOnc.Type.WI_FI) {
       this.roaming_ = false;
-      var security = CrOnc.getTypeProperty(networkState, 'Security');
+      var security = CrOnc.getActiveTypeValue(networkState, 'Security');
       this.secure_ = !!security && security != 'None';
       this.technology_ = '';
     } else if (type == CrOnc.Type.WI_MAX) {
@@ -250,11 +251,11 @@
       this.secure_ = false;
       this.technology_ = '4g';
     } else if (type == CrOnc.Type.CELLULAR) {
-      this.roaming_ = CrOnc.getTypeProperty(networkState, 'RoamingState') ==
+      this.roaming_ = CrOnc.getActiveTypeValue(networkState, 'RoamingState') ==
                       CrOnc.RoamingState.ROAMING;
       this.secure_ = false;
       var oncTechnology =
-          CrOnc.getTypeProperty(networkState, 'NetworkTechnology');
+          CrOnc.getActiveTypeValue(networkState, 'NetworkTechnology');
       switch (oncTechnology) {
         case CrOnc.NetworkTechnology.CDMA1XRTT:
           this.technology_ = '1x';
diff --git a/ui/webui/resources/cr_elements/v1_0/network/cr_network_select.js b/ui/webui/resources/cr_elements/v1_0/network/cr_network_select.js
index e4c6a22..23ead1a 100644
--- a/ui/webui/resources/cr_elements/v1_0/network/cr_network_select.js
+++ b/ui/webui/resources/cr_elements/v1_0/network/cr_network_select.js
@@ -98,7 +98,7 @@
 
   /** @override */
   detached: function() {
-    chrome.networkingPrivate.onNetworksChanged.removeListener(
+    chrome.networkingPrivate.onNetworkListChanged.removeListener(
         this.networkListChangedListener_);
     chrome.networkingPrivate.onDeviceStateListChanged.removeListener(
         this.deviceStateListChangedListener_);
diff --git a/ui/webui/resources/cr_elements/v1_0/network/cr_onc_types.js b/ui/webui/resources/cr_elements/v1_0/network/cr_onc_types.js
index 873dee2..cca3371 100644
--- a/ui/webui/resources/cr_elements/v1_0/network/cr_onc_types.js
+++ b/ui/webui/resources/cr_elements/v1_0/network/cr_onc_types.js
@@ -20,33 +20,32 @@
 /** @typedef {chrome.networkingPrivate.NetworkStateProperties} */
 CrOnc.NetworkStateProperties;
 
+/** @typedef {chrome.networkingPrivate.NetworkProperties} */
+CrOnc.NetworkProperties;
+
 /** @typedef {string|number|boolean|Object|Array<Object>} */
-CrOnc.NetworkStateProperty;
+CrOnc.NetworkPropertyType;
 
 /**
+ * TODO(stevenjb): Eliminate this when we switch to using
+ * chrome.networkingPrivate.ManagedProperties once defined.
  * @typedef {{
- *   Active: CrOnc.NetworkStateProperty,
- *   Effective: CrOnc.NetworkStateProperty,
- *   UserPolicy: CrOnc.NetworkStateProperty,
- *   DevicePolicy: CrOnc.NetworkStateProperty,
- *   UserSetting: CrOnc.NetworkStateProperty,
- *   SharedSetting: CrOnc.NetworkStateProperty,
+ *   Active: CrOnc.NetworkPropertyType,
+ *   Effective: CrOnc.NetworkPropertyType,
+ *   UserPolicy: CrOnc.NetworkPropertyType,
+ *   DevicePolicy: CrOnc.NetworkPropertyType,
+ *   UserSetting: CrOnc.NetworkPropertyType,
+ *   SharedSetting: CrOnc.NetworkPropertyType,
  *   UserEditable: boolean,
  *   DeviceEditable: boolean
  * }}
  */
 CrOnc.ManagedProperty;
 
-/** @typedef {CrOnc.NetworkStateProperty|!CrOnc.ManagedProperty} */
+/** @typedef {CrOnc.NetworkPropertyType|!CrOnc.ManagedProperty} */
 CrOnc.ManagedNetworkStateProperty;
 
-/**
- * @typedef {{
- *   LockType: !CrOnc.LockType,
- *   LockEnabled: boolean,
- *   RetriesLeft: (number|undefined)
- * }}
- */
+/** @typedef {chrome.networkingPrivate.SIMLockStatus} */
 CrOnc.SIMLockStatus;
 
 /** @typedef {chrome.networkingPrivate.APNProperties} */
@@ -81,13 +80,7 @@
  */
 CrOnc.IPConfigUIProperties;
 
-/**
- * @typedef {{
- *   Method: string,
- *   PostData: (string|undefined),
- *   Url: string
- * }}
- */
+/** @typedef {chrome.networkingPrivate.PaymentPortal} */
 CrOnc.PaymentPortal;
 
 CrOnc.ActivationState = chrome.networkingPrivate.ActivationStateType;
@@ -152,15 +145,18 @@
 
 /**
  * Helper function to retrieve the active ONC property value.
- * @param {!CrOnc.ManagedNetworkStateProperty} property The property, which may
- *     be a managed dictionary or the property itself.
- * @return {!CrOnc.NetworkStateProperty|undefined} The active property value
+ * @param {!CrOnc.ManagedNetworkStateProperty|undefined} property The property,
+ *     which may be a managed dictionary or the property itself.
+ * @return {!CrOnc.NetworkPropertyType|undefined} The active property value
  *     if it exists, otherwise undefined.
  */
-CrOnc.getActivePropertyValue = function(property) {
+CrOnc.getActiveValue = function(property) {
+  if (property == undefined)
+    return undefined;
+
   // If this is not a dictionary, return the value.
   if (Array.isArray(property) || typeof property != 'object')
-    return /** @type {!CrOnc.NetworkStateProperty} */ (property);
+    return /** @type {!CrOnc.NetworkPropertyType} */ (property);
 
   // Otherwise return the Active value if it exists.
   if ('Active' in property)
@@ -173,91 +169,43 @@
       return property[effective];
   }
 
-  console.error('getActivePropertyValue called on invalid ONC object: ' +
-                property);
+  console.error('getActiveValue called on invalid ONC object: ' +
+                JSON.stringify(property));
   return undefined;
 };
 
 /**
- * Returns either a managed property dictionary or an unmanaged value associated
- * with a key. TODO(stevenjb): Remove this. Properties should be accessed
- * directly so that the closure compiler can do type checking. Removal is
- * dependent on adding a NetworkProperties type to the networking_private.js
- * externs file.
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
- * @param {string} key The property key which may be nested, e.g. 'Foo.Bar'.
- * @return {!CrOnc.ManagedNetworkStateProperty|undefined} The property value or
- *     dictionary if it exists, otherwise undefined.
- */
-CrOnc.getProperty = function(state, key) {
-  if (!state) {
-    console.error('CrOnc.getProperty called with undefined state');
-    return undefined;
-  }
-  while (true) {
-    var index = key.indexOf('.');
-    if (index < 0)
-      break;
-    var keyComponent = key.substr(0, index);
-    if (!state.hasOwnProperty(keyComponent))
-      return undefined;
-    state = state[keyComponent];
-    key = key.substr(index + 1);
-  }
-  return state[key];
-};
-
-/**
- * Calls getProperty with '{state.Type}.key', e.g. WiFi.AutoConnect.
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
- * @param {string} key The type property key, e.g. 'AutoConnect'.
- * @return {!CrOnc.ManagedNetworkStateProperty|undefined} The property value or
- *     dictionary if it exists, otherwise undefined.
- */
-CrOnc.getTypeProperty = function(state, key) {
-  var typeKey = state ? state.Type + '.' + key : '';
-  return CrOnc.getProperty(state, typeKey);
-};
-
-/**
- * Returns either the active value of a managed property dictionary or the
- * unmanaged value associated with a key.
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
- * @param {string} key The property key which may be nested, e.g. 'Foo.Bar'.
- * @return {!CrOnc.ManagedNetworkStateProperty|undefined} The active property
- *     value if it exists, otherwise undefined.
- */
-CrOnc.getActiveValue = function(state, key) {
-  var property = CrOnc.getProperty(state, key);
-  if (property == undefined)
-    return undefined;
-  return CrOnc.getActivePropertyValue(property);
-};
-
-/**
  * Calls getActiveValue with '{state.Type}.key', e.g. WiFi.AutoConnect.
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
+ * @param {!CrOnc.NetworkProperties|!CrOnc.NetworkStateProperties|undefined}
+ *     properties The ONC network properties or state properties.
  * @param {string} key The type property key, e.g. 'AutoConnect'.
- * @return {!CrOnc.ManagedNetworkStateProperty|undefined} The active property
- *     value if it exists, otherwise undefined.
+ * @return {!CrOnc.ManagedNetworkStateProperty|undefined} The property value or
+ *     dictionary if it exists, otherwise undefined.
  */
-CrOnc.getActiveTypeValue = function(state, key) {
-  var typeKey = state ? state.Type + '.' + key : '';
-  return CrOnc.getActiveValue(state, typeKey);
+CrOnc.getActiveTypeValue = function(properties, key) {
+  var typeDict = properties[properties.Type];
+  if (!typeDict) {
+    // An 'Ethernet' dictionary will only be present for EAP ethernet networks,
+    // so don't log an error when Type == Ethernet.
+    if (properties.Type != chrome.networkingPrivate.NetworkType.ETHERNET)
+      console.error('Network properties missing for:', properties.GUID);
+    return undefined;
+  }
+  return CrOnc.getActiveValue(typeDict[key]);
 };
 
 /**
  * Returns an IPConfigProperties object for |type|. For IPV4, these will be the
  * static properties if IPAddressConfigType is Static and StaticIPConfig is set.
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
+ * @param {!CrOnc.NetworkProperties|undefined} properties The ONC properties.
  * @param {!CrOnc.IPType} type The IP Config type.
- * @return {?CrOnc.IPConfigProperties} The IP Config object, or undefined if
- *     no properties for |type| are available.
+ * @return {CrOnc.IPConfigProperties|undefined} The IP Config object, or
+ *     undefined if no properties for |type| are available.
  */
-CrOnc.getIPConfigForType = function(state, type) {
+CrOnc.getIPConfigForType = function(properties, type) {
   'use strict';
   var result;
-  var ipConfigs = CrOnc.getActiveValue(state, 'IPConfigs');
+  var ipConfigs = properties.IPConfigs;
   if (ipConfigs) {
     for (let i = 0; i < ipConfigs.length; ++i) {
       let ipConfig = ipConfigs[i];
@@ -270,8 +218,7 @@
   if (type != CrOnc.IPType.IPV4)
     return result;
 
-  var staticIpConfig =
-      /** @type{CrOnc.IPConfigProperties} */ (state['StaticIPConfig']);
+  var staticIpConfig = properties.StaticIPConfig;
   if (!staticIpConfig)
     return result;
 
@@ -281,30 +228,33 @@
 
   // Otherwise, merge the appropriate static values into the result.
   if (staticIpConfig.IPAddress &&
-      CrOnc.getActiveValue(state, 'IPAddressConfigType') == 'Static') {
+      CrOnc.getActiveValue(properties.IPAddressConfigType) == 'Static') {
     result.Gateway = staticIpConfig.Gateway;
     result.IPAddress = staticIpConfig.IPAddress;
     result.RoutingPrefix = staticIpConfig.RoutingPrefix;
     result.Type = staticIpConfig.Type;
   }
   if (staticIpConfig.NameServers &&
-      CrOnc.getActiveValue(state, 'NameServersConfigType') == 'Static') {
+      CrOnc.getActiveValue(properties.NameServersConfigType) == 'Static') {
     result.NameServers = staticIpConfig.NameServers;
   }
   return result;
 };
 
 /**
- * @param {?CrOnc.NetworkStateProperties|undefined} state The ONC network state.
- * @return {boolean} True if |state| is a Cellular network with a locked SIM.
+ * @param {!CrOnc.NetworkProperties|!CrOnc.NetworkStateProperties|undefined}
+ *   properties The ONC network properties or state properties.
+ * @return {boolean} True if |properties| is a Cellular network with a
+ *   locked SIM.
  */
-CrOnc.isSimLocked = function(state) {
-  if (!state || state.Type != CrOnc.Type.CELLULAR)
+CrOnc.isSimLocked = function(properties) {
+  if (!properties.Cellular)
     return false;
-  var property = /** @type {!CrOnc.SIMLockStatus} */(
-      CrOnc.getProperty(state, 'Cellular.SIMLockStatus'));
-  return property != undefined && (property.LockType == CrOnc.LockType.PIN ||
-                                   property.LockType == CrOnc.LockType.PUK);
+  var simLockStatus = properties.Cellular.SIMLockStatus;
+  if (simLockStatus == undefined)
+    return false;
+  return simLockStatus.LockType == CrOnc.LockType.PIN ||
+         simLockStatus.LockType == CrOnc.LockType.PUK;
 };
 
 /**
@@ -313,17 +263,17 @@
  * properties in |config| will be preserved unless invalid.
  * @param {!chrome.networkingPrivate.NetworkConfigProperties} config A partial
  *     ONC configuration.
- * @param {!CrOnc.NetworkStateProperties} state The complete ONC network state.
+ * @param {CrOnc.NetworkProperties|undefined} properties The ONC properties.
  */
-CrOnc.setValidStaticIPConfig = function(config, state) {
+CrOnc.setValidStaticIPConfig = function(config, properties) {
   if (!config.IPAddressConfigType) {
     var ipConfigType = /** @type {chrome.networkingPrivate.IPConfigType} */(
-        CrOnc.getActiveValue(state, 'IPAddressConfigType'));
+        CrOnc.getActiveValue(properties.IPAddressConfigType));
     config.IPAddressConfigType = ipConfigType || CrOnc.IPConfigType.DHCP;
   }
   if (!config.NameServersConfigType) {
     var nsConfigType = /** @type {chrome.networkingPrivate.IPConfigType} */(
-        CrOnc.getActiveValue(state, 'NameServersConfigType'));
+        CrOnc.getActiveValue(properties.NameServersConfigType));
     config.NameServersConfigType = nsConfigType || CrOnc.IPConfigType.DHCP;
   }
   if (config.IPAddressConfigType != CrOnc.IPConfigType.STATIC &&
@@ -338,7 +288,7 @@
         /** @type {chrome.networkingPrivate.IPConfigProperties} */({});
   }
   var staticIP = config.StaticIPConfig;
-  var stateIPConfig = CrOnc.getIPConfigForType(state, CrOnc.IPType.IPV4);
+  var stateIPConfig = CrOnc.getIPConfigForType(properties, CrOnc.IPType.IPV4);
   if (config.IPAddressConfigType == 'Static') {
     staticIP.Gateway = staticIP.Gateway || stateIPConfig.Gateway || '';
     staticIP.IPAddress = staticIP.IPAddress || stateIPConfig.IPAddress || '';
@@ -356,8 +306,9 @@
 /**
  * Sets the value of a property in an ONC dictionary.
  * @param {!chrome.networkingPrivate.NetworkConfigProperties} properties
+ *     The ONC property dictionary to modify.
  * @param {string} key The property key which may be nested, e.g. 'Foo.Bar'.
- * @param {!CrOnc.NetworkStateProperty} value The property value to set.
+ * @param {!CrOnc.NetworkPropertyType} value The property value to set.
  */
 CrOnc.setProperty = function(properties, key, value) {
   while (true) {
@@ -378,7 +329,7 @@
  * @param {!chrome.networkingPrivate.NetworkConfigProperties} properties The
  *     ONC properties to set. properties.Type must be set already.
  * @param {string} key The type property key, e.g. 'AutoConnect'.
- * @param {!CrOnc.NetworkStateProperty} value The property value to set.
+ * @param {!CrOnc.NetworkPropertyType} value The property value to set.
  */
 CrOnc.setTypeProperty = function(properties, key, value) {
   if (properties.Type == undefined) {
diff --git a/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.html b/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.html
index 24418604..ea2ead1 100644
--- a/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.html
+++ b/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.html
@@ -10,7 +10,7 @@
       <iron-icon id="indicator"
           hidden$="[[!isIndicatorVisible_(indicatorType)]]"
           icon="[[getIcon_(indicatorType)]]"
-          title="[[getTooltipText_(indicatorType, pref)]]">
+          title$="[[getTooltipText_(indicatorType, pref, controllingUser)]]">
       </iron-icon>
     </div>
   </template>
diff --git a/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.js b/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.js
index d81c3aae..d9248c5 100644
--- a/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.js
+++ b/ui/webui/resources/cr_elements/v1_0/policy/cr_policy_indicator.js
@@ -7,35 +7,46 @@
  * element controlling a settings preference.
  */
 
-(function() {
-
-/** @enum {string} */
-var IndicatorType = {
-  DEVICE_POLICY: 'devicePolicy',
-  EXTENSION: 'extension',
-  NONE: 'none',
-  OWNER: 'owner',
-  PRIMARY_USER: 'primary_user',
-  RECOMMENDED: 'recommended',
-  USER_POLICY: 'userPolicy',
+var CrPolicyIndicator = {
+  /** @enum {string} */
+  Type: {
+    DEVICE_POLICY: 'devicePolicy',
+    EXTENSION: 'extension',
+    NONE: 'none',
+    OWNER: 'owner',
+    PRIMARY_USER: 'primary_user',
+    RECOMMENDED: 'recommended',
+    USER_POLICY: 'userPolicy',
+  },
 };
 
+(function() {
+
 /** @element cr-policy-indicator */
 Polymer({
   is: 'cr-policy-indicator',
 
   properties: {
     /**
-     * The preference object to show an indicator for.
-     * @type {chrome.settingsPrivate.PrefObject|undefined}
+     * Optional preference object associated with the indicator. Initialized to
+     * null so that computed functions will get called if this is never set.
+     * @type {?chrome.settingsPrivate.PrefObject}
      */
-    pref: {type: Object},
+    pref: {type: Object, value: null},
+
+    /**
+     * Optional email of the user controlling the setting when the setting does
+     * not correspond to a pref (Chrome OS only). Only used when pref is null.
+     * Initialized to '' so that computed functions will get called if this is
+     * never set.
+     */
+    controllingUser: {type: String, value: ''},
 
     /**
      * Which indicator type to show (or NONE).
-     * @type {IndicatorType}
+     * @type {CrPolicyIndicator.Type}
      */
-    indicatorType: {type: String, value: IndicatorType.NONE},
+    indicatorType: {type: String, value: CrPolicyIndicator.Type.NONE},
   },
 
   observers: ['prefPolicyChanged_(pref.policySource, pref.policyEnforcement)'],
@@ -47,51 +58,53 @@
    * @private
    */
   prefPolicyChanged_: function(source, enforcement) {
-    var type = IndicatorType.NONE;
+    var type = CrPolicyIndicator.Type.NONE;
     if (enforcement == chrome.settingsPrivate.PolicyEnforcement.ENFORCED) {
       if (source == chrome.settingsPrivate.PolicySource.PRIMARY_USER)
-        type = IndicatorType.PRIMARY_USER;
+        type = CrPolicyIndicator.Type.PRIMARY_USER;
       else if (source == chrome.settingsPrivate.PolicySource.OWNER)
-        type = IndicatorType.OWNER;
+        type = CrPolicyIndicator.Type.OWNER;
       else if (source == chrome.settingsPrivate.PolicySource.USER_POLICY)
-        type = IndicatorType.USER_POLICY;
+        type = CrPolicyIndicator.Type.USER_POLICY;
       else if (source == chrome.settingsPrivate.PolicySource.DEVICE_POLICY)
-        type = IndicatorType.DEVICE_POLICY;
+        type = CrPolicyIndicator.Type.DEVICE_POLICY;
       else if (source == chrome.settingsPrivate.PolicySource.EXTENSION)
-        type = IndicatorType.EXTENSION;
+        type = CrPolicyIndicator.Type.EXTENSION;
     } else if (enforcement ==
                chrome.settingsPrivate.PolicyEnforcement.RECOMMENDED) {
-      type = IndicatorType.RECOMMENDED;
+      type = CrPolicyIndicator.Type.RECOMMENDED;
     }
     this.indicatorType = type;
   },
 
   /**
-   * @param {IndicatorType} type
+   * @param {CrPolicyIndicator.Type} type
    * @return {boolean} True if the indicator should be shown.
    * @private
    */
-  isIndicatorVisible_: function(type) { return type != IndicatorType.NONE; },
+  isIndicatorVisible_: function(type) {
+    return type != CrPolicyIndicator.Type.NONE;
+  },
 
   /**
-   * @param {IndicatorType} type
+   * @param {CrPolicyIndicator.Type} type
    * @return {string} The iron-icons icon name.
    * @private
    */
   getIcon_: function(type) {
     switch (type) {
-      case IndicatorType.NONE:
+      case CrPolicyIndicator.Type.NONE:
         return '';
-      case IndicatorType.PRIMARY_USER:
+      case CrPolicyIndicator.Type.PRIMARY_USER:
         return 'social:group';
-      case IndicatorType.OWNER:
+      case CrPolicyIndicator.Type.OWNER:
         return 'social:person';
-      case IndicatorType.USER_POLICY:
-      case IndicatorType.DEVICE_POLICY:
+      case CrPolicyIndicator.Type.USER_POLICY:
+      case CrPolicyIndicator.Type.DEVICE_POLICY:
         return 'social:domain';
-      case IndicatorType.EXTENSION:
+      case CrPolicyIndicator.Type.EXTENSION:
         return 'extension';
-      case IndicatorType.RECOMMENDED:
+      case CrPolicyIndicator.Type.RECOMMENDED:
         return 'social:domain';
     }
     assertNotReached();
@@ -107,25 +120,28 @@
   },
 
   /**
-   * @param {IndicatorType} type The type of indicator.
-   * @param {!chrome.settingsPrivate.PrefObject} pref
+   * @param {CrPolicyIndicator.Type} type The type of indicator.
+   * @param {?chrome.settingsPrivate.PrefObject} pref
+   * @param {string} controllingUser The user controlling the setting, if |pref|
+   *     is null.
    * @return {string} The tooltip text for |type|.
    * @private
    */
-  getTooltipText_: function(type, pref) {
-    var name = pref.policySourceName || '';
+  getTooltipText_: function(type, pref, controllingUser) {
+    var name = pref ? pref.policySourceName : controllingUser;
+
     switch (type) {
-      case IndicatorType.PRIMARY_USER:
+      case CrPolicyIndicator.Type.PRIMARY_USER:
         return this.i18n_('controlledSettingShared', name);
-      case IndicatorType.OWNER:
+      case CrPolicyIndicator.Type.OWNER:
         return this.i18n_('controlledSettingOwner', name);
-      case IndicatorType.USER_POLICY:
-      case IndicatorType.DEVICE_POLICY:
+      case CrPolicyIndicator.Type.USER_POLICY:
+      case CrPolicyIndicator.Type.DEVICE_POLICY:
         return this.i18n_('controlledSettingPolicy');
-      case IndicatorType.EXTENSION:
+      case CrPolicyIndicator.Type.EXTENSION:
         return this.i18n_('controlledSettingExtension', name);
-      case IndicatorType.RECOMMENDED:
-        if (pref.value == pref.recommendedValue)
+      case CrPolicyIndicator.Type.RECOMMENDED:
+        if (pref && pref.value == pref.recommendedValue)
           return this.i18n_('controlledSettingRecommendedMatches');
         return this.i18n_('controlledSettingRecommendedDiffers');
     }
diff --git a/ui/webui/resources/html/chromeos/ui_account_tweaks.html b/ui/webui/resources/html/chromeos/ui_account_tweaks.html
new file mode 100644
index 0000000..10b6db6
--- /dev/null
+++ b/ui/webui/resources/html/chromeos/ui_account_tweaks.html
@@ -0,0 +1 @@
+<script src="chrome://resources/js/chromeos/ui_account_tweaks.js"></script>
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd
index 8a84b147..50af42a 100644
--- a/ui/webui/resources/webui_resources.grd
+++ b/ui/webui/resources/webui_resources.grd
@@ -430,6 +430,9 @@
         <structure name="IDR_WEBUI_CSS_UI_ACCOUNT_TWEAKS"
                    file="css/chromeos/ui_account_tweaks.css"
                    type="chrome_html" />
+        <structure name="IDR_WEBUI_HTML_UI_ACCOUNT_TWEAKS"
+                   file="html/chromeos/ui_account_tweaks.html"
+                   type="chrome_html" />
         <structure name="IDR_WEBUI_JS_UI_ACCOUNT_TWEAKS"
                    file="js/chromeos/ui_account_tweaks.js"
                    type="chrome_html" />
diff --git a/win8/metro_driver/metro_driver_win7.cc b/win8/metro_driver/metro_driver_win7.cc
index 3ace04ca..c88cd3f 100644
--- a/win8/metro_driver/metro_driver_win7.cc
+++ b/win8/metro_driver/metro_driver_win7.cc
@@ -7,7 +7,6 @@
 #include <shobjidl.h>
 
 #include "base/logging.h"
-#include "base/profiler/scoped_tracker.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/win/msg_util.h"